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)
committerJonathan Rajotte <jonathan.rajotte-julien@efficios.com>
Fri, 25 Feb 2022 15:35:09 +0000 (10:35 -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 db65735350825261915219cdacaed56a17cf79a6..eec294dec24d74685f558f1db41d9fadc607ede3 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
@@ -110,6 +154,15 @@ int lttng_event_serialize(const struct lttng_event *event,
                struct lttng_bytecode *bytecode,
                struct lttng_payload *payload);
 
+ssize_t lttng_event_context_create_from_payload(
+               struct lttng_payload_view *view,
+               struct lttng_event_context **event_ctx);
+
+int lttng_event_context_serialize(struct lttng_event_context *context,
+               struct lttng_payload *payload);
+
+void lttng_event_context_destroy(struct lttng_event_context *context);
+
 enum lttng_error_code lttng_events_create_and_flatten_from_payload(
                struct lttng_payload_view *view,
                unsigned int count,
index 82ace4902596f71fcc1f9a9e03cf5d4dc500ce85..86708d2e28f96bf15e9ce204afba4ac1beb67255 100644 (file)
@@ -834,6 +834,60 @@ end:
        return ret_code;
 }
 
+static enum lttng_error_code receive_lttng_event_context(
+               const struct command_ctx *cmd_ctx,
+               int sock,
+               int *sock_error,
+               struct lttng_event_context **out_event_context)
+{
+       int ret;
+       const size_t event_context_len =
+                       (size_t) cmd_ctx->lsm.u.context.length;
+       ssize_t sock_recv_len;
+       enum lttng_error_code ret_code;
+       struct lttng_payload event_context_payload;
+
+       lttng_payload_init(&event_context_payload);
+
+       ret = lttng_dynamic_buffer_set_size(&event_context_payload.buffer,
+                       event_context_len);
+       if (ret) {
+               ret_code = LTTNG_ERR_NOMEM;
+               goto end;
+       }
+
+       sock_recv_len = lttcomm_recv_unix_sock(
+                       sock, event_context_payload.buffer.data,
+                       event_context_len);
+       if (sock_recv_len < 0 || sock_recv_len != event_context_len) {
+               ERR("Failed to receive event context in command payload");
+               *sock_error = 1;
+               ret_code = LTTNG_ERR_INVALID_PROTOCOL;
+               goto end;
+       }
+
+       /* Deserialize event. */
+       {
+               struct lttng_payload_view event_context_view =
+                               lttng_payload_view_from_payload(
+                                               &event_context_payload, 0, -1);
+
+               if (lttng_event_context_create_from_payload(
+                               &event_context_view, out_event_context) !=
+                               event_context_len) {
+                       ERR("Invalid event context received as part of command payload");
+                       ret_code = LTTNG_ERR_INVALID_PROTOCOL;
+                       goto end;
+               }
+       }
+
+       ret_code = LTTNG_OK;
+
+end:
+       lttng_payload_reset(&event_context_payload);
+       return ret_code;
+}
+
 /*
  * Version of setup_lttng_msg() without command header.
  */
@@ -1307,74 +1361,18 @@ 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;
-                       }
-               }
+               struct lttng_event_context *event_context;
+               const enum lttng_error_code ret_code =
+                       receive_lttng_event_context(
+                               cmd_ctx, *sock, sock_error, &event_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),
-                               the_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) {
+               if (ret_code != LTTNG_OK) {
+                       ret = (int) ret_code;
                        goto error;
                }
+
+               ret = cmd_add_context(cmd_ctx, event_context, the_kernel_poll_pipe[1]);
+               lttng_event_context_destroy(event_context);
                break;
        }
        case LTTNG_DISABLE_CHANNEL:
index 371bd68fd4818952e6484b9ae1cea5ab9b07f4c2..74c50579307ea24d3ef0f6582d6c8e421ded8312 100644 (file)
@@ -1865,27 +1865,24 @@ 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,
+       const struct lttng_event_context *event_context, int kwpipe)
 {
        int ret, chan_kern_created = 0, chan_ust_created = 0;
-       char *app_ctx_provider_name = NULL, *app_ctx_name = NULL;
+       const enum lttng_domain_type domain = cmd_ctx->lsm.domain.type;
+       const struct ltt_session *session = cmd_ctx->session;
+       const char *channel_name = cmd_ctx->lsm.u.context.channel_name;
 
        /*
         * 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);
@@ -1899,7 +1896,8 @@ int cmd_add_context(struct ltt_session *session, enum lttng_domain_type domain,
                        chan_kern_created = 1;
                }
                /* Add kernel context to kernel tracer */
-               ret = context_kernel_add(session->kernel_session, ctx, channel_name);
+               ret = context_kernel_add(session->kernel_session,
+                               event_context, channel_name);
                if (ret != LTTNG_OK) {
                        goto error;
                }
@@ -1953,11 +1951,8 @@ int cmd_add_context(struct ltt_session *session, enum lttng_domain_type domain,
                        chan_ust_created = 1;
                }
 
-               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;
+               ret = context_ust_add(usess, domain, event_context,
+                               channel_name);
                if (ret != LTTNG_OK) {
                        goto error;
                }
@@ -1994,8 +1989,6 @@ error:
                trace_ust_destroy_channel(uchan);
        }
 end:
-       free(app_ctx_provider_name);
-       free(app_ctx_name);
        return ret;
 }
 
index 27b10cb346e813f19b23992122b89d7252bee9e5..69389e5fa258ce9ee2b88d6a43980da0d0e52ceb 100644 (file)
@@ -82,8 +82,9 @@ int cmd_disable_event(struct command_ctx *cmd_ctx,
                char *filter_expression,
                struct lttng_bytecode *filter,
                struct lttng_event_exclusion *exclusion);
-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,
+               const struct lttng_event_context *event_context,
+               int kwpipe);
 int cmd_set_filter(struct ltt_session *session, enum lttng_domain_type domain,
                char *channel_name, struct lttng_event *event,
                struct lttng_bytecode *bytecode);
index a3a12c5332405c3062e0b59530741b00b26b50ff..35eefced30c57e99f214bfbcd4d5a84927540484 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;
@@ -366,7 +367,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 f6a24ef1b188286f0cbd5e32aea03c918640595d..1aaa1f0c0d42f0c291f56487732594a044c7119e 100644 (file)
@@ -887,6 +887,398 @@ end:
        return ret;
 }
 
+static ssize_t lttng_event_context_app_populate_from_payload(
+               const struct lttng_payload_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->buffer, 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->buffer,
+                                               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->buffer, 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_payload(
+               const struct lttng_payload_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->buffer, 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->buffer, 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;
+}
+
+ssize_t lttng_event_context_create_from_payload(
+               struct lttng_payload_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 comm_view = lttng_buffer_view_from_view(
+                       &view->buffer, 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 = (struct lttng_event_context *)
+                       zmalloc(sizeof(*local_context));
+       if (!local_context) {
+               ret = -1;
+               goto end;
+       }
+
+       local_context->ctx = (enum lttng_event_context_type) comm->type;
+
+       {
+               struct lttng_payload_view subtype_view =
+                               lttng_payload_view_from_view(view, offset, -1);
+
+               switch (local_context->ctx) {
+               case LTTNG_EVENT_CONTEXT_APP_CONTEXT:
+                       ret = lttng_event_context_app_populate_from_payload(
+                                       &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_payload(
+                                       &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_payload *payload)
+{
+       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(payload);
+       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(&payload->buffer, &comm,
+                       sizeof(comm));
+       if (ret) {
+               ret = -1;
+               goto end;
+       }
+
+       ret = lttng_dynamic_buffer_append(&payload->buffer, provider_name,
+                       provider_len);
+       if (ret) {
+               ret = -1;
+               goto end;
+       }
+
+       ret = lttng_dynamic_buffer_append(&payload->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_payload *payload)
+{
+       int ret;
+       struct lttng_event_context_perf_counter_comm comm = { 0 };
+
+       assert(payload);
+       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(&payload->buffer, &comm,
+                       sizeof(comm));
+       if (ret) {
+               ret = -1;
+               goto end;
+       }
+
+       ret = lttng_dynamic_buffer_append(&payload->buffer, context->name,
+                       comm.name_len);
+       if (ret) {
+               ret = -1;
+               goto end;
+       }
+
+end:
+       return ret;
+}
+
+int lttng_event_context_serialize(struct lttng_event_context *context,
+               struct lttng_payload *payload)
+{
+       int ret;
+       struct lttng_event_context_comm context_comm = { 0 };
+
+       assert(context);
+       assert(payload);
+
+       context_comm.type = (uint32_t) context->ctx;
+
+       /* Header */
+       ret = lttng_dynamic_buffer_append(
+                       &payload->buffer, &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, payload);
+               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, payload);
+               break;
+       default:
+               /* Nothing else to serialize. */
+               break;
+       }
+
+       if (ret) {
+               goto end;
+       }
+
+end:
+       return ret;
+}
+
+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 b145aeb061712e545066f5bc31041558893878a3..33098d869eb1e2aa99700910eb0b54890b2ed9eb 100644 (file)
@@ -393,9 +393,7 @@ struct lttcomm_session_msg {
                /* Context */
                struct {
                        char channel_name[LTTNG_SYMBOL_NAME_LEN];
-                       struct lttng_event_context ctx;
-                       uint32_t provider_name_len;
-                       uint32_t context_name_len;
+                       uint32_t length;
                } LTTNG_PACKED context;
                /* Use by register_consumer */
                struct {
index fc1d272bf84a449aabadcdb1c1d2b509dc3b08fe..b596e760f3d159d0778484881fedef6e5b727db4 100644 (file)
@@ -919,9 +919,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 lttcomm_session_msg lsm = { .cmd_type = LTTNG_ADD_CONTEXT };
+       struct lttng_payload payload;
+
+       lttng_payload_init(&payload);
 
        /* Safety check. Both are mandatory. */
        if (handle == NULL || ctx == NULL) {
@@ -929,8 +930,11 @@ int lttng_add_context(struct lttng_handle *handle,
                goto end;
        }
 
-       memset(&lsm, 0, sizeof(lsm));
-       lsm.cmd_type = LTTNG_ADD_CONTEXT;
+       ret = lttng_dynamic_buffer_set_size(&payload.buffer, sizeof(lsm));
+       if (ret) {
+               ret = -LTTNG_ERR_NOMEM;
+               goto end;
+       }
 
        /* If no channel name, send empty string. */
        ret = lttng_strncpy(lsm.u.context.channel_name, channel_name ?: "",
@@ -948,55 +952,33 @@ 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;
+       ret = lttng_event_context_serialize(ctx, &payload);
+       if (ret) {
+               ret = -LTTNG_ERR_INVALID;
+               goto end;
+       }
 
-               if (!provider_name || !ctx_name) {
-                       ret = -LTTNG_ERR_INVALID;
-                       goto end;
-               }
+       lsm.u.context.length = payload.buffer.size - sizeof(lsm);
 
-               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;
+       /* Update message header. */
+       memcpy(payload.buffer.data, &lsm, sizeof(lsm));
 
-               len = provider_len + ctx_len;
-               buf = zmalloc(len);
-               if (!buf) {
-                       ret = -LTTNG_ERR_NOMEM;
+       {
+               struct lttng_payload reply;
+               struct lttng_payload_view payload_view =
+                               lttng_payload_view_from_payload(&payload, 0,
+                               -1);
+
+               lttng_payload_init(&reply);
+               ret = lttng_ctl_ask_sessiond_payload(&payload_view, &reply);
+               lttng_payload_reset(&reply);
+               if (ret) {
                        goto end;
                }
-
-               memcpy(buf, provider_name, provider_len);
-               memcpy(buf + provider_len, ctx_name, ctx_len);
-       }
-       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;
        }
 
-       ret = lttng_ctl_ask_sessiond_varlen_no_cmd_header(&lsm, buf, len, NULL);
 end:
-       free(buf);
+       lttng_payload_reset(&payload);
        return ret;
 }
 
This page took 0.037807 seconds and 4 git commands to generate.