From a4a3d6bd4a06e907f9cec07456f42ab08d59829a Mon Sep 17 00:00:00 2001 From: Jonathan Rajotte Date: Wed, 12 Jan 2022 18:18:08 -0500 Subject: [PATCH] Fix: liblttng-ctl comm: lttng_event_context is not packed MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 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 Signed-off-by: Jérémie Galarneau Change-Id: Ieb400eab2a2df4070ff51cb2b44929d3ea945ce4 --- include/lttng/event-internal.h | 53 +++ src/bin/lttng-sessiond/client.c | 128 ++++---- src/bin/lttng-sessiond/cmd.c | 27 +- src/bin/lttng-sessiond/cmd.h | 5 +- src/bin/lttng-sessiond/context.c | 5 +- src/bin/lttng-sessiond/context.h | 5 +- src/common/event.c | 392 +++++++++++++++++++++++ src/common/sessiond-comm/sessiond-comm.h | 4 +- src/lib/lttng-ctl/lttng-ctl.c | 74 ++--- 9 files changed, 556 insertions(+), 137 deletions(-) diff --git a/include/lttng/event-internal.h b/include/lttng/event-internal.h index db6573535..eec294dec 100644 --- a/include/lttng/event-internal.h +++ b/include/lttng/event-internal.h @@ -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, diff --git a/src/bin/lttng-sessiond/client.c b/src/bin/lttng-sessiond/client.c index 82ace4902..86708d2e2 100644 --- a/src/bin/lttng-sessiond/client.c +++ b/src/bin/lttng-sessiond/client.c @@ -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: diff --git a/src/bin/lttng-sessiond/cmd.c b/src/bin/lttng-sessiond/cmd.c index 371bd68fd..74c505793 100644 --- a/src/bin/lttng-sessiond/cmd.c +++ b/src/bin/lttng-sessiond/cmd.c @@ -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; } diff --git a/src/bin/lttng-sessiond/cmd.h b/src/bin/lttng-sessiond/cmd.h index 27b10cb34..69389e5fa 100644 --- a/src/bin/lttng-sessiond/cmd.h +++ b/src/bin/lttng-sessiond/cmd.h @@ -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); diff --git a/src/bin/lttng-sessiond/context.c b/src/bin/lttng-sessiond/context.c index a3a12c533..35eefced3 100644 --- a/src/bin/lttng-sessiond/context.c +++ b/src/bin/lttng-sessiond/context.c @@ -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; diff --git a/src/bin/lttng-sessiond/context.h b/src/bin/lttng-sessiond/context.h index ed5fe2ca2..073a2e178 100644 --- a/src/bin/lttng-sessiond/context.h +++ b/src/bin/lttng-sessiond/context.h @@ -15,10 +15,11 @@ #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 */ diff --git a/src/common/event.c b/src/common/event.c index f6a24ef1b..1aaa1f0c0 100644 --- a/src/common/event.c +++ b/src/common/event.c @@ -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) { diff --git a/src/common/sessiond-comm/sessiond-comm.h b/src/common/sessiond-comm/sessiond-comm.h index b145aeb06..33098d869 100644 --- a/src/common/sessiond-comm/sessiond-comm.h +++ b/src/common/sessiond-comm/sessiond-comm.h @@ -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 { diff --git a/src/lib/lttng-ctl/lttng-ctl.c b/src/lib/lttng-ctl/lttng-ctl.c index fc1d272bf..b596e760f 100644 --- a/src/lib/lttng-ctl/lttng-ctl.c +++ b/src/lib/lttng-ctl/lttng-ctl.c @@ -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; } -- 2.34.1