/*
* SPDX-License-Identifier: GPL-2.0-only
*
- * Copyright (C) 2011 Julien Desfossez <julien.desfossez@polymtl.ca>
+ * Copyright (C) 2011 EfficiOS Inc.
* Copyright (C) 2011-2013 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
*/
#include <lttng/ust-abi.h>
#include <lttng/ust-endian.h>
#include <lttng/ust-common.h>
+#include <lttng/ust-sigbus.h>
+#include <urcu/rculist.h>
#include "common/logging.h"
#include "common/ustcomm.h"
#include "common/ringbuffer/frontend.h"
#include "common/events.h"
#include "common/wait.h"
-#include "lib/lttng-ust/lttng-rb-clients.h"
-#include "common/clock.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"
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
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;
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)
}
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;
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)
{
}
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)
{
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 */
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)
{
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 */
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)
{
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;
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)
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;
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)
{
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)
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,
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 {
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 {
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 {
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;
}
}
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;
}
}
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;
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);
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;
{
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. */
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;
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). */
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);
+ lttng_ust_sigbus_del_range(&range);
+ sigbus_end();
return 0;
}
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;
}
{
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;
}
{
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;
}
/*
{
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) */
{
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 */
{
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
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;
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,
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;
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,
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;
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,
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;
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,
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;
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,
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;
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,
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;
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,
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;
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,
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;
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
/*
* 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,
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
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)
{
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;
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)
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;
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)
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;
*/
lttng_ust_common_ctor();
- lttng_ust_clock_init();
lttng_ust_ring_buffer_clients_init();
lttng_ust_counter_clients_init();
lib_ringbuffer_signal_init();