Fix: liblttng-ctl comm: lttng_event_context is not packed
authorJonathan Rajotte <jonathan.rajotte-julien@efficios.com>
Wed, 12 Jan 2022 23:18:08 +0000 (18:18 -0500)
committerJérémie Galarneau <jeremie.galarneau@efficios.com>
Mon, 28 Feb 2022 22:12:33 +0000 (17:12 -0500)
Observed issue
==============

The size of the struct differs between bitness for x86-64 and x86
leading to serialization/deserialization problem across client
(liblttng-ctl) and lttng-sessiond.

sizeof(struct lttng_event_context):

  x86: 308
  x86-64: 312

The struct cannot be marked as LTTNG_PACKED since it is part of the API.

Solution
========

Adopt a similar pattern to the new API with a "serialize" &
"create_from_buffer" approach.

Most of the complexity is moved to `src/common/event.c`

Known drawbacks
=========

None.

Signed-off-by: Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
Change-Id: Ieb400eab2a2df4070ff51cb2b44929d3ea945ce4

include/lttng/event-internal.h
src/bin/lttng-sessiond/client.c
src/bin/lttng-sessiond/cmd.c
src/bin/lttng-sessiond/cmd.h
src/bin/lttng-sessiond/context.c
src/bin/lttng-sessiond/context.h
src/common/event.c
src/common/sessiond-comm/sessiond-comm.h
src/lib/lttng-ctl/lttng-ctl.c

index e3aceaa703ac62a9f70e7df72bbcb96dd1e1b7fd..54f33fdf1c5031c9fa57baa617396353553cf502 100644 (file)
@@ -77,6 +77,50 @@ struct lttng_event_function_attr_comm {
        char payload[];
 } LTTNG_PACKED;
 
+struct lttng_event_context_comm {
+       uint32_t type;
+       /*
+        * Depending on the type.
+        * For:
+        *  - LTTNG_EVENT_CONTEXT_APP_CONTEXT.
+        *
+        *  -> struct lttng_event_context_app_comm
+        *
+        * For
+        *  - LTTNG_EVENT_CONTEXT_PERF_COUNTER,
+        *  - LTTNG_EVENT_CONTEXT_PERF_CPU_COUNTER,
+        *  - LTTNG_EVENT_CONTEXT_PERF_THREAD_COUNTER.
+        *
+        *  -> struct lttng_event_context_perf_counter_comm
+        *
+        *  Other type -> no payload.
+        */
+       char payload[];
+} LTTNG_PACKED;
+
+struct lttng_event_context_perf_counter_comm {
+       uint32_t type;
+       uint64_t config;
+       /* Includes terminator `\0`. */
+       uint32_t name_len;
+       /*
+        * char name [name_len]
+        */
+       char payload[];
+} LTTNG_PACKED;
+
+struct lttng_event_context_app_comm {
+       /* Includes terminator `\0`. */
+       uint32_t provider_name_len;
+       /* Includes terminator `\0`. */
+       uint32_t ctx_name_len;
+       /*
+        * provider name [provider_name_len]
+        * ctx name [ctx_name_len]
+        */
+       char payload[];
+} LTTNG_PACKED;
+
 struct lttng_event_extended {
        /*
         * exclusions and filter_expression are only set when the lttng_event
@@ -114,6 +158,18 @@ int lttng_event_serialize(const struct lttng_event *event,
                struct lttng_dynamic_buffer *buf,
                int *fd_to_send);
 
+LTTNG_HIDDEN
+ssize_t lttng_event_context_create_from_buffer(
+               const struct lttng_buffer_view *view,
+               struct lttng_event_context **event_ctx);
+
+LTTNG_HIDDEN
+int lttng_event_context_serialize(struct lttng_event_context *context,
+               struct lttng_dynamic_buffer *buf);
+
+LTTNG_HIDDEN
+void lttng_event_context_destroy(struct lttng_event_context *context);
+
 LTTNG_HIDDEN
 enum lttng_error_code lttng_events_create_and_flatten_from_buffer(
                const struct lttng_buffer_view *view,
index 0d56e42f5da6cd70a1b7ab26a8aa5d3339e21980..d6de4bfbd2fbe202ce119b553041a7056255a1f9 100644 (file)
@@ -981,74 +981,7 @@ skip_domain:
        switch (cmd_ctx->lsm->cmd_type) {
        case LTTNG_ADD_CONTEXT:
        {
-               /*
-                * An LTTNG_ADD_CONTEXT command might have a supplementary
-                * payload if the context being added is an application context.
-                */
-               if (cmd_ctx->lsm->u.context.ctx.ctx ==
-                               LTTNG_EVENT_CONTEXT_APP_CONTEXT) {
-                       char *provider_name = NULL, *context_name = NULL;
-                       size_t provider_name_len =
-                                       cmd_ctx->lsm->u.context.provider_name_len;
-                       size_t context_name_len =
-                                       cmd_ctx->lsm->u.context.context_name_len;
-
-                       if (provider_name_len == 0 || context_name_len == 0) {
-                               /*
-                                * Application provider and context names MUST
-                                * be provided.
-                                */
-                               ret = -LTTNG_ERR_INVALID;
-                               goto error;
-                       }
-
-                       provider_name = zmalloc(provider_name_len + 1);
-                       if (!provider_name) {
-                               ret = -LTTNG_ERR_NOMEM;
-                               goto error;
-                       }
-                       cmd_ctx->lsm->u.context.ctx.u.app_ctx.provider_name =
-                                       provider_name;
-
-                       context_name = zmalloc(context_name_len + 1);
-                       if (!context_name) {
-                               ret = -LTTNG_ERR_NOMEM;
-                               goto error_add_context;
-                       }
-                       cmd_ctx->lsm->u.context.ctx.u.app_ctx.ctx_name =
-                                       context_name;
-
-                       ret = lttcomm_recv_unix_sock(*sock, provider_name,
-                                       provider_name_len);
-                       if (ret < 0) {
-                               goto error_add_context;
-                       }
-
-                       ret = lttcomm_recv_unix_sock(*sock, context_name,
-                                       context_name_len);
-                       if (ret < 0) {
-                               goto error_add_context;
-                       }
-               }
-
-               /*
-                * cmd_add_context assumes ownership of the provider and context
-                * names.
-                */
-               ret = cmd_add_context(cmd_ctx->session,
-                               cmd_ctx->lsm->domain.type,
-                               cmd_ctx->lsm->u.context.channel_name,
-                               ALIGNED_CONST_PTR(cmd_ctx->lsm->u.context.ctx),
-                               kernel_poll_pipe[1]);
-
-               cmd_ctx->lsm->u.context.ctx.u.app_ctx.provider_name = NULL;
-               cmd_ctx->lsm->u.context.ctx.u.app_ctx.ctx_name = NULL;
-error_add_context:
-               free(cmd_ctx->lsm->u.context.ctx.u.app_ctx.provider_name);
-               free(cmd_ctx->lsm->u.context.ctx.u.app_ctx.ctx_name);
-               if (ret < 0) {
-                       goto error;
-               }
+               ret = cmd_add_context(cmd_ctx, *sock, kernel_poll_pipe[1]);
                break;
        }
        case LTTNG_DISABLE_CHANNEL:
index efa46cc28128b938f9eee35194f6fe03c6f01055..5a6414ebbe4991f48b4450d64d31c32f1d1ce00e 100644 (file)
@@ -1913,27 +1913,54 @@ error:
 /*
  * Command LTTNG_ADD_CONTEXT processed by the client thread.
  */
-int cmd_add_context(struct ltt_session *session, enum lttng_domain_type domain,
-               char *channel_name, const struct lttng_event_context *ctx, int kwpipe)
+
+int cmd_add_context(struct command_ctx *cmd_ctx, int sock, int kwpipe)
 {
+       struct lttng_event_context *ctx = NULL;
        int ret, chan_kern_created = 0, chan_ust_created = 0;
-       char *app_ctx_provider_name = NULL, *app_ctx_name = NULL;
+       struct lttng_dynamic_buffer buffer;
+       struct lttng_buffer_view view;
+       size_t context_len;
+       ssize_t sock_recv_len;
+       enum lttng_domain_type domain = cmd_ctx->lsm->domain.type;
+       struct ltt_session *session = cmd_ctx->session;
+       const char *channel_name = cmd_ctx->lsm->u.context.channel_name;
+
+       lttng_dynamic_buffer_init(&buffer);
+
+       context_len = (size_t) cmd_ctx->lsm->u.context.length;
+       ret = lttng_dynamic_buffer_set_size(&buffer, context_len);
+       if (ret) {
+               ret = LTTNG_ERR_NOMEM;
+               goto end;
+       }
+
+       sock_recv_len = lttcomm_recv_unix_sock(sock, buffer.data, context_len);
+       if (sock_recv_len < 0 || sock_recv_len != context_len) {
+               ERR("Failed to receive \"add context\" command payload");
+               ret = LTTNG_ERR_INVALID;
+               goto end;
+       }
+
+       view = lttng_buffer_view_from_dynamic_buffer(&buffer, 0, -1);
+
+       if (lttng_event_context_create_from_buffer(&view, &ctx) !=
+                       context_len) {
+               ERR("Invalid event context payload received in \"add context\" command");
+               ret = LTTNG_ERR_INVALID;
+               goto end;
+       }
 
        /*
         * Don't try to add a context if the session has been started at
         * some point in time before. The tracer does not allow it and would
         * result in a corrupted trace.
         */
-       if (session->has_been_started) {
+       if (cmd_ctx->session->has_been_started) {
                ret = LTTNG_ERR_TRACE_ALREADY_STARTED;
                goto end;
        }
 
-       if (ctx->ctx == LTTNG_EVENT_CONTEXT_APP_CONTEXT) {
-               app_ctx_provider_name = ctx->u.app_ctx.provider_name;
-               app_ctx_name = ctx->u.app_ctx.ctx_name;
-       }
-
        switch (domain) {
        case LTTNG_DOMAIN_KERNEL:
                assert(session->kernel_session);
@@ -2002,10 +2029,6 @@ int cmd_add_context(struct ltt_session *session, enum lttng_domain_type domain,
                }
 
                ret = context_ust_add(usess, domain, ctx, channel_name);
-               free(app_ctx_provider_name);
-               free(app_ctx_name);
-               app_ctx_name = NULL;
-               app_ctx_provider_name = NULL;
                if (ret != LTTNG_OK) {
                        goto error;
                }
@@ -2042,8 +2065,7 @@ error:
                trace_ust_destroy_channel(uchan);
        }
 end:
-       free(app_ctx_provider_name);
-       free(app_ctx_name);
+       lttng_event_context_destroy(ctx);
        return ret;
 }
 
index e2db454186e90b259137faf26e61d2035f469284..6b693c06a6342c00d9f4ab6c071624d2f9cd35a5 100644 (file)
@@ -78,8 +78,7 @@ enum lttng_error_code cmd_process_attr_tracker_get_inclusion_set(
 
 /* Event commands */
 int cmd_disable_event(struct command_ctx *cmd_ctx, int sock);
-int cmd_add_context(struct ltt_session *session, enum lttng_domain_type domain,
-               char *channel_name, const struct lttng_event_context *ctx, int kwpipe);
+int cmd_add_context(struct command_ctx *cmd_ctx, int sock, int kwpipe);
 int cmd_set_filter(struct ltt_session *session, enum lttng_domain_type domain,
                char *channel_name, struct lttng_event *event,
                struct lttng_filter_bytecode *bytecode);
index 7bc6667a0f26e33a497e2c6fbdd23caff67fd900..2f5b93c157f7c98b2f855ca44a4ee546cd7e8283 100644 (file)
@@ -187,7 +187,8 @@ duplicate:
  * Add kernel context to tracer.
  */
 int context_kernel_add(struct ltt_kernel_session *ksession,
-               const struct lttng_event_context *ctx, char *channel_name)
+               const struct lttng_event_context *ctx,
+               const char *channel_name)
 {
        int ret;
        struct ltt_kernel_channel *kchan;
@@ -363,7 +364,7 @@ error:
 int context_ust_add(struct ltt_ust_session *usess,
                enum lttng_domain_type domain,
                const struct lttng_event_context *ctx,
-               char *channel_name)
+               const char *channel_name)
 {
        int ret = LTTNG_OK;
        struct lttng_ht_iter iter;
index ed5fe2ca27bb7c6e9a9743bdb0d4196de70a092a..073a2e1784a794146bdced46c3a4cba7228c62e2 100644 (file)
 #include "lttng-ust-ctl.h"
 
 int context_kernel_add(struct ltt_kernel_session *ksession,
-               const struct lttng_event_context *ctx, char *channel_name);
+               const struct lttng_event_context *ctx,
+               const char *channel_name);
 int context_ust_add(struct ltt_ust_session *usess,
                enum lttng_domain_type domain,
                const struct lttng_event_context *ctx,
-               char *channel_name);
+               const char *channel_name);
 
 #endif /* _LTT_CONTEXT_H */
index 967f36bb5f237847265fd1eb0e69d92fa7232834..0f6ac9a8c1d306a7a3144f139c00461c1792349e 100644 (file)
@@ -946,6 +946,385 @@ end:
        return ret;
 }
 
+static ssize_t lttng_event_context_app_populate_from_buffer(
+               const struct lttng_buffer_view *view,
+               struct lttng_event_context *event_ctx)
+{
+       ssize_t ret, offset = 0;
+       const struct lttng_event_context_app_comm *comm;
+       char *provider_name = NULL, *context_name = NULL;
+       size_t provider_name_len, context_name_len;
+       const struct lttng_buffer_view comm_view = lttng_buffer_view_from_view(
+                       view, offset, sizeof(*comm));
+
+       assert(event_ctx->ctx == LTTNG_EVENT_CONTEXT_APP_CONTEXT);
+
+       if (!lttng_buffer_view_is_valid(&comm_view)) {
+               ret = -1;
+               goto end;
+       }
+
+       comm = (typeof(comm)) comm_view.data;
+       offset += sizeof(*comm);
+
+       provider_name_len = comm->provider_name_len;
+       context_name_len = comm->ctx_name_len;
+
+       if (provider_name_len == 0 || context_name_len == 0) {
+               /*
+                * Application provider and context names MUST
+                * be provided.
+                */
+               ret = -1;
+               goto end;
+       }
+
+       {
+               const char *name;
+               const struct lttng_buffer_view provider_name_view =
+                               lttng_buffer_view_from_view(view, offset,
+                                               provider_name_len);
+
+               if (!lttng_buffer_view_is_valid(&provider_name_view)) {
+                       ret = -1;
+                       goto end;
+               }
+
+               name = provider_name_view.data;
+
+               if (!lttng_buffer_view_contains_string(&provider_name_view,
+                                   name, provider_name_len)) {
+                       ret = -1;
+                       goto end;
+               }
+
+               provider_name = lttng_strndup(name, provider_name_len);
+               if (!provider_name) {
+                       ret = -1;
+                       goto end;
+               }
+               offset += provider_name_len;
+       }
+
+       {
+               const char *name;
+               const struct lttng_buffer_view context_name_view =
+                               lttng_buffer_view_from_view(
+                                               view, offset, context_name_len);
+
+               if (!lttng_buffer_view_is_valid(&context_name_view)) {
+                       ret = -1;
+                       goto end;
+               }
+
+               name = context_name_view.data;
+
+               if (!lttng_buffer_view_contains_string(&context_name_view, name,
+                                   context_name_len)) {
+                       ret = -1;
+                       goto end;
+               }
+
+               context_name = lttng_strndup(name, context_name_len);
+               if (!context_name) {
+                       ret = -1;
+                       goto end;
+               }
+
+               offset += context_name_len;
+       }
+
+       /* Transfer ownership of the strings */
+       event_ctx->u.app_ctx.provider_name = provider_name;
+       event_ctx->u.app_ctx.ctx_name = context_name;
+       provider_name = NULL;
+       context_name = NULL;
+
+       ret = offset;
+end:
+       free(provider_name);
+       free(context_name);
+
+       return ret;
+}
+
+static ssize_t lttng_event_context_perf_counter_populate_from_buffer(
+               const struct lttng_buffer_view *view,
+               struct lttng_event_context *event_ctx)
+{
+       ssize_t ret, offset = 0;
+       const struct lttng_event_context_perf_counter_comm *comm;
+       size_t name_len;
+       const struct lttng_buffer_view comm_view = lttng_buffer_view_from_view(
+                       view, offset, sizeof(*comm));
+
+       assert(event_ctx->ctx == LTTNG_EVENT_CONTEXT_PERF_COUNTER ||
+                       event_ctx->ctx ==
+                                       LTTNG_EVENT_CONTEXT_PERF_THREAD_COUNTER ||
+                       event_ctx->ctx == LTTNG_EVENT_CONTEXT_PERF_CPU_COUNTER);
+
+       if (!lttng_buffer_view_is_valid(&comm_view)) {
+               ret = -1;
+               goto end;
+       }
+
+       comm = (typeof(comm)) comm_view.data;
+       offset += sizeof(*comm);
+
+       name_len = comm->name_len;
+       {
+               const char *name;
+               const struct lttng_buffer_view provider_name_view =
+                               lttng_buffer_view_from_view(
+                                               view, offset, name_len);
+               if (!lttng_buffer_view_is_valid(&provider_name_view)) {
+                       ret = -1;
+                       goto end;
+               }
+
+               name = provider_name_view.data;
+
+               if (!lttng_buffer_view_contains_string(
+                                   &provider_name_view, name, name_len)) {
+                       ret = -1;
+                       goto end;
+               }
+
+               lttng_strncpy(event_ctx->u.perf_counter.name, name, name_len);
+               offset += name_len;
+       }
+
+       event_ctx->u.perf_counter.config = comm->config;
+       event_ctx->u.perf_counter.type = comm->type;
+
+       ret = offset;
+
+end:
+       return ret;
+}
+
+LTTNG_HIDDEN
+ssize_t lttng_event_context_create_from_buffer(
+               const struct lttng_buffer_view *view,
+               struct lttng_event_context **event_ctx)
+{
+       ssize_t ret, offset = 0;
+       const struct lttng_event_context_comm *comm;
+       struct lttng_event_context *local_context = NULL;
+       struct lttng_buffer_view subtype_view;
+       struct lttng_buffer_view comm_view = lttng_buffer_view_from_view(
+                       view, offset, sizeof(*comm));
+
+       assert(event_ctx);
+       assert(view);
+
+       if (!lttng_buffer_view_is_valid(&comm_view)) {
+               ret = -1;
+               goto end;
+       }
+
+       comm = (typeof(comm)) comm_view.data;
+       offset += sizeof(*comm);
+
+       local_context = zmalloc(sizeof(*local_context));
+       if (!local_context) {
+               ret = -1;
+               goto end;
+       }
+
+       local_context->ctx = comm->type;
+
+       subtype_view = lttng_buffer_view_from_view(view, offset, -1);
+
+       switch (local_context->ctx) {
+       case LTTNG_EVENT_CONTEXT_APP_CONTEXT:
+               ret = lttng_event_context_app_populate_from_buffer(
+                               &subtype_view, local_context);
+               break;
+       case LTTNG_EVENT_CONTEXT_PERF_COUNTER:
+       case LTTNG_EVENT_CONTEXT_PERF_THREAD_COUNTER:
+       case LTTNG_EVENT_CONTEXT_PERF_CPU_COUNTER:
+               ret = lttng_event_context_perf_counter_populate_from_buffer(
+                               &subtype_view, local_context);
+               break;
+       default:
+               /* Nothing else to deserialize. */
+               ret = 0;
+               break;
+       }
+
+       if (ret < 0) {
+               goto end;
+       }
+
+       offset += ret;
+
+       *event_ctx = local_context;
+       local_context = NULL;
+       ret = offset;
+
+end:
+       free(local_context);
+       return ret;
+}
+
+static int lttng_event_context_app_serialize(
+               struct lttng_event_context *context,
+               struct lttng_dynamic_buffer *buffer)
+{
+       int ret;
+       struct lttng_event_context_app_comm comm = { 0 };
+       size_t provider_len, ctx_len;
+       const char *provider_name;
+       const char *ctx_name;
+
+       assert(buffer);
+       assert(context);
+       assert(context->ctx == LTTNG_EVENT_CONTEXT_APP_CONTEXT);
+
+       provider_name = context->u.app_ctx.provider_name;
+       ctx_name = context->u.app_ctx.ctx_name;
+
+       if (!provider_name || !ctx_name) {
+               ret = -LTTNG_ERR_INVALID;
+               goto end;
+       }
+
+       provider_len = strlen(provider_name);
+       if (provider_len == 0) {
+               ret = -LTTNG_ERR_INVALID;
+               goto end;
+       }
+
+       /* Include the null terminator. */
+       comm.provider_name_len = provider_len + 1;
+
+       ctx_len = strlen(ctx_name);
+       if (ctx_len == 0) {
+               ret = -LTTNG_ERR_INVALID;
+               goto end;
+       }
+
+       /* Include the null terminator. */
+       comm.ctx_name_len = ctx_len + 1;
+
+       /* Header */
+       ret = lttng_dynamic_buffer_append(buffer, &comm, sizeof(comm));
+       if (ret) {
+               ret = -1;
+               goto end;
+       }
+
+       ret = lttng_dynamic_buffer_append(buffer, provider_name, provider_len);
+       if (ret) {
+               ret = -1;
+               goto end;
+       }
+       ret = lttng_dynamic_buffer_append(buffer, ctx_name, ctx_len);
+       if (ret) {
+               ret = -1;
+               goto end;
+       }
+
+end:
+       return ret;
+}
+
+static int lttng_event_context_perf_counter_serialize(
+               struct lttng_event_perf_counter_ctx *context,
+               struct lttng_dynamic_buffer *buffer)
+{
+       int ret;
+       struct lttng_event_context_perf_counter_comm comm = { 0 };
+
+       assert(buffer);
+       assert(context);
+
+       comm.config = context->config;
+       comm.type = context->type;
+       comm.name_len = lttng_strnlen(context->name, LTTNG_SYMBOL_NAME_LEN);
+
+       if (comm.name_len == LTTNG_SYMBOL_NAME_LEN) {
+               ret = -1;
+               goto end;
+       }
+
+       /* Include the null terminator. */
+       comm.name_len += 1;
+
+       /* Header */
+       ret = lttng_dynamic_buffer_append(buffer, &comm, sizeof(comm));
+       if (ret) {
+               ret = -1;
+               goto end;
+       }
+
+       ret = lttng_dynamic_buffer_append(buffer, context->name, comm.name_len);
+       if (ret) {
+               ret = -1;
+               goto end;
+       }
+
+end:
+       return ret;
+}
+
+LTTNG_HIDDEN
+int lttng_event_context_serialize(struct lttng_event_context *context,
+               struct lttng_dynamic_buffer *buf)
+{
+       int ret;
+       struct lttng_event_context_comm context_comm = { 0 };
+
+       assert(context);
+       assert(buf);
+
+       context_comm.type = (uint32_t) context->ctx;
+
+       /* Header */
+       ret = lttng_dynamic_buffer_append(
+                       buf, &context_comm, sizeof(context_comm));
+       if (ret) {
+               goto end;
+       }
+
+       switch (context->ctx) {
+       case LTTNG_EVENT_CONTEXT_APP_CONTEXT:
+               ret = lttng_event_context_app_serialize(context, buf);
+               break;
+       case LTTNG_EVENT_CONTEXT_PERF_COUNTER:
+       case LTTNG_EVENT_CONTEXT_PERF_THREAD_COUNTER:
+       case LTTNG_EVENT_CONTEXT_PERF_CPU_COUNTER:
+               ret = lttng_event_context_perf_counter_serialize(
+                               &context->u.perf_counter, buf);
+               break;
+       default:
+               /* Nothing else to serialize. */
+               break;
+       }
+
+       if (ret) {
+               goto end;
+       }
+
+end:
+       return ret;
+}
+
+LTTNG_HIDDEN
+void lttng_event_context_destroy(struct lttng_event_context *context)
+{
+       if (!context) {
+               return;
+       }
+
+       if (context->ctx == LTTNG_EVENT_CONTEXT_APP_CONTEXT) {
+               free(context->u.app_ctx.provider_name);
+               free(context->u.app_ctx.ctx_name);
+       }
+
+       free(context);
+}
 static enum lttng_error_code compute_flattened_size(
                struct lttng_dynamic_pointer_array *events, size_t *size)
 {
index 2db5ba46938625163b150b271882299aac146459..4e7d292759229bc1220903f0357195d5da436613 100644 (file)
@@ -291,9 +291,7 @@ struct lttcomm_session_msg {
                /* Context */
                struct {
                        char channel_name[LTTNG_SYMBOL_NAME_LEN];
-                       struct lttng_event_context ctx LTTNG_PACKED;
-                       uint32_t provider_name_len;
-                       uint32_t context_name_len;
+                       uint32_t length;
                } LTTNG_PACKED context;
                /* Use by register_consumer */
                struct {
index 6b745d0204eb30d1c6517c72d2a6314fd1787858..a387202a66e1d192cfa7b586553164ab01d94d8c 100644 (file)
@@ -804,9 +804,10 @@ int lttng_add_context(struct lttng_handle *handle,
                const char *channel_name)
 {
        int ret;
-       size_t len = 0;
-       char *buf = NULL;
        struct lttcomm_session_msg lsm;
+       struct lttng_dynamic_buffer buffer;
+
+       lttng_dynamic_buffer_init(&buffer);
 
        /* Safety check. Both are mandatory. */
        if (handle == NULL || ctx == NULL) {
@@ -833,55 +834,18 @@ int lttng_add_context(struct lttng_handle *handle,
                goto end;
        }
 
-       if (ctx->ctx == LTTNG_EVENT_CONTEXT_APP_CONTEXT) {
-               size_t provider_len, ctx_len;
-               const char *provider_name = ctx->u.app_ctx.provider_name;
-               const char *ctx_name = ctx->u.app_ctx.ctx_name;
-
-               if (!provider_name || !ctx_name) {
-                       ret = -LTTNG_ERR_INVALID;
-                       goto end;
-               }
-
-               provider_len = strlen(provider_name);
-               if (provider_len == 0) {
-                       ret = -LTTNG_ERR_INVALID;
-                       goto end;
-               }
-               lsm.u.context.provider_name_len = provider_len;
-
-               ctx_len = strlen(ctx_name);
-               if (ctx_len == 0) {
-                       ret = -LTTNG_ERR_INVALID;
-                       goto end;
-               }
-               lsm.u.context.context_name_len = ctx_len;
-
-               len = provider_len + ctx_len;
-               buf = zmalloc(len);
-               if (!buf) {
-                       ret = -LTTNG_ERR_NOMEM;
-                       goto end;
-               }
-
-               memcpy(buf, provider_name, provider_len);
-               memcpy(buf + provider_len, ctx_name, ctx_len);
+       ret = lttng_event_context_serialize(ctx, &buffer);
+       if (ret) {
+               ret = -LTTNG_ERR_INVALID;
+               goto end;
        }
-       memcpy(&lsm.u.context.ctx, ctx, sizeof(struct lttng_event_context));
 
-       if (ctx->ctx == LTTNG_EVENT_CONTEXT_APP_CONTEXT) {
-               /*
-                * Don't leak application addresses to the sessiond.
-                * This is only necessary when ctx is for an app ctx otherwise
-                * the values inside the union (type & config) are overwritten.
-                */
-               lsm.u.context.ctx.u.app_ctx.provider_name = NULL;
-               lsm.u.context.ctx.u.app_ctx.ctx_name = NULL;
-       }
+       lsm.u.context.length = buffer.size;
 
-       ret = lttng_ctl_ask_sessiond_varlen_no_cmd_header(&lsm, buf, len, NULL);
+       ret = lttng_ctl_ask_sessiond_varlen_no_cmd_header(
+                       &lsm, buffer.data, buffer.size, NULL);
 end:
-       free(buf);
+       lttng_dynamic_buffer_reset(&buffer);
        return ret;
 }
 
This page took 0.035186 seconds and 4 git commands to generate.