X-Git-Url: http://git.lttng.org/?a=blobdiff_plain;f=src%2Flib%2Flttng-ust-ctl%2Fustctl.c;h=6faaef5ed44ff4fcc88a31b181ddd511c3f87cce;hb=a616fb4e0a0245ae2cbd4614910480df19aa23d6;hp=86e37f1816a660881b225f9742ec13c9d296ae4d;hpb=f41a6b5f307db311352f79d35f0656959db60891;p=lttng-ust.git diff --git a/src/lib/lttng-ust-ctl/ustctl.c b/src/lib/lttng-ust-ctl/ustctl.c index 86e37f18..6faaef5e 100644 --- a/src/lib/lttng-ust-ctl/ustctl.c +++ b/src/lib/lttng-ust-ctl/ustctl.c @@ -1,7 +1,7 @@ /* * SPDX-License-Identifier: GPL-2.0-only * - * Copyright (C) 2011 Julien Desfossez + * Copyright (C) 2011 EfficiOS Inc. * Copyright (C) 2011-2013 Mathieu Desnoyers */ @@ -17,6 +17,8 @@ #include #include #include +#include +#include #include "common/logging.h" #include "common/ustcomm.h" @@ -27,10 +29,10 @@ #include "common/ringbuffer/frontend.h" #include "common/events.h" #include "common/wait.h" -#include "lib/lttng-ust/lttng-rb-clients.h" +#include "common/ringbuffer-clients/clients.h" #include "common/getenv.h" -#include "lib/lttng-ust/lttng-tracer-core.h" -#include "lib/lttng-ust/lttng-counter-client.h" +#include "common/tracer.h" +#include "common/counter-clients/clients.h" #include "common/smp.h" #include "common/counter/counter.h" @@ -62,6 +64,7 @@ struct lttng_ust_ctl_consumer_stream { int shm_fd, wait_fd, wakeup_fd; int cpu; uint64_t memory_map_size; + void *memory_map_addr; }; #define LTTNG_UST_CTL_COUNTER_ATTR_DIMENSION_MAX 8 @@ -83,6 +86,67 @@ struct lttng_ust_ctl_daemon_counter { struct lttng_ust_ctl_counter_attr *attr; /* initial attributes */ }; +/* + * Evaluates to false if transaction begins, true if it has failed due to SIGBUS. + * The entire transaction must complete before the current function returns. + * A transaction can contain 0 or more tracked ranges as sigbus begin/end pairs. + */ +#define sigbus_begin() \ +({ \ + assert(!lttng_ust_sigbus_state.jmp_ready); \ + if (!lttng_ust_sigbus_state.head.next) { \ + /* \ + * Lazy init because static list initialisation is \ + * problematic for TLS variable. \ + */ \ + CDS_INIT_LIST_HEAD(<tng_ust_sigbus_state.head); \ + } \ + if (sigsetjmp(lttng_ust_sigbus_state.sj_env, 1)) { \ + /* SIGBUS. */ \ + CMM_STORE_SHARED(lttng_ust_sigbus_state.jmp_ready, 0); \ + true; \ + } \ + cmm_barrier(); \ + CMM_STORE_SHARED(lttng_ust_sigbus_state.jmp_ready, 1); \ + false; \ +}) + +static void sigbus_end(void) +{ + assert(lttng_ust_sigbus_state.jmp_ready); + cmm_barrier(); + CMM_STORE_SHARED(lttng_ust_sigbus_state.jmp_ready, 0); +} + +static +void lttng_ust_sigbus_add_range(struct lttng_ust_sigbus_range *range, void *start, size_t len) +{ + range->start = start; + range->end = (char *)start + len; + cds_list_add_rcu(&range->node, <tng_ust_sigbus_state.head); + cmm_barrier(); +} + +static +void lttng_ust_sigbus_del_range(struct lttng_ust_sigbus_range *range) +{ + cmm_barrier(); + cds_list_del_rcu(&range->node); +} + +void lttng_ust_ctl_sigbus_handle(void *addr) +{ + struct lttng_ust_sigbus_range *range; + + if (!CMM_LOAD_SHARED(lttng_ust_sigbus_state.jmp_ready)) + return; + cds_list_for_each_entry_rcu(range, <tng_ust_sigbus_state.head, node) { + if (addr < range->start || addr >= range->end) + continue; + siglongjmp(lttng_ust_sigbus_state.sj_env, 1); + } +} + int lttng_ust_ctl_release_handle(int sock, int handle) { struct ustcomm_ust_msg lum; @@ -248,6 +312,17 @@ int lttng_ust_ctl_create_event(int sock, struct lttng_ust_abi_event *ev, return 0; } +/* + * Protocol for LTTNG_UST_ABI_CONTEXT command: + * + * - send: struct ustcomm_ust_msg + * - send: var len ctx_name + * - receive: struct ustcomm_ust_reply + * + * TODO: At the next breaking protocol bump, we should indicate the total + * command message length as part of a message header so that the protocol can + * recover from invalid command errors. + */ int lttng_ust_ctl_add_context(int sock, struct lttng_ust_context_attr *ctx, struct lttng_ust_abi_object_data *obj_data, struct lttng_ust_abi_object_data **_context_data) @@ -319,6 +394,13 @@ int lttng_ust_ctl_add_context(int sock, struct lttng_ust_context_attr *ctx, } ret = ustcomm_recv_app_reply(sock, &lur, lum.handle, lum.cmd); if (ret < 0) { + if (ret == -EINVAL) { + /* + * Command unknown from remote end. The communication socket is + * now out-of-sync and needs to be shutdown. + */ + (void) ustcomm_shutdown_unix_sock(sock); + } goto end; } context_data->handle = -1; @@ -331,6 +413,17 @@ end: return ret; } +/* + * Protocol for LTTNG_UST_ABI_FILTER command: + * + * - send: struct ustcomm_ust_msg + * - send: var len bytecode + * - receive: struct ustcomm_ust_reply + * + * TODO: At the next breaking protocol bump, we should indicate the total + * command message length as part of a message header so that the protocol can + * recover from invalid command errors. + */ int lttng_ust_ctl_set_filter(int sock, struct lttng_ust_abi_filter_bytecode *bytecode, struct lttng_ust_abi_object_data *obj_data) { @@ -359,9 +452,25 @@ int lttng_ust_ctl_set_filter(int sock, struct lttng_ust_abi_filter_bytecode *byt } if (ret != bytecode->len) return -EINVAL; - return ustcomm_recv_app_reply(sock, &lur, lum.handle, lum.cmd); + ret = ustcomm_recv_app_reply(sock, &lur, lum.handle, lum.cmd); + if (ret == -EINVAL) { + /* + * Command unknown from remote end. The communication socket is + * now out-of-sync and needs to be shutdown. + */ + (void) ustcomm_shutdown_unix_sock(sock); + } + return ret; } +/* + * Protocol for LTTNG_UST_ABI_CAPTURE command: + * + * - send: struct ustcomm_ust_msg + * - receive: struct ustcomm_ust_reply + * - send: var len bytecode + * - receive: struct ustcomm_ust_reply (actual command return code) + */ int lttng_ust_ctl_set_capture(int sock, struct lttng_ust_abi_capture_bytecode *bytecode, struct lttng_ust_abi_object_data *obj_data) { @@ -379,7 +488,7 @@ int lttng_ust_ctl_set_capture(int sock, struct lttng_ust_abi_capture_bytecode *b lum.u.capture.reloc_offset = bytecode->reloc_offset; lum.u.capture.seqnum = bytecode->seqnum; - ret = ustcomm_send_app_msg(sock, &lum); + ret = ustcomm_send_app_cmd(sock, &lum, &lur); if (ret) return ret; /* send var len bytecode */ @@ -393,6 +502,17 @@ int lttng_ust_ctl_set_capture(int sock, struct lttng_ust_abi_capture_bytecode *b return ustcomm_recv_app_reply(sock, &lur, lum.handle, lum.cmd); } +/* + * Protocol for LTTNG_UST_ABI_EXCLUSION command: + * + * - send: struct ustcomm_ust_msg + * - send: var len exclusion names + * - receive: struct ustcomm_ust_reply + * + * TODO: At the next breaking protocol bump, we should indicate the total + * command message length as part of a message header so that the protocol can + * recover from invalid command errors. + */ int lttng_ust_ctl_set_exclusion(int sock, struct lttng_ust_abi_event_exclusion *exclusion, struct lttng_ust_abi_object_data *obj_data) { @@ -424,7 +544,15 @@ int lttng_ust_ctl_set_exclusion(int sock, struct lttng_ust_abi_event_exclusion * if (ret != exclusion->count * LTTNG_UST_ABI_SYM_NAME_LEN) { return -EINVAL; } - return ustcomm_recv_app_reply(sock, &lur, lum.handle, lum.cmd); + ret = ustcomm_recv_app_reply(sock, &lur, lum.handle, lum.cmd); + if (ret == -EINVAL) { + /* + * Command unknown from remote end. The communication socket is + * now out-of-sync and needs to be shutdown. + */ + (void) ustcomm_shutdown_unix_sock(sock); + } + return ret; } /* Enable event, channel and session ioctl */ @@ -483,6 +611,14 @@ int lttng_ust_ctl_stop_session(int sock, int handle) return lttng_ust_ctl_disable(sock, &obj); } +/* + * Protocol for LTTNG_UST_ABI_EVENT_NOTIFIER_GROUP_CREATE command: + * + * - send: struct ustcomm_ust_msg + * - receive: struct ustcomm_ust_reply + * - send: file descriptor + * - receive: struct ustcomm_ust_reply (actual command return code) + */ int lttng_ust_ctl_create_event_notifier_group(int sock, int pipe_fd, struct lttng_ust_abi_object_data **_event_notifier_group_data) { @@ -505,7 +641,7 @@ int lttng_ust_ctl_create_event_notifier_group(int sock, int pipe_fd, lum.handle = LTTNG_UST_ABI_ROOT_HANDLE; lum.cmd = LTTNG_UST_ABI_EVENT_NOTIFIER_GROUP_CREATE; - ret = ustcomm_send_app_msg(sock, &lum); + ret = ustcomm_send_app_cmd(sock, &lum, &lur); if (ret) goto error; @@ -534,6 +670,14 @@ end: return ret; } +/* + * Protocol for LTTNG_UST_ABI_EVENT_NOTIFIER_CREATE command: + * + * - send: struct ustcomm_ust_msg + * - receive: struct ustcomm_ust_reply + * - send: struct lttng_ust_abi_event_notifier + * - receive: struct ustcomm_ust_reply (actual command return code) + */ int lttng_ust_ctl_create_event_notifier(int sock, struct lttng_ust_abi_event_notifier *event_notifier, struct lttng_ust_abi_object_data *event_notifier_group, struct lttng_ust_abi_object_data **_event_notifier_data) @@ -558,7 +702,7 @@ int lttng_ust_ctl_create_event_notifier(int sock, struct lttng_ust_abi_event_not lum.cmd = LTTNG_UST_ABI_EVENT_NOTIFIER_CREATE; lum.u.event_notifier.len = sizeof(*event_notifier); - ret = ustcomm_send_app_msg(sock, &lum); + ret = ustcomm_send_app_cmd(sock, &lum, &lur); if (ret) { free(event_notifier_data); return ret; @@ -984,6 +1128,17 @@ error_alloc: return ret; } +/* + * Protocol for LTTNG_UST_ABI_CHANNEL command: + * + * - send: struct ustcomm_ust_msg + * - send: file descriptors and channel data + * - receive: struct ustcomm_ust_reply + * + * TODO: At the next breaking protocol bump, we should indicate the total + * command message length as part of a message header so that the protocol can + * recover from invalid command errors. + */ int lttng_ust_ctl_send_channel_to_ust(int sock, int session_handle, struct lttng_ust_abi_object_data *channel_data) { @@ -1014,10 +1169,27 @@ int lttng_ust_ctl_send_channel_to_ust(int sock, int session_handle, ret = ustcomm_recv_app_reply(sock, &lur, lum.handle, lum.cmd); if (!ret) { channel_data->handle = lur.ret_val; + } else if (ret == -EINVAL) { + /* + * Command unknown from remote end. The communication socket is + * now out-of-sync and needs to be shutdown. + */ + (void) ustcomm_shutdown_unix_sock(sock); } return ret; } +/* + * Protocol for LTTNG_UST_ABI_STREAM command: + * + * - send: struct ustcomm_ust_msg + * - send: file descriptors and stream data + * - receive: struct ustcomm_ust_reply + * + * TODO: At the next breaking protocol bump, we should indicate the total + * command message length as part of a message header so that the protocol can + * recover from invalid command errors. + */ int lttng_ust_ctl_send_stream_to_ust(int sock, struct lttng_ust_abi_object_data *channel_data, struct lttng_ust_abi_object_data *stream_data) @@ -1045,7 +1217,15 @@ int lttng_ust_ctl_send_stream_to_ust(int sock, stream_data->u.stream.wakeup_fd, 1); if (ret) return ret; - return ustcomm_recv_app_reply(sock, &lur, lum.handle, lum.cmd); + ret = ustcomm_recv_app_reply(sock, &lur, lum.handle, lum.cmd); + if (ret == -EINVAL) { + /* + * Command unknown from remote end. The communication socket is + * now out-of-sync and needs to be shutdown. + */ + (void) ustcomm_shutdown_unix_sock(sock); + } + return ret; } int lttng_ust_ctl_duplicate_ust_object_data(struct lttng_ust_abi_object_data **dest, @@ -1077,7 +1257,7 @@ int lttng_ust_ctl_duplicate_ust_object_data(struct lttng_ust_abi_object_data **d obj->u.channel.wakeup_fd = dup(src->u.channel.wakeup_fd); if (obj->u.channel.wakeup_fd < 0) { - ret = errno; + ret = -errno; goto chan_error_wakeup_fd; } } else { @@ -1113,7 +1293,7 @@ int lttng_ust_ctl_duplicate_ust_object_data(struct lttng_ust_abi_object_data **d obj->u.stream.wakeup_fd = dup(src->u.stream.wakeup_fd); if (obj->u.stream.wakeup_fd < 0) { - ret = errno; + ret = -errno; goto stream_error_wakeup_fd; } } else { @@ -1125,7 +1305,7 @@ int lttng_ust_ctl_duplicate_ust_object_data(struct lttng_ust_abi_object_data **d obj->u.stream.shm_fd = dup(src->u.stream.shm_fd); if (obj->u.stream.shm_fd < 0) { - ret = errno; + ret = -errno; goto stream_error_shm_fd; } } else { @@ -1164,7 +1344,7 @@ int lttng_ust_ctl_duplicate_ust_object_data(struct lttng_ust_abi_object_data **d obj->u.counter_global.shm_fd = dup(src->u.counter_global.shm_fd); if (obj->u.counter_global.shm_fd < 0) { - ret = errno; + ret = -errno; goto error_type; } } @@ -1178,7 +1358,7 @@ int lttng_ust_ctl_duplicate_ust_object_data(struct lttng_ust_abi_object_data **d obj->u.counter_cpu.shm_fd = dup(src->u.counter_cpu.shm_fd); if (obj->u.counter_cpu.shm_fd < 0) { - ret = errno; + ret = -errno; goto error_type; } } @@ -1204,7 +1384,7 @@ error: int lttng_ust_ctl_get_nr_stream_per_channel(void) { - return num_possible_cpus(); + return get_possible_cpus_array_len(); } struct lttng_ust_ctl_consumer_channel * @@ -1446,6 +1626,7 @@ struct lttng_ust_ctl_consumer_stream * struct lttng_ust_ring_buffer_channel *rb_chan; int shm_fd, wait_fd, wakeup_fd; uint64_t memory_map_size; + void *memory_map_addr; struct lttng_ust_ring_buffer *buf; int ret; @@ -1458,7 +1639,7 @@ struct lttng_ust_ctl_consumer_stream * buf = channel_get_ring_buffer(&rb_chan->backend.config, rb_chan, cpu, handle, &shm_fd, &wait_fd, - &wakeup_fd, &memory_map_size); + &wakeup_fd, &memory_map_size, &memory_map_addr); if (!buf) return NULL; ret = lib_ring_buffer_open_read(buf, handle); @@ -1474,6 +1655,7 @@ struct lttng_ust_ctl_consumer_stream * stream->wait_fd = wait_fd; stream->wakeup_fd = wakeup_fd; stream->memory_map_size = memory_map_size; + stream->memory_map_addr = memory_map_addr; stream->cpu = cpu; return stream; @@ -1541,12 +1723,21 @@ void *lttng_ust_ctl_get_mmap_base(struct lttng_ust_ctl_consumer_stream *stream) { struct lttng_ust_ring_buffer *buf; struct lttng_ust_ctl_consumer_channel *consumer_chan; + struct lttng_ust_sigbus_range range; + void *p; if (!stream) return NULL; buf = stream->buf; consumer_chan = stream->chan; - return shmp(consumer_chan->chan->priv->rb_chan->handle, buf->backend.memory_map); + if (sigbus_begin()) + return NULL; + lttng_ust_sigbus_add_range(&range, stream->memory_map_addr, + stream->memory_map_size); + p = shmp(consumer_chan->chan->priv->rb_chan->handle, buf->backend.memory_map); + lttng_ust_sigbus_del_range(&range); + sigbus_end(); + return p; /* Users of this pointer should check for sigbus. */ } /* returns the length to mmap. */ @@ -1602,6 +1793,8 @@ int lttng_ust_ctl_get_mmap_read_offset(struct lttng_ust_ctl_consumer_stream *str struct lttng_ust_ctl_consumer_channel *consumer_chan; struct lttng_ust_ring_buffer_backend_pages_shmp *barray_idx; struct lttng_ust_ring_buffer_backend_pages *pages; + struct lttng_ust_sigbus_range range; + int ret; if (!stream) return -EINVAL; @@ -1610,17 +1803,31 @@ int lttng_ust_ctl_get_mmap_read_offset(struct lttng_ust_ctl_consumer_stream *str rb_chan = consumer_chan->chan->priv->rb_chan; if (rb_chan->backend.config.output != RING_BUFFER_MMAP) return -EINVAL; + + if (sigbus_begin()) + return -EIO; + ret = 0; + lttng_ust_sigbus_add_range(&range, stream->memory_map_addr, + stream->memory_map_size); + sb_bindex = subbuffer_id_get_index(&rb_chan->backend.config, buf->backend.buf_rsb.id); barray_idx = shmp_index(rb_chan->handle, buf->backend.array, sb_bindex); - if (!barray_idx) - return -EINVAL; + if (!barray_idx) { + ret = -EINVAL; + goto end; + } pages = shmp(rb_chan->handle, barray_idx->shmp); - if (!pages) - return -EINVAL; + if (!pages) { + ret = -EINVAL; + goto end; + } *off = pages->mmap_offset; - return 0; +end: + lttng_ust_sigbus_del_range(&range); + sigbus_end(); + return ret; } /* returns the size of the current sub-buffer, without padding (for mmap). */ @@ -1630,6 +1837,7 @@ int lttng_ust_ctl_get_subbuf_size(struct lttng_ust_ctl_consumer_stream *stream, struct lttng_ust_ctl_consumer_channel *consumer_chan; struct lttng_ust_ring_buffer_channel *rb_chan; struct lttng_ust_ring_buffer *buf; + struct lttng_ust_sigbus_range range; if (!stream) return -EINVAL; @@ -1637,8 +1845,14 @@ int lttng_ust_ctl_get_subbuf_size(struct lttng_ust_ctl_consumer_stream *stream, buf = stream->buf; consumer_chan = stream->chan; rb_chan = consumer_chan->chan->priv->rb_chan; + if (sigbus_begin()) + return -EIO; + lttng_ust_sigbus_add_range(&range, stream->memory_map_addr, + stream->memory_map_size); *len = lib_ring_buffer_get_read_data_size(&rb_chan->backend.config, buf, rb_chan->handle); + lttng_ust_sigbus_del_range(&range); + sigbus_end(); return 0; } @@ -1649,15 +1863,22 @@ int lttng_ust_ctl_get_padded_subbuf_size(struct lttng_ust_ctl_consumer_stream *s struct lttng_ust_ctl_consumer_channel *consumer_chan; struct lttng_ust_ring_buffer_channel *rb_chan; struct lttng_ust_ring_buffer *buf; + struct lttng_ust_sigbus_range range; if (!stream) return -EINVAL; buf = stream->buf; consumer_chan = stream->chan; rb_chan = consumer_chan->chan->priv->rb_chan; + if (sigbus_begin()) + return -EIO; + lttng_ust_sigbus_add_range(&range, stream->memory_map_addr, + stream->memory_map_size); *len = lib_ring_buffer_get_read_data_size(&rb_chan->backend.config, buf, rb_chan->handle); *len = LTTNG_UST_PAGE_ALIGN(*len); + lttng_ust_sigbus_del_range(&range); + sigbus_end(); return 0; } @@ -1666,27 +1887,42 @@ int lttng_ust_ctl_get_next_subbuf(struct lttng_ust_ctl_consumer_stream *stream) { struct lttng_ust_ring_buffer *buf; struct lttng_ust_ctl_consumer_channel *consumer_chan; + struct lttng_ust_sigbus_range range; + int ret; if (!stream) return -EINVAL; buf = stream->buf; consumer_chan = stream->chan; - return lib_ring_buffer_get_next_subbuf(buf, + if (sigbus_begin()) + return -EIO; + lttng_ust_sigbus_add_range(&range, stream->memory_map_addr, + stream->memory_map_size); + ret = lib_ring_buffer_get_next_subbuf(buf, consumer_chan->chan->priv->rb_chan->handle); + lttng_ust_sigbus_del_range(&range); + sigbus_end(); + return ret; } - /* Release exclusive sub-buffer access, move consumer forward. */ int lttng_ust_ctl_put_next_subbuf(struct lttng_ust_ctl_consumer_stream *stream) { struct lttng_ust_ring_buffer *buf; struct lttng_ust_ctl_consumer_channel *consumer_chan; + struct lttng_ust_sigbus_range range; if (!stream) return -EINVAL; buf = stream->buf; consumer_chan = stream->chan; + if (sigbus_begin()) + return -EIO; + lttng_ust_sigbus_add_range(&range, stream->memory_map_addr, + stream->memory_map_size); lib_ring_buffer_put_next_subbuf(buf, consumer_chan->chan->priv->rb_chan->handle); + lttng_ust_sigbus_del_range(&range); + sigbus_end(); return 0; } @@ -1697,13 +1933,22 @@ int lttng_ust_ctl_snapshot(struct lttng_ust_ctl_consumer_stream *stream) { struct lttng_ust_ring_buffer *buf; struct lttng_ust_ctl_consumer_channel *consumer_chan; + struct lttng_ust_sigbus_range range; + int ret; if (!stream) return -EINVAL; buf = stream->buf; consumer_chan = stream->chan; - return lib_ring_buffer_snapshot(buf, &buf->cons_snapshot, + if (sigbus_begin()) + return -EIO; + lttng_ust_sigbus_add_range(&range, stream->memory_map_addr, + stream->memory_map_size); + ret = lib_ring_buffer_snapshot(buf, &buf->cons_snapshot, &buf->prod_snapshot, consumer_chan->chan->priv->rb_chan->handle); + lttng_ust_sigbus_del_range(&range); + sigbus_end(); + return ret; } /* @@ -1715,14 +1960,23 @@ int lttng_ust_ctl_snapshot_sample_positions(struct lttng_ust_ctl_consumer_stream { struct lttng_ust_ring_buffer *buf; struct lttng_ust_ctl_consumer_channel *consumer_chan; + struct lttng_ust_sigbus_range range; + int ret; if (!stream) return -EINVAL; buf = stream->buf; consumer_chan = stream->chan; - return lib_ring_buffer_snapshot_sample_positions(buf, + if (sigbus_begin()) + return -EIO; + lttng_ust_sigbus_add_range(&range, stream->memory_map_addr, + stream->memory_map_size); + ret = lib_ring_buffer_snapshot_sample_positions(buf, &buf->cons_snapshot, &buf->prod_snapshot, consumer_chan->chan->priv->rb_chan->handle); + lttng_ust_sigbus_del_range(&range); + sigbus_end(); + return ret; } /* Get the consumer position (iteration start) */ @@ -1757,13 +2011,22 @@ int lttng_ust_ctl_get_subbuf(struct lttng_ust_ctl_consumer_stream *stream, { struct lttng_ust_ring_buffer *buf; struct lttng_ust_ctl_consumer_channel *consumer_chan; + struct lttng_ust_sigbus_range range; + int ret; if (!stream) return -EINVAL; buf = stream->buf; consumer_chan = stream->chan; - return lib_ring_buffer_get_subbuf(buf, *pos, + if (sigbus_begin()) + return -EIO; + lttng_ust_sigbus_add_range(&range, stream->memory_map_addr, + stream->memory_map_size); + ret = lib_ring_buffer_get_subbuf(buf, *pos, consumer_chan->chan->priv->rb_chan->handle); + lttng_ust_sigbus_del_range(&range); + sigbus_end(); + return ret; } /* Release exclusive sub-buffer access */ @@ -1771,40 +2034,63 @@ int lttng_ust_ctl_put_subbuf(struct lttng_ust_ctl_consumer_stream *stream) { struct lttng_ust_ring_buffer *buf; struct lttng_ust_ctl_consumer_channel *consumer_chan; + struct lttng_ust_sigbus_range range; if (!stream) return -EINVAL; buf = stream->buf; consumer_chan = stream->chan; + if (sigbus_begin()) + return -EIO; + lttng_ust_sigbus_add_range(&range, stream->memory_map_addr, + stream->memory_map_size); lib_ring_buffer_put_subbuf(buf, consumer_chan->chan->priv->rb_chan->handle); + lttng_ust_sigbus_del_range(&range); + sigbus_end(); return 0; } -void lttng_ust_ctl_flush_buffer(struct lttng_ust_ctl_consumer_stream *stream, +int lttng_ust_ctl_flush_buffer(struct lttng_ust_ctl_consumer_stream *stream, int producer_active) { struct lttng_ust_ring_buffer *buf; struct lttng_ust_ctl_consumer_channel *consumer_chan; + struct lttng_ust_sigbus_range range; assert(stream); buf = stream->buf; consumer_chan = stream->chan; + if (sigbus_begin()) + return -EIO; + lttng_ust_sigbus_add_range(&range, stream->memory_map_addr, + stream->memory_map_size); lib_ring_buffer_switch_slow(buf, producer_active ? SWITCH_ACTIVE : SWITCH_FLUSH, consumer_chan->chan->priv->rb_chan->handle); + lttng_ust_sigbus_del_range(&range); + sigbus_end(); + return 0; } -void lttng_ust_ctl_clear_buffer(struct lttng_ust_ctl_consumer_stream *stream) +int lttng_ust_ctl_clear_buffer(struct lttng_ust_ctl_consumer_stream *stream) { struct lttng_ust_ring_buffer *buf; struct lttng_ust_ctl_consumer_channel *consumer_chan; + struct lttng_ust_sigbus_range range; assert(stream); buf = stream->buf; consumer_chan = stream->chan; + if (sigbus_begin()) + return -EIO; + lttng_ust_sigbus_add_range(&range, stream->memory_map_addr, + stream->memory_map_size); lib_ring_buffer_switch_slow(buf, SWITCH_ACTIVE, consumer_chan->chan->priv->rb_chan->handle); lib_ring_buffer_clear_reader(buf, consumer_chan->chan->priv->rb_chan->handle); + lttng_ust_sigbus_del_range(&range); + sigbus_end(); + return 0; } static @@ -1830,6 +2116,8 @@ int lttng_ust_ctl_get_timestamp_begin(struct lttng_ust_ctl_consumer_stream *stre struct lttng_ust_client_lib_ring_buffer_client_cb *client_cb; struct lttng_ust_ring_buffer_channel *chan; struct lttng_ust_ring_buffer *buf; + struct lttng_ust_sigbus_range range; + int ret; if (!stream || !timestamp_begin) return -EINVAL; @@ -1838,7 +2126,14 @@ int lttng_ust_ctl_get_timestamp_begin(struct lttng_ust_ctl_consumer_stream *stre client_cb = get_client_cb(buf, chan); if (!client_cb) return -ENOSYS; - return client_cb->timestamp_begin(buf, chan, timestamp_begin); + if (sigbus_begin()) + return -EIO; + lttng_ust_sigbus_add_range(&range, stream->memory_map_addr, + stream->memory_map_size); + ret = client_cb->timestamp_begin(buf, chan, timestamp_begin); + lttng_ust_sigbus_del_range(&range); + sigbus_end(); + return ret; } int lttng_ust_ctl_get_timestamp_end(struct lttng_ust_ctl_consumer_stream *stream, @@ -1847,6 +2142,8 @@ int lttng_ust_ctl_get_timestamp_end(struct lttng_ust_ctl_consumer_stream *stream struct lttng_ust_client_lib_ring_buffer_client_cb *client_cb; struct lttng_ust_ring_buffer_channel *chan; struct lttng_ust_ring_buffer *buf; + struct lttng_ust_sigbus_range range; + int ret; if (!stream || !timestamp_end) return -EINVAL; @@ -1855,7 +2152,14 @@ int lttng_ust_ctl_get_timestamp_end(struct lttng_ust_ctl_consumer_stream *stream client_cb = get_client_cb(buf, chan); if (!client_cb) return -ENOSYS; - return client_cb->timestamp_end(buf, chan, timestamp_end); + if (sigbus_begin()) + return -EIO; + lttng_ust_sigbus_add_range(&range, stream->memory_map_addr, + stream->memory_map_size); + ret = client_cb->timestamp_end(buf, chan, timestamp_end); + lttng_ust_sigbus_del_range(&range); + sigbus_end(); + return ret; } int lttng_ust_ctl_get_events_discarded(struct lttng_ust_ctl_consumer_stream *stream, @@ -1864,6 +2168,8 @@ int lttng_ust_ctl_get_events_discarded(struct lttng_ust_ctl_consumer_stream *str struct lttng_ust_client_lib_ring_buffer_client_cb *client_cb; struct lttng_ust_ring_buffer_channel *chan; struct lttng_ust_ring_buffer *buf; + struct lttng_ust_sigbus_range range; + int ret; if (!stream || !events_discarded) return -EINVAL; @@ -1872,7 +2178,14 @@ int lttng_ust_ctl_get_events_discarded(struct lttng_ust_ctl_consumer_stream *str client_cb = get_client_cb(buf, chan); if (!client_cb) return -ENOSYS; - return client_cb->events_discarded(buf, chan, events_discarded); + if (sigbus_begin()) + return -EIO; + lttng_ust_sigbus_add_range(&range, stream->memory_map_addr, + stream->memory_map_size); + ret = client_cb->events_discarded(buf, chan, events_discarded); + lttng_ust_sigbus_del_range(&range); + sigbus_end(); + return ret; } int lttng_ust_ctl_get_content_size(struct lttng_ust_ctl_consumer_stream *stream, @@ -1881,6 +2194,8 @@ int lttng_ust_ctl_get_content_size(struct lttng_ust_ctl_consumer_stream *stream, struct lttng_ust_client_lib_ring_buffer_client_cb *client_cb; struct lttng_ust_ring_buffer_channel *chan; struct lttng_ust_ring_buffer *buf; + struct lttng_ust_sigbus_range range; + int ret; if (!stream || !content_size) return -EINVAL; @@ -1889,7 +2204,14 @@ int lttng_ust_ctl_get_content_size(struct lttng_ust_ctl_consumer_stream *stream, client_cb = get_client_cb(buf, chan); if (!client_cb) return -ENOSYS; - return client_cb->content_size(buf, chan, content_size); + if (sigbus_begin()) + return -EIO; + lttng_ust_sigbus_add_range(&range, stream->memory_map_addr, + stream->memory_map_size); + ret = client_cb->content_size(buf, chan, content_size); + lttng_ust_sigbus_del_range(&range); + sigbus_end(); + return ret; } int lttng_ust_ctl_get_packet_size(struct lttng_ust_ctl_consumer_stream *stream, @@ -1898,6 +2220,8 @@ int lttng_ust_ctl_get_packet_size(struct lttng_ust_ctl_consumer_stream *stream, struct lttng_ust_client_lib_ring_buffer_client_cb *client_cb; struct lttng_ust_ring_buffer_channel *chan; struct lttng_ust_ring_buffer *buf; + struct lttng_ust_sigbus_range range; + int ret; if (!stream || !packet_size) return -EINVAL; @@ -1906,7 +2230,14 @@ int lttng_ust_ctl_get_packet_size(struct lttng_ust_ctl_consumer_stream *stream, client_cb = get_client_cb(buf, chan); if (!client_cb) return -ENOSYS; - return client_cb->packet_size(buf, chan, packet_size); + if (sigbus_begin()) + return -EIO; + lttng_ust_sigbus_add_range(&range, stream->memory_map_addr, + stream->memory_map_size); + ret = client_cb->packet_size(buf, chan, packet_size); + lttng_ust_sigbus_del_range(&range); + sigbus_end(); + return ret; } int lttng_ust_ctl_get_stream_id(struct lttng_ust_ctl_consumer_stream *stream, @@ -1915,6 +2246,8 @@ int lttng_ust_ctl_get_stream_id(struct lttng_ust_ctl_consumer_stream *stream, struct lttng_ust_client_lib_ring_buffer_client_cb *client_cb; struct lttng_ust_ring_buffer_channel *chan; struct lttng_ust_ring_buffer *buf; + struct lttng_ust_sigbus_range range; + int ret; if (!stream || !stream_id) return -EINVAL; @@ -1923,7 +2256,14 @@ int lttng_ust_ctl_get_stream_id(struct lttng_ust_ctl_consumer_stream *stream, client_cb = get_client_cb(buf, chan); if (!client_cb) return -ENOSYS; - return client_cb->stream_id(buf, chan, stream_id); + if (sigbus_begin()) + return -EIO; + lttng_ust_sigbus_add_range(&range, stream->memory_map_addr, + stream->memory_map_size); + ret = client_cb->stream_id(buf, chan, stream_id); + lttng_ust_sigbus_del_range(&range); + sigbus_end(); + return ret; } int lttng_ust_ctl_get_current_timestamp(struct lttng_ust_ctl_consumer_stream *stream, @@ -1932,6 +2272,8 @@ int lttng_ust_ctl_get_current_timestamp(struct lttng_ust_ctl_consumer_stream *st struct lttng_ust_client_lib_ring_buffer_client_cb *client_cb; struct lttng_ust_ring_buffer_channel *chan; struct lttng_ust_ring_buffer *buf; + struct lttng_ust_sigbus_range range; + int ret; if (!stream || !ts) return -EINVAL; @@ -1940,7 +2282,14 @@ int lttng_ust_ctl_get_current_timestamp(struct lttng_ust_ctl_consumer_stream *st client_cb = get_client_cb(buf, chan); if (!client_cb || !client_cb->current_timestamp) return -ENOSYS; - return client_cb->current_timestamp(buf, chan, ts); + if (sigbus_begin()) + return -EIO; + lttng_ust_sigbus_add_range(&range, stream->memory_map_addr, + stream->memory_map_size); + ret = client_cb->current_timestamp(buf, chan, ts); + lttng_ust_sigbus_del_range(&range); + sigbus_end(); + return ret; } int lttng_ust_ctl_get_sequence_number(struct lttng_ust_ctl_consumer_stream *stream, @@ -1949,6 +2298,8 @@ int lttng_ust_ctl_get_sequence_number(struct lttng_ust_ctl_consumer_stream *stre struct lttng_ust_client_lib_ring_buffer_client_cb *client_cb; struct lttng_ust_ring_buffer_channel *chan; struct lttng_ust_ring_buffer *buf; + struct lttng_ust_sigbus_range range; + int ret; if (!stream || !seq) return -EINVAL; @@ -1957,7 +2308,14 @@ int lttng_ust_ctl_get_sequence_number(struct lttng_ust_ctl_consumer_stream *stre client_cb = get_client_cb(buf, chan); if (!client_cb || !client_cb->sequence_number) return -ENOSYS; - return client_cb->sequence_number(buf, chan, seq); + if (sigbus_begin()) + return -EIO; + lttng_ust_sigbus_add_range(&range, stream->memory_map_addr, + stream->memory_map_size); + ret = client_cb->sequence_number(buf, chan, seq); + lttng_ust_sigbus_del_range(&range); + sigbus_end(); + return ret; } int lttng_ust_ctl_get_instance_id(struct lttng_ust_ctl_consumer_stream *stream, @@ -1966,6 +2324,8 @@ int lttng_ust_ctl_get_instance_id(struct lttng_ust_ctl_consumer_stream *stream, struct lttng_ust_client_lib_ring_buffer_client_cb *client_cb; struct lttng_ust_ring_buffer_channel *chan; struct lttng_ust_ring_buffer *buf; + struct lttng_ust_sigbus_range range; + int ret; if (!stream || !id) return -EINVAL; @@ -1974,7 +2334,14 @@ int lttng_ust_ctl_get_instance_id(struct lttng_ust_ctl_consumer_stream *stream, client_cb = get_client_cb(buf, chan); if (!client_cb) return -ENOSYS; - return client_cb->instance_id(buf, chan, id); + if (sigbus_begin()) + return -EIO; + lttng_ust_sigbus_add_range(&range, stream->memory_map_addr, + stream->memory_map_size); + ret = client_cb->instance_id(buf, chan, id); + lttng_ust_sigbus_del_range(&range); + sigbus_end(); + return ret; } #ifdef HAVE_LINUX_PERF_EVENT_H @@ -2041,7 +2408,6 @@ int get_cred(int sock, /* * Override application uid/gid with unix socket credentials. Use the * first group of the cr_groups. - * Use the pid and ppid provided by the application on registration. */ static int get_cred(int sock, @@ -2055,21 +2421,25 @@ int get_cred(int sock, socklen_t xucred_len = sizeof(struct xucred); int ret; - ret = getsockopt(sock, SOL_SOCKET, LOCAL_PEERCRED, &xucred, &xucred_len); + ret = getsockopt(sock, SOL_LOCAL, LOCAL_PEERCRED, &xucred, &xucred_len); if (ret) { return -LTTNG_UST_ERR_PEERCRED; } if (xucred.cr_version != XUCRED_VERSION || xucred.cr_ngroups < 1) { return -LTTNG_UST_ERR_PEERCRED; } - DBG("Unix socket peercred [ uid: %u, gid: %u ], " - "application registered claiming [ pid: %d, ppid: %d, uid: %u, gid: %u ]", - xucred.cr_uid, xucred.cr_groups[0], + DBG("Unix socket peercred [ pid: %u, uid: %u, gid: %u ], " + "application registered claiming [ pid: %u, ppid: %u, uid: %u, gid: %u ]", + xucred.cr_pid, xucred.cr_uid, xucred.cr_groups[0], reg_msg->pid, reg_msg->ppid, reg_msg->uid, reg_msg->gid); - *pid = reg_msg->pid; - *ppid = reg_msg->ppid; + *pid = xucred.cr_pid; *uid = xucred.cr_uid; *gid = xucred.cr_groups[0]; + if (xucred.cr_pid == reg_msg->pid) { + *ppid = reg_msg->ppid; + } else { + *ppid = 0; + } return 0; } #else @@ -2534,7 +2904,7 @@ int lttng_ust_ctl_regenerate_statedump(int sock, int handle) int lttng_ust_ctl_get_nr_cpu_per_counter(void) { - return num_possible_cpus(); + return get_possible_cpus_array_len(); } struct lttng_ust_ctl_daemon_counter * @@ -2762,6 +3132,14 @@ void lttng_ust_ctl_destroy_counter(struct lttng_ust_ctl_daemon_counter *counter) free(counter); } +/* + * Protocol for LTTNG_UST_ABI_COUNTER command: + * + * - send: struct ustcomm_ust_msg + * - receive: struct ustcomm_ust_reply + * - send: counter data + * - receive: struct ustcomm_ust_reply (actual command return code) + */ int lttng_ust_ctl_send_counter_data_to_ust(int sock, int parent_handle, struct lttng_ust_abi_object_data *counter_data) { @@ -2779,7 +3157,7 @@ int lttng_ust_ctl_send_counter_data_to_ust(int sock, int parent_handle, lum.handle = parent_handle; lum.cmd = LTTNG_UST_ABI_COUNTER; lum.u.counter.len = size; - ret = ustcomm_send_app_msg(sock, &lum); + ret = ustcomm_send_app_cmd(sock, &lum, &lur); if (ret) return ret; @@ -2799,6 +3177,14 @@ int lttng_ust_ctl_send_counter_data_to_ust(int sock, int parent_handle, return ret; } +/* + * Protocol for LTTNG_UST_ABI_COUNTER_GLOBAL command: + * + * - send: struct ustcomm_ust_msg + * - receive: struct ustcomm_ust_reply + * - send: file descriptor + * - receive: struct ustcomm_ust_reply (actual command return code) + */ int lttng_ust_ctl_send_counter_global_data_to_ust(int sock, struct lttng_ust_abi_object_data *counter_data, struct lttng_ust_abi_object_data *counter_global_data) @@ -2817,7 +3203,7 @@ int lttng_ust_ctl_send_counter_global_data_to_ust(int sock, lum.handle = counter_data->handle; /* parent handle */ lum.cmd = LTTNG_UST_ABI_COUNTER_GLOBAL; lum.u.counter_global.len = size; - ret = ustcomm_send_app_msg(sock, &lum); + ret = ustcomm_send_app_cmd(sock, &lum, &lur); if (ret) return ret; @@ -2837,6 +3223,14 @@ int lttng_ust_ctl_send_counter_global_data_to_ust(int sock, return ret; } +/* + * Protocol for LTTNG_UST_ABI_COUNTER_CPU command: + * + * - send: struct ustcomm_ust_msg + * - receive: struct ustcomm_ust_reply + * - send: file descriptor + * - receive: struct ustcomm_ust_reply (actual command return code) + */ int lttng_ust_ctl_send_counter_cpu_data_to_ust(int sock, struct lttng_ust_abi_object_data *counter_data, struct lttng_ust_abi_object_data *counter_cpu_data) @@ -2856,7 +3250,7 @@ int lttng_ust_ctl_send_counter_cpu_data_to_ust(int sock, lum.cmd = LTTNG_UST_ABI_COUNTER_CPU; lum.u.counter_cpu.len = size; lum.u.counter_cpu.cpu_nr = counter_cpu_data->u.counter_cpu.cpu_nr; - ret = ustcomm_send_app_msg(sock, &lum); + ret = ustcomm_send_app_cmd(sock, &lum, &lur); if (ret) return ret;