From 0bfaecd62c7bcc1ec52262b3ccb08b6916019d44 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=A9mie=20Galarneau?= Date: Tue, 23 May 2023 19:35:10 -0400 Subject: [PATCH] Fix: sessiond: incorrect use of exclusions array leads to crash MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Issue observed -------------- When using the CLI to list the configuration of a session that has an event rule which makes use of multiple exclusions, the session daemon crashes with the following stack trace: (gdb) bt #0 0x00007fa9ed401445 in ?? () from /usr/lib/libc.so.6 #1 0x0000560cd5fc5199 in lttng_strnlen (str=0x615f6f6c6c6568 , max=256) at ../../src/common/compat/string.h:19 #2 0x0000560cd5fc6b39 in lttng_event_serialize (event=0x7fa9cc01d8b0, exclusion_count=2, exclusion_list=0x7fa9cc011794, filter_expression=0x0, bytecode_len=0, bytecode=0x0, payload=0x7fa9d3ffda88) at event.c:767 #3 0x0000560cd5f380b5 in list_lttng_ust_global_events (nb_events=, reply_payload=0x7fa9d3ffda88, ust_global=, channel_name=) at cmd.c:472 #4 cmd_list_events (domain=, session=, channel_name=, reply_payload=0x7fa9d3ffda88) at cmd.c:3860 #5 0x0000560cd5f6d76a in process_client_msg (cmd_ctx=0x7fa9d3ffa710, sock=0x7fa9d3ffa5b0, sock_error=0x7fa9d3ffa5b4) at client.c:1890 #6 0x0000560cd5f6f876 in thread_manage_clients (data=0x560cd7879490) at client.c:2629 #7 0x0000560cd5f65a54 in launch_thread (data=0x560cd7879500) at thread.c:66 #8 0x00007fa9ed32d44b in ?? () from /usr/lib/libc.so.6 #9 0x00007fa9ed3b0e40 in ?? () from /usr/lib/libc.so.6 Cause ----- lttng_event_serialize expects a `char **` list of exclusion names, as provided by the other callsite in liblttng-ctl. However, the callsite in list_lttng_ust_global_events passes pointer to the exclusions as stored in lttng_event_exclusion. lttng_event_exclusion contains an array of fixed-length strings (with a stride of 256 bytes) which isn't an expected layout for lttng_event_serialize. Solution -------- A temporary array of pointers is constructed before invoking lttng_event_serialize to construct a list of exclusions with the layout that lttng_event_serialize expects. The array itself is reused for all events, limiting the number of allocations. Note ---- None. Change-Id: I266a1cc9e9f18e0476177a0047b1d8f468110575 Signed-off-by: Jérémie Galarneau --- src/bin/lttng-sessiond/cmd.c | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/src/bin/lttng-sessiond/cmd.c b/src/bin/lttng-sessiond/cmd.c index 3adbbebca..1adeeee47 100644 --- a/src/bin/lttng-sessiond/cmd.c +++ b/src/bin/lttng-sessiond/cmd.c @@ -376,10 +376,13 @@ static enum lttng_error_code list_lttng_ust_global_events(char *channel_name, struct ltt_ust_event *uevent; unsigned long channel_event_count; unsigned int local_nb_events = 0; + struct lttng_dynamic_pointer_array exclusion_names; assert(reply_payload); assert(nb_events); + lttng_dynamic_pointer_array_init(&exclusion_names, NULL); + DBG("Listing UST global events for channel %s", channel_name); rcu_read_lock(); @@ -465,14 +468,34 @@ static enum lttng_error_code list_lttng_ust_global_events(char *channel_name, tmp_event->exclusion = 1; } + if (uevent->exclusion) { + int i; + + for (i = 0; i < uevent->exclusion->count; i++) { + const int add_ret = lttng_dynamic_pointer_array_add_pointer( + &exclusion_names, + LTTNG_EVENT_EXCLUSION_NAME_AT(uevent->exclusion, i)); + + if (add_ret) { + PERROR("Failed to add exclusion name to temporary serialization array"); + ret_code = LTTNG_ERR_NOMEM; + goto error; + } + } + } + /* * We do not care about the filter bytecode and the fd from the * userspace_probe_location. */ - ret = lttng_event_serialize(tmp_event, uevent->exclusion ? uevent->exclusion->count : 0, - uevent->exclusion ? (char **) uevent->exclusion ->names : NULL, - uevent->filter_expression, 0, NULL, reply_payload); + ret = lttng_event_serialize(tmp_event, + lttng_dynamic_pointer_array_get_count(&exclusion_names), + lttng_dynamic_pointer_array_get_count(&exclusion_names) ? + (char **) exclusion_names.array.buffer.data : NULL, + uevent->filter_expression, 0, NULL, + reply_payload); lttng_event_destroy(tmp_event); + lttng_dynamic_pointer_array_clear(&exclusion_names); if (ret) { ret_code = LTTNG_ERR_FATAL; goto error; @@ -484,6 +507,7 @@ end: ret_code = LTTNG_OK; *nb_events = local_nb_events; error: + lttng_dynamic_pointer_array_reset(&exclusion_names); rcu_read_unlock(); return ret_code; } -- 2.34.1