From 0e7b45661dabc88c533f4f322615217410ce68db Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Wed, 24 Nov 2021 15:56:16 -0500 Subject: [PATCH] Validate channel context mismatch across UST applications MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Observed issue ============== Applications traced with LTTng-UST are expected to all provide the exact same layout for their channel's context fields, else it leads to corrupted traces. This is only enforced within LTTng-UST. There is nothing in the session daemon that prevents this scenario, and it is only observable when reading the corrupted trace. This makes the entire trace unreadable from the point where it is corrupted. Cause ===== Even though LTTng-UST sends the entire description of its context fields along with the channel registration notification, there is no validation of the context fields' content against the context fields present in the ust registry. Solution ======== Validate each registered UST channel context fields against the fields present in the registry. Reject the application if there is a mismatch. Known drawbacks =============== None. Signed-off-by: Mathieu Desnoyers Signed-off-by: Jérémie Galarneau Change-Id: I8b49032bf4f766e549dfccfafdce8cddcbb2873f --- src/bin/lttng-sessiond/ust-app.c | 20 ++++++++++++++-- src/bin/lttng-sessiond/ust-field-utils.c | 30 ++++++++++++++++++++++++ src/bin/lttng-sessiond/ust-field-utils.h | 9 +++++++ src/bin/lttng-sessiond/ust-registry.c | 14 +++-------- 4 files changed, 60 insertions(+), 13 deletions(-) diff --git a/src/bin/lttng-sessiond/ust-app.c b/src/bin/lttng-sessiond/ust-app.c index ddc7c2336..808a5dfcb 100644 --- a/src/bin/lttng-sessiond/ust-app.c +++ b/src/bin/lttng-sessiond/ust-app.c @@ -34,6 +34,8 @@ #include "lttng-sessiond.h" #include "notification-thread-commands.h" #include "rotate.h" +#include "event.h" +#include "ust-field-utils.h" struct lttng_ht *ust_app_ht; struct lttng_ht *ust_app_ht_by_sock; @@ -5493,6 +5495,9 @@ static int reply_ust_register_channel(int sock, int cobjd, chan_reg = ust_registry_channel_find(registry, chan_reg_key); assert(chan_reg); + /* Channel id is set during the object creation. */ + chan_id = chan_reg->chan_id; + if (!chan_reg->register_done) { /* * TODO: eventually use the registry event count for @@ -5507,9 +5512,20 @@ static int reply_ust_register_channel(int sock, int cobjd, } else { /* Get current already assigned values. */ type = chan_reg->header_type; + + /* + * Validate that the context fields match between + * registry and newcoming application. + */ + if (!match_lttng_ust_ctl_field_array(chan_reg->ctx_fields, + chan_reg->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 = chan_reg->chan_id; /* Append to metadata */ if (!chan_reg->metadata_dumped) { diff --git a/src/bin/lttng-sessiond/ust-field-utils.c b/src/bin/lttng-sessiond/ust-field-utils.c index 954581d3c..cef026156 100644 --- a/src/bin/lttng-sessiond/ust-field-utils.c +++ b/src/bin/lttng-sessiond/ust-field-utils.c @@ -278,3 +278,33 @@ int match_ustctl_field(const struct ustctl_field *first, no_match: return false; } + +/* + * Compare two arrays of UST fields. + * Return true if both arrays have identical field definitions, false otherwise. + */ +bool match_lttng_ust_ctl_field_array(const struct ustctl_field *first, + size_t nr_first, + const struct ustctl_field *second, + size_t nr_second) +{ + size_t i; + const size_t nr_fields = nr_first; + + /* Compare the array lengths. */ + if (nr_first != nr_second) { + goto no_match; + } + + /* Compare each field individually. */ + for (i = 0; i < nr_fields; i++) { + if (!match_ustctl_field(&first[i], &second[i])) { + goto no_match; + } + } + + return true; + +no_match: + return false; +} diff --git a/src/bin/lttng-sessiond/ust-field-utils.h b/src/bin/lttng-sessiond/ust-field-utils.h index 286111f08..2f7530330 100644 --- a/src/bin/lttng-sessiond/ust-field-utils.h +++ b/src/bin/lttng-sessiond/ust-field-utils.h @@ -17,4 +17,13 @@ int match_ustctl_field(const struct ustctl_field *first, const struct ustctl_field *second); +/* + * Compare two arrays of UST fields. + * Return true if both arrays have identical field definitions, false otherwise. + */ +bool match_lttng_ust_ctl_field_array(const struct ustctl_field *first, + size_t nr_first, + const struct ustctl_field *second, + size_t nr_second); + #endif /* LTTNG_UST_FIELD_UTILS_H */ diff --git a/src/bin/lttng-sessiond/ust-registry.c b/src/bin/lttng-sessiond/ust-registry.c index 205eef6aa..5d2487cd2 100644 --- a/src/bin/lttng-sessiond/ust-registry.c +++ b/src/bin/lttng-sessiond/ust-registry.c @@ -20,7 +20,6 @@ #include "lttng-sessiond.h" #include "notification-thread-commands.h" - /* * Hash table match function for event in the registry. */ @@ -28,7 +27,6 @@ static int ht_match_event(struct cds_lfht_node *node, const void *_key) { const struct ust_registry_event *key; struct ust_registry_event *event; - int i; assert(node); assert(_key); @@ -47,18 +45,12 @@ static int ht_match_event(struct cds_lfht_node *node, const void *_key) goto no_match; } - /* Compare the number of fields. */ - if (event->nr_fields != key->nr_fields) { + /* Compare the arrays of fields. */ + if (!match_lttng_ust_ctl_field_array(event->fields, event->nr_fields, + key->fields, key->nr_fields)) { goto no_match; } - /* Compare each field individually. */ - for (i = 0; i < event->nr_fields; i++) { - if (!match_ustctl_field(&event->fields[i], &key->fields[i])) { - goto no_match; - } - } - /* Compare model URI. */ if (event->model_emf_uri != NULL && key->model_emf_uri == NULL) { goto no_match; -- 2.34.1