X-Git-Url: https://git.lttng.org/?a=blobdiff_plain;f=src%2Fbin%2Flttng-sessiond%2Fust-app.cpp;h=5cffdc9741012ec6cdc562ff56c2a11c8f75c8fa;hb=c9e313bc594f40a86eed237dce222c0fc99c957f;hp=ef0f696522694ce31a07e3c10d492ffb0043f03f;hpb=0f1b1d2510d23e9a2a4baa9e2642ef97a35ef83f;p=lttng-tools.git diff --git a/src/bin/lttng-sessiond/ust-app.cpp b/src/bin/lttng-sessiond/ust-app.cpp index ef0f69652..5cffdc974 100644 --- a/src/bin/lttng-sessiond/ust-app.cpp +++ b/src/bin/lttng-sessiond/ust-app.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 David Goulet + * Copyright (C) 2011 EfficiOS Inc. * Copyright (C) 2016 Jérémie Galarneau * * SPDX-License-Identifier: GPL-2.0-only @@ -21,35 +21,35 @@ #include #include -#include -#include -#include -#include +#include +#include +#include +#include #include -#include +#include #include #include -#include +#include #include -#include -#include - -#include "buffer-registry.h" -#include "condition-internal.h" -#include "fd-limit.h" -#include "health-sessiond.h" -#include "ust-app.h" -#include "ust-consumer.h" -#include "lttng-ust-ctl.h" -#include "lttng-ust-error.h" -#include "utils.h" -#include "session.h" -#include "lttng-sessiond.h" -#include "notification-thread-commands.h" -#include "rotate.h" -#include "event.h" -#include "event-notifier-error-accounting.h" - +#include +#include + +#include "buffer-registry.hpp" +#include "condition-internal.hpp" +#include "fd-limit.hpp" +#include "health-sessiond.hpp" +#include "ust-app.hpp" +#include "ust-consumer.hpp" +#include "lttng-ust-ctl.hpp" +#include "lttng-ust-error.hpp" +#include "utils.hpp" +#include "session.hpp" +#include "lttng-sessiond.hpp" +#include "notification-thread-commands.hpp" +#include "rotate.hpp" +#include "event.hpp" +#include "event-notifier-error-accounting.hpp" +#include "ust-field-utils.hpp" struct lttng_ht *ust_app_ht; struct lttng_ht *ust_app_ht_by_sock; @@ -287,6 +287,7 @@ void delete_ust_app_ctx(int sock, struct ust_app_ctx *ua_ctx, int ret; LTTNG_ASSERT(ua_ctx); + ASSERT_RCU_READ_LOCKED(); if (ua_ctx->obj) { pthread_mutex_lock(&app->sock_lock); @@ -321,6 +322,7 @@ void delete_ust_app_event(int sock, struct ust_app_event *ua_event, int ret; LTTNG_ASSERT(ua_event); + ASSERT_RCU_READ_LOCKED(); free(ua_event->filter); if (ua_event->exclusion != NULL) @@ -443,25 +445,20 @@ void delete_ust_app_stream(int sock, struct ust_app_stream *stream, struct ust_app *app) { LTTNG_ASSERT(stream); + ASSERT_RCU_READ_LOCKED(); (void) release_ust_app_stream(sock, stream, app); free(stream); } -/* - * We need to execute ht_destroy outside of RCU read-side critical - * section and outside of call_rcu thread, so we postpone its execution - * using ht_cleanup_push. It is simpler than to change the semantic of - * the many callers of delete_ust_app_session(). - */ static void delete_ust_app_channel_rcu(struct rcu_head *head) { struct ust_app_channel *ua_chan = caa_container_of(head, struct ust_app_channel, rcu_head); - ht_cleanup_push(ua_chan->ctx); - ht_cleanup_push(ua_chan->events); + lttng_ht_destroy(ua_chan->ctx); + lttng_ht_destroy(ua_chan->events); free(ua_chan); } @@ -549,6 +546,7 @@ void delete_ust_app_channel(int sock, struct ust_app_channel *ua_chan, struct ust_registry_session *registry; LTTNG_ASSERT(ua_chan); + ASSERT_RCU_READ_LOCKED(); DBG3("UST app deleting channel %s", ua_chan->name); @@ -670,6 +668,7 @@ ssize_t ust_app_push_metadata(struct ust_registry_session *registry, LTTNG_ASSERT(registry); LTTNG_ASSERT(socket); + ASSERT_RCU_READ_LOCKED(); metadata_key = registry->metadata_key; @@ -806,6 +805,7 @@ static int push_metadata(struct ust_registry_session *registry, LTTNG_ASSERT(registry); LTTNG_ASSERT(consumer); + ASSERT_RCU_READ_LOCKED(); pthread_mutex_lock(®istry->lock); if (registry->metadata_closed) { @@ -895,19 +895,13 @@ end: return ret; } -/* - * We need to execute ht_destroy outside of RCU read-side critical - * section and outside of call_rcu thread, so we postpone its execution - * using ht_cleanup_push. It is simpler than to change the semantic of - * the many callers of delete_ust_app_session(). - */ static void delete_ust_app_session_rcu(struct rcu_head *head) { struct ust_app_session *ua_sess = caa_container_of(head, struct ust_app_session, rcu_head); - ht_cleanup_push(ua_sess->channels); + lttng_ht_destroy(ua_sess->channels); free(ua_sess); } @@ -927,6 +921,7 @@ void delete_ust_app_session(int sock, struct ust_app_session *ua_sess, struct ust_registry_session *registry; LTTNG_ASSERT(ua_sess); + ASSERT_RCU_READ_LOCKED(); pthread_mutex_lock(&ua_sess->lock); @@ -1004,8 +999,6 @@ void delete_ust_app_session(int sock, struct ust_app_session *ua_sess, /* * Delete a traceable application structure from the global list. Never call * this function outside of a call_rcu call. - * - * RCU read side lock should _NOT_ be held when calling this function. */ static void delete_ust_app(struct ust_app *app) @@ -1047,10 +1040,10 @@ void delete_ust_app(struct ust_app *app) rcu_read_unlock(); - ht_cleanup_push(app->sessions); - ht_cleanup_push(app->ust_sessions_objd); - ht_cleanup_push(app->ust_objd); - ht_cleanup_push(app->token_to_event_notifier_rule_ht); + lttng_ht_destroy(app->sessions); + lttng_ht_destroy(app->ust_sessions_objd); + lttng_ht_destroy(app->ust_objd); + lttng_ht_destroy(app->token_to_event_notifier_rule_ht); /* * This could be NULL if the event notifier setup failed (e.g the app @@ -1456,6 +1449,8 @@ struct ust_app *ust_app_find_by_sock(int sock) struct lttng_ht_node_ulong *node; struct lttng_ht_iter iter; + ASSERT_RCU_READ_LOCKED(); + lttng_ht_lookup(ust_app_ht_by_sock, (void *)((unsigned long) sock), &iter); node = lttng_ht_iter_get_node_ulong(&iter); if (node == NULL) { @@ -1478,6 +1473,8 @@ static struct ust_app *find_app_by_notify_sock(int sock) struct lttng_ht_node_ulong *node; struct lttng_ht_iter iter; + ASSERT_RCU_READ_LOCKED(); + lttng_ht_lookup(ust_app_ht_by_notify_sock, (void *)((unsigned long) sock), &iter); node = lttng_ht_iter_get_node_ulong(&iter); @@ -1546,6 +1543,7 @@ static struct ust_app_event_notifier_rule *find_ust_app_event_notifier_rule( struct ust_app_event_notifier_rule *event_notifier_rule = NULL; LTTNG_ASSERT(ht); + ASSERT_RCU_READ_LOCKED(); lttng_ht_lookup(ht, &token, &iter); node = lttng_ht_iter_get_node_u64(&iter); @@ -2000,7 +1998,7 @@ error: * Should be called with session mutex held. */ static -int create_ust_event(struct ust_app *app, struct ust_app_session *ua_sess, +int create_ust_event(struct ust_app *app, struct ust_app_channel *ua_chan, struct ust_app_event *ua_event) { int ret = 0; @@ -2151,7 +2149,7 @@ static int init_ust_event_notifier_from_event_rule( event_notifier->event.instrumentation = LTTNG_UST_ABI_TRACEPOINT; ret = lttng_strncpy(event_notifier->event.name, pattern, - LTTNG_UST_ABI_SYM_NAME_LEN - 1); + sizeof(event_notifier->event.name)); if (ret) { ERR("Failed to copy event rule pattern to notifier: pattern = '%s' ", pattern); @@ -2232,7 +2230,7 @@ static int create_ust_event_notifier(struct ust_app *app, ua_event_notifier_rule->handle = ua_event_notifier_rule->obj->handle; - DBG2("UST app event notifier %s created successfully: app = '%s': pid = %d), object = %p", + DBG2("UST app event notifier %s created successfully: app = '%s': pid = %d, object = %p", event_notifier.event.name, app->name, app->pid, ua_event_notifier_rule->obj); @@ -2823,6 +2821,7 @@ struct ust_app_ctx *find_ust_app_context(struct lttng_ht *ht, LTTNG_ASSERT(uctx); LTTNG_ASSERT(ht); + ASSERT_RCU_READ_LOCKED(); /* Lookup using the lttng_ust_context_type and a custom match fct. */ cds_lfht_lookup(ht->ht, ht->hash_fct((void *) uctx->ctx, lttng_ht_seed), @@ -2851,6 +2850,8 @@ int create_ust_app_channel_context(struct ust_app_channel *ua_chan, int ret = 0; struct ust_app_ctx *ua_ctx; + ASSERT_RCU_READ_LOCKED(); + DBG2("UST app adding context to channel %s", ua_chan->name); ua_ctx = find_ust_app_context(ua_chan->ctx, uctx); @@ -2885,8 +2886,8 @@ error: * Called with UST app session lock held. */ static -int enable_ust_app_event(struct ust_app_session *ua_sess, - struct ust_app_event *ua_event, struct ust_app *app) +int enable_ust_app_event(struct ust_app_event *ua_event, + struct ust_app *app) { int ret; @@ -2904,8 +2905,8 @@ error: /* * Disable on the tracer side a ust app event for the session and channel. */ -static int disable_ust_app_event(struct ust_app_session *ua_sess, - struct ust_app_event *ua_event, struct ust_app *app) +static int disable_ust_app_event(struct ust_app_event *ua_event, + struct ust_app *app) { int ret; @@ -2952,6 +2953,8 @@ static int enable_ust_app_channel(struct ust_app_session *ua_sess, struct lttng_ht_node_str *ua_chan_node; struct ust_app_channel *ua_chan; + ASSERT_RCU_READ_LOCKED(); + lttng_ht_lookup(ua_sess->channels, (void *)uchan->name, &iter); ua_chan_node = lttng_ht_iter_get_node_str(&iter); if (ua_chan_node == NULL) { @@ -2980,8 +2983,7 @@ error: */ static int do_consumer_create_channel(struct ltt_ust_session *usess, struct ust_app_session *ua_sess, struct ust_app_channel *ua_chan, - int bitness, struct ust_registry_session *registry, - uint64_t trace_archive_id) + int bitness, struct ust_registry_session *registry) { int ret; unsigned int nb_fd = 0; @@ -3317,7 +3319,7 @@ static int send_channel_uid_to_ust(struct buffer_reg_channel *buf_reg_chan, /* Send all streams to application. */ pthread_mutex_lock(&buf_reg_chan->stream_list_lock); cds_list_for_each_entry(reg_stream, &buf_reg_chan->streams, lnode) { - struct ust_app_stream stream; + struct ust_app_stream stream = {}; ret = duplicate_stream_object(reg_stream, &stream); if (ret < 0) { @@ -3334,8 +3336,8 @@ static int send_channel_uid_to_ust(struct buffer_reg_channel *buf_reg_chan, * Treat this the same way as an application * that is exiting. */ - WARN("Communication with application %d timed out on send_stream for stream \"%s\" of channel \"%s\" of session \"%" PRIu64 "\".", - app->pid, stream.name, + WARN("Communication with application %d timed out on send_stream for stream of channel \"%s\" of session \"%" PRIu64 "\".", + app->pid, ua_chan->name, ua_sess->tracing_id); ret = -ENOTCONN; @@ -3381,6 +3383,7 @@ static int create_channel_per_uid(struct ust_app *app, LTTNG_ASSERT(usess); LTTNG_ASSERT(ua_sess); LTTNG_ASSERT(ua_chan); + ASSERT_RCU_READ_LOCKED(); DBG("UST app creating channel %s with per UID buffers", ua_chan->name); @@ -3416,8 +3419,7 @@ static int create_channel_per_uid(struct ust_app *app, * ust app channel object with all streams and data object. */ ret = do_consumer_create_channel(usess, ua_sess, ua_chan, - app->bits_per_long, reg_uid->registry->reg.ust, - session->most_recent_chunk_id.value); + app->bits_per_long, reg_uid->registry->reg.ust); if (ret < 0) { ERR("Error creating UST channel \"%s\" on the consumer daemon", ua_chan->name); @@ -3531,8 +3533,7 @@ static int create_channel_per_pid(struct ust_app *app, /* Create and get channel on the consumer side. */ ret = do_consumer_create_channel(usess, ua_sess, ua_chan, - app->bits_per_long, registry, - session->most_recent_chunk_id.value); + app->bits_per_long, registry); if (ret < 0) { ERR("Error creating UST channel \"%s\" on the consumer daemon", ua_chan->name); @@ -3601,6 +3602,7 @@ static int ust_app_channel_send(struct ust_app *app, LTTNG_ASSERT(usess->active); LTTNG_ASSERT(ua_sess); LTTNG_ASSERT(ua_chan); + ASSERT_RCU_READ_LOCKED(); /* Handle buffer type before sending the channel to the application. */ switch (usess->buffer_type) { @@ -3651,7 +3653,8 @@ error: */ static int ust_app_channel_allocate(struct ust_app_session *ua_sess, struct ltt_ust_channel *uchan, - enum lttng_ust_abi_chan_type type, struct ltt_ust_session *usess, + enum lttng_ust_abi_chan_type type, + struct ltt_ust_session *usess __attribute__((unused)), struct ust_app_channel **ua_chanp) { int ret = 0; @@ -3659,6 +3662,8 @@ static int ust_app_channel_allocate(struct ust_app_session *ua_sess, struct lttng_ht_node_str *ua_chan_node; struct ust_app_channel *ua_chan; + ASSERT_RCU_READ_LOCKED(); + /* Lookup channel in the ust app session */ lttng_ht_lookup(ua_sess->channels, (void *)uchan->name, &iter); ua_chan_node = lttng_ht_iter_get_node_str(&iter); @@ -3699,13 +3704,15 @@ error: * Called with ust app session mutex held. */ static -int create_ust_app_event(struct ust_app_session *ua_sess, - struct ust_app_channel *ua_chan, struct ltt_ust_event *uevent, +int create_ust_app_event(struct ust_app_channel *ua_chan, + struct ltt_ust_event *uevent, struct ust_app *app) { int ret = 0; struct ust_app_event *ua_event; + ASSERT_RCU_READ_LOCKED(); + ua_event = alloc_ust_app_event(uevent->attr.name, &uevent->attr); if (ua_event == NULL) { /* Only failure mode of alloc_ust_app_event(). */ @@ -3715,7 +3722,7 @@ int create_ust_app_event(struct ust_app_session *ua_sess, shadow_copy_event(ua_event, uevent); /* Create it on the tracer side */ - ret = create_ust_event(app, ua_sess, ua_chan, ua_event); + ret = create_ust_event(app, ua_chan, ua_event); if (ret < 0) { /* * Not found previously means that it does not exist on the @@ -3760,6 +3767,8 @@ int create_ust_app_event_notifier_rule(struct lttng_trigger *trigger, int ret = 0; struct ust_app_event_notifier_rule *ua_event_notifier_rule; + ASSERT_RCU_READ_LOCKED(); + ua_event_notifier_rule = alloc_ust_app_event_notifier_rule(trigger); if (ua_event_notifier_rule == NULL) { ret = -ENOMEM; @@ -3788,7 +3797,7 @@ int create_ust_app_event_notifier_rule(struct lttng_trigger *trigger, lttng_ht_add_unique_u64(app->token_to_event_notifier_rule_ht, &ua_event_notifier_rule->node); - DBG2("UST app create token event rule completed: app = '%s', pid = %d), token = %" PRIu64, + DBG2("UST app create token event rule completed: app = '%s', pid = %d, token = %" PRIu64, app->name, app->pid, lttng_trigger_get_tracer_token(trigger)); goto end; @@ -3817,6 +3826,7 @@ static int create_ust_app_metadata(struct ust_app_session *ua_sess, LTTNG_ASSERT(ua_sess); LTTNG_ASSERT(app); LTTNG_ASSERT(consumer); + ASSERT_RCU_READ_LOCKED(); registry = get_session_registry(ua_sess); /* The UST app session is held registry shall not be null. */ @@ -4618,8 +4628,6 @@ error: /* * Free and clean all traceable apps of the global list. - * - * Should _NOT_ be called with RCU read-side lock held. */ void ust_app_clean_list(void) { @@ -4666,13 +4674,13 @@ void ust_app_clean_list(void) /* Destroy is done only when the ht is empty */ if (ust_app_ht) { - ht_cleanup_push(ust_app_ht); + lttng_ht_destroy(ust_app_ht); } if (ust_app_ht_by_sock) { - ht_cleanup_push(ust_app_ht_by_sock); + lttng_ht_destroy(ust_app_ht_by_sock); } if (ust_app_ht_by_notify_sock) { - ht_cleanup_push(ust_app_ht_by_notify_sock); + lttng_ht_destroy(ust_app_ht_by_notify_sock); } } @@ -4850,7 +4858,7 @@ int ust_app_disable_event_glb(struct ltt_ust_session *usess, continue; } - ret = disable_ust_app_event(ua_sess, ua_event, app); + ret = disable_ust_app_event(ua_event, app); if (ret < 0) { /* XXX: Report error someday... */ continue; @@ -5009,7 +5017,7 @@ int ust_app_enable_event_glb(struct ltt_ust_session *usess, goto next_app; } - ret = enable_ust_app_event(ua_sess, ua_event, app); + ret = enable_ust_app_event(ua_event, app); if (ret < 0) { pthread_mutex_unlock(&ua_sess->lock); goto error; @@ -5073,7 +5081,7 @@ int ust_app_create_event_glb(struct ltt_ust_session *usess, ua_chan = caa_container_of(ua_chan_node, struct ust_app_channel, node); - ret = create_ust_app_event(ua_sess, ua_chan, uevent, app); + ret = create_ust_app_event(ua_chan, uevent, app); pthread_mutex_unlock(&ua_sess->lock); if (ret < 0) { if (ret != -LTTNG_UST_ERR_EXIST) { @@ -5268,13 +5276,13 @@ int ust_app_stop_trace(struct ltt_ust_session *usess, struct ust_app *app) pthread_mutex_unlock(&app->sock_lock); if (ret < 0) { if (ret == -EPIPE || ret == -LTTNG_UST_ERR_EXITING) { - DBG3("UST app wait quiescent failed. Application is dead: pid= %d, sock = %d)", + DBG3("UST app wait quiescent failed. Application is dead: pid= %d, sock = %d", app->pid, app->sock); } else if (ret == -EAGAIN) { - WARN("UST app wait quiescent failed. Communication time out: pid= %d, sock = %d)", + WARN("UST app wait quiescent failed. Communication time out: pid= %d, sock = %d", app->pid, app->sock); } else { - ERR("UST app wait quiescent failed with ret %d: pid= %d, sock = %d)", + ERR("UST app wait quiescent failed with ret %d: pid= %d, sock = %d", ret, app->pid, app->sock); } } @@ -5626,13 +5634,13 @@ static int destroy_trace(struct ltt_ust_session *usess, struct ust_app *app) pthread_mutex_unlock(&app->sock_lock); if (ret < 0) { if (ret == -EPIPE || ret == -LTTNG_UST_ERR_EXITING) { - DBG3("UST app wait quiescent failed. Application is dead: pid= %d, sock = %d)", + DBG3("UST app wait quiescent failed. Application is dead: pid= %d, sock = %d", app->pid, app->sock); } else if (ret == -EAGAIN) { - WARN("UST app wait quiescent failed. Communication time out: pid= %d, sock = %d)", + WARN("UST app wait quiescent failed. Communication time out: pid= %d, sock = %d", app->pid, app->sock); } else { - ERR("UST app wait quiescent failed with ret %d: pid= %d, sock = %d)", + ERR("UST app wait quiescent failed with ret %d: pid= %d, sock = %d", ret, app->pid, app->sock); } } @@ -5769,7 +5777,7 @@ end: static int ust_app_channel_synchronize_event(struct ust_app_channel *ua_chan, - struct ltt_ust_event *uevent, struct ust_app_session *ua_sess, + struct ltt_ust_event *uevent, struct ust_app *app) { int ret = 0; @@ -5778,15 +5786,15 @@ int ust_app_channel_synchronize_event(struct ust_app_channel *ua_chan, ua_event = find_ust_app_event(ua_chan->events, uevent->attr.name, uevent->filter, uevent->attr.loglevel, uevent->exclusion); if (!ua_event) { - ret = create_ust_app_event(ua_sess, ua_chan, uevent, app); + ret = create_ust_app_event(ua_chan, uevent, app); if (ret < 0) { goto end; } } else { if (ua_event->enabled != uevent->enabled) { ret = uevent->enabled ? - enable_ust_app_event(ua_sess, ua_event, app) : - disable_ust_app_event(ua_sess, ua_event, app); + enable_ust_app_event(ua_event, app) : + disable_ust_app_event(ua_event, app); } } @@ -5806,6 +5814,8 @@ void ust_app_synchronize_event_notifier_rules(struct ust_app *app) struct ust_app_event_notifier_rule *event_notifier_rule; unsigned int count, i; + ASSERT_RCU_READ_LOCKED(); + if (!ust_app_supports_notifiers(app)) { goto end; } @@ -5957,6 +5967,7 @@ void ust_app_synchronize_all_channels(struct ltt_ust_session *usess, LTTNG_ASSERT(usess); LTTNG_ASSERT(ua_sess); LTTNG_ASSERT(app); + ASSERT_RCU_READ_LOCKED(); cds_lfht_for_each_entry(usess->domain_global.channels->ht, &uchan_iter, uchan, node.node) { @@ -5986,7 +5997,7 @@ void ust_app_synchronize_all_channels(struct ltt_ust_session *usess, cds_lfht_for_each_entry(uchan->events->ht, &uevent_iter, uevent, node.node) { ret = ust_app_channel_synchronize_event(ua_chan, - uevent, ua_sess, app); + uevent, app); if (ret) { goto end; } @@ -6086,6 +6097,7 @@ void ust_app_global_update(struct ltt_ust_session *usess, struct ust_app *app) { LTTNG_ASSERT(usess); LTTNG_ASSERT(usess->active); + ASSERT_RCU_READ_LOCKED(); DBG2("UST app global update for app sock %d for session id %" PRIu64, app->sock, usess->id); @@ -6120,7 +6132,9 @@ void ust_app_global_update(struct ltt_ust_session *usess, struct ust_app *app) */ void ust_app_global_update_event_notifier_rules(struct ust_app *app) { - DBG2("UST application global event notifier rules update: app = '%s', pid = %d)", + ASSERT_RCU_READ_LOCKED(); + + DBG2("UST application global event notifier rules update: app = '%s', pid = %d", app->name, app->pid); if (!app->compatible || !ust_app_supports_notifiers(app)) { @@ -6128,7 +6142,7 @@ void ust_app_global_update_event_notifier_rules(struct ust_app *app) } if (app->event_notifier_group.object == NULL) { - WARN("UST app global update of event notifiers for app skipped since communication handle is null: app = '%s' pid = %d)", + WARN("UST app global update of event notifiers for app skipped since communication handle is null: app = '%s', pid = %d", app->name, app->pid); return; } @@ -6282,6 +6296,7 @@ static struct ust_app_session *find_session_by_objd(struct ust_app *app, struct ust_app_session *ua_sess = NULL; LTTNG_ASSERT(app); + ASSERT_RCU_READ_LOCKED(); lttng_ht_lookup(app->ust_sessions_objd, (void *)((unsigned long) objd), &iter); node = lttng_ht_iter_get_node_ulong(&iter); @@ -6309,6 +6324,7 @@ static struct ust_app_channel *find_channel_by_objd(struct ust_app *app, struct ust_app_channel *ua_chan = NULL; LTTNG_ASSERT(app); + ASSERT_RCU_READ_LOCKED(); lttng_ht_lookup(app->ust_objd, (void *)((unsigned long) objd), &iter); node = lttng_ht_iter_get_node_ulong(&iter); @@ -6323,6 +6339,104 @@ error: return ua_chan; } +/* + * Fixup legacy context fields for comparison: + * - legacy array becomes array_nestable, + * - legacy struct becomes struct_nestable, + * - legacy variant becomes variant_nestable, + * legacy sequences are not emitted in LTTng-UST contexts. + */ +static int ust_app_fixup_legacy_context_fields(size_t *_nr_fields, + struct lttng_ust_ctl_field **_fields) +{ + struct lttng_ust_ctl_field *fields = *_fields, *new_fields = NULL; + size_t nr_fields = *_nr_fields, new_nr_fields = 0, i, j; + bool found = false; + int ret = 0; + + for (i = 0; i < nr_fields; i++) { + const struct lttng_ust_ctl_field *field = &fields[i]; + + switch (field->type.atype) { + case lttng_ust_ctl_atype_sequence: + ERR("Unexpected legacy sequence context."); + ret = -EINVAL; + goto end; + case lttng_ust_ctl_atype_array: + switch (field->type.u.legacy.array.elem_type.atype) { + case lttng_ust_ctl_atype_integer: + break; + default: + ERR("Unexpected legacy array element type in context."); + ret = -EINVAL; + goto end; + } + found = true; + /* One field for array_nested, one field for elem type. */ + new_nr_fields += 2; + break; + + case lttng_ust_ctl_atype_struct: /* Fallthrough */ + case lttng_ust_ctl_atype_variant: + found = true; + new_nr_fields++; + break; + default: + new_nr_fields++; + break; + } + } + if (!found) { + goto end; + } + new_fields = (struct lttng_ust_ctl_field *) zmalloc(sizeof(*new_fields) * new_nr_fields); + if (!new_fields) { + ret = -ENOMEM; + goto end; + } + for (i = 0, j = 0; i < nr_fields; i++, j++) { + const struct lttng_ust_ctl_field *field = &fields[i]; + struct lttng_ust_ctl_field *new_field = &new_fields[j]; + + switch (field->type.atype) { + case lttng_ust_ctl_atype_array: + /* One field for array_nested, one field for elem type. */ + strncpy(new_field->name, field->name, LTTNG_UST_ABI_SYM_NAME_LEN - 1); + new_field->type.atype = lttng_ust_ctl_atype_array_nestable; + new_field->type.u.array_nestable.length = field->type.u.legacy.array.length; + new_field->type.u.array_nestable.alignment = 0; + new_field = &new_fields[++j]; /* elem type */ + new_field->type.atype = field->type.u.legacy.array.elem_type.atype; + assert(new_field->type.atype == lttng_ust_ctl_atype_integer); + new_field->type.u.integer = field->type.u.legacy.array.elem_type.u.basic.integer; + break; + case lttng_ust_ctl_atype_struct: + strncpy(new_field->name, field->name, LTTNG_UST_ABI_SYM_NAME_LEN - 1); + new_field->type.atype = lttng_ust_ctl_atype_struct_nestable; + new_field->type.u.struct_nestable.nr_fields = field->type.u.legacy._struct.nr_fields; + new_field->type.u.struct_nestable.alignment = 0; + break; + case lttng_ust_ctl_atype_variant: + strncpy(new_field->name, field->name, LTTNG_UST_ABI_SYM_NAME_LEN - 1); + new_field->type.atype = lttng_ust_ctl_atype_variant_nestable; + new_field->type.u.variant_nestable.nr_choices = field->type.u.legacy.variant.nr_choices; + strncpy(new_field->type.u.variant_nestable.tag_name, + field->type.u.legacy.variant.tag_name, + LTTNG_UST_ABI_SYM_NAME_LEN - 1); + new_field->type.u.variant_nestable.alignment = 0; + break; + default: + *new_field = *field; + break; + } + } + free(fields); + *_fields = new_fields; + *_nr_fields = new_nr_fields; +end: + return ret; +} + /* * Reply to a register channel notification from an application on the notify * socket. The channel metadata is also created. @@ -6337,7 +6451,7 @@ static int reply_ust_register_channel(int sock, int cobjd, int ret, ret_code = 0; uint32_t chan_id; uint64_t chan_reg_key; - enum lttng_ust_ctl_channel_header type; + enum lttng_ust_ctl_channel_header type = LTTNG_UST_CTL_CHANNEL_HEADER_UNKNOWN; struct ust_app *app; struct ust_app_channel *ua_chan; struct ust_app_session *ua_sess; @@ -6386,6 +6500,16 @@ static int reply_ust_register_channel(int sock, int cobjd, ust_reg_chan = ust_registry_channel_find(registry, chan_reg_key); LTTNG_ASSERT(ust_reg_chan); + /* Channel id is set during the object creation. */ + chan_id = ust_reg_chan->chan_id; + + ret = ust_app_fixup_legacy_context_fields(&nr_fields, &fields); + if (ret < 0) { + ERR("Registering application channel due to legacy context fields fixup error: pid = %d, sock = %d", + app->pid, app->sock); + ret_code = -EINVAL; + goto reply; + } if (!ust_reg_chan->register_done) { /* * TODO: eventually use the registry event count for @@ -6400,9 +6524,19 @@ static int reply_ust_register_channel(int sock, int cobjd, } else { /* Get current already assigned values. */ type = ust_reg_chan->header_type; + /* + * Validate that the context fields match between + * registry and newcoming application. + */ + if (!match_lttng_ust_ctl_field_array(ust_reg_chan->ctx_fields, + ust_reg_chan->nr_ctx_fields, + fields, nr_fields)) { + ERR("Registering application channel due to context field mismatch: pid = %d, sock = %d", + app->pid, app->sock); + ret_code = -EINVAL; + goto reply; + } } - /* Channel id is set during the object creation. */ - chan_id = ust_reg_chan->chan_id; /* Append to metadata */ if (!ust_reg_chan->metadata_dumped) { @@ -6728,7 +6862,7 @@ int ust_app_recv_notify(int sock) WARN("UST app recv channel failed. Communication time out: sock = %d", sock); } else { - ERR("UST app recv channel failed with ret %d: sock = %d)", + ERR("UST app recv channel failed with ret %d: sock = %d", ret, sock); } goto error; @@ -6887,7 +7021,7 @@ void ust_app_destroy(struct ust_app *app) */ enum lttng_error_code ust_app_snapshot_record( const struct ltt_ust_session *usess, - const struct consumer_output *output, int wait, + const struct consumer_output *output, uint64_t nb_packets_per_stream) { int ret = 0; @@ -6947,8 +7081,7 @@ enum lttng_error_code ust_app_snapshot_record( buf_reg_chan, node.node) { status = consumer_snapshot_channel(socket, buf_reg_chan->consumer_key, - output, 0, usess->uid, - usess->gid, &trace_path[consumer_path_offset], wait, + output, 0, &trace_path[consumer_path_offset], nb_packets_per_stream); if (status != LTTNG_OK) { goto error; @@ -6956,8 +7089,7 @@ enum lttng_error_code ust_app_snapshot_record( } status = consumer_snapshot_channel(socket, reg->registry->reg.ust->metadata_key, output, 1, - usess->uid, usess->gid, &trace_path[consumer_path_offset], - wait, 0); + &trace_path[consumer_path_offset], 0); if (status != LTTNG_OK) { goto error; } @@ -7010,9 +7142,7 @@ enum lttng_error_code ust_app_snapshot_record( ua_chan, node.node) { status = consumer_snapshot_channel(socket, ua_chan->key, output, 0, - lttng_credentials_get_uid(&ua_sess->effective_credentials), - lttng_credentials_get_gid(&ua_sess->effective_credentials), - &trace_path[consumer_path_offset], wait, + &trace_path[consumer_path_offset], nb_packets_per_stream); switch (status) { case LTTNG_OK: @@ -7031,9 +7161,7 @@ enum lttng_error_code ust_app_snapshot_record( } status = consumer_snapshot_channel(socket, registry->metadata_key, output, 1, - lttng_credentials_get_uid(&ua_sess->effective_credentials), - lttng_credentials_get_gid(&ua_sess->effective_credentials), - &trace_path[consumer_path_offset], wait, 0); + &trace_path[consumer_path_offset], 0); switch (status) { case LTTNG_OK: break; @@ -7326,7 +7454,6 @@ enum lttng_error_code ust_app_rotate_session(struct ltt_session *session) buf_reg_chan, node.node) { ret = consumer_rotate_channel(socket, buf_reg_chan->consumer_key, - usess->uid, usess->gid, usess->consumer, /* is_metadata_channel */ false); if (ret < 0) { @@ -7352,7 +7479,6 @@ enum lttng_error_code ust_app_rotate_session(struct ltt_session *session) ret = consumer_rotate_channel(socket, reg->registry->reg.ust->metadata_key, - usess->uid, usess->gid, usess->consumer, /* is_metadata_channel */ true); if (ret < 0) { @@ -7396,8 +7522,6 @@ enum lttng_error_code ust_app_rotate_session(struct ltt_session *session) ua_chan, node.node) { ret = consumer_rotate_channel(socket, ua_chan->key, - lttng_credentials_get_uid(&ua_sess->effective_credentials), - lttng_credentials_get_gid(&ua_sess->effective_credentials), ua_sess->consumer, /* is_metadata_channel */ false); if (ret < 0) { @@ -7413,8 +7537,6 @@ enum lttng_error_code ust_app_rotate_session(struct ltt_session *session) (void) push_metadata(registry, usess->consumer); ret = consumer_rotate_channel(socket, registry->metadata_key, - lttng_credentials_get_uid(&ua_sess->effective_credentials), - lttng_credentials_get_gid(&ua_sess->effective_credentials), ua_sess->consumer, /* is_metadata_channel */ true); if (ret < 0) {