Fix: sessiond: incorrect use of exclusions array leads to crash
authorJérémie Galarneau <jeremie.galarneau@efficios.com>
Tue, 23 May 2023 23:35:10 +0000 (19:35 -0400)
committerJérémie Galarneau <jeremie.galarneau@efficios.com>
Tue, 6 Jun 2023 18:37:21 +0000 (14:37 -0400)
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 <error: Cannot access memory at address 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=<synthetic pointer>, reply_payload=0x7fa9d3ffda88, ust_global=<optimized out>, channel_name=<optimized out>) at cmd.c:472
  #4  cmd_list_events (domain=<optimized out>, session=<optimized out>, channel_name=<optimized out>, 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 <jeremie.galarneau@efficios.com>
src/bin/lttng-sessiond/cmd.c

index 3adbbebcad1f46137838f6f95238a856815729f9..1adeeee4701d34e844f66d1217a716974a50b01a 100644 (file)
@@ -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;
 }
This page took 0.028131 seconds and 4 git commands to generate.