From fb2772932d3207bd9d340f34f41d822d9c0ff0a9 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.cpp | 19 +++++++++++--- src/bin/lttng-sessiond/ust-field-utils.cpp | 30 ++++++++++++++++++++++ src/bin/lttng-sessiond/ust-field-utils.h | 9 +++++++ src/bin/lttng-sessiond/ust-registry.cpp | 14 +++------- 4 files changed, 58 insertions(+), 14 deletions(-) diff --git a/src/bin/lttng-sessiond/ust-app.cpp b/src/bin/lttng-sessiond/ust-app.cpp index 712e57709..54cd4dea6 100644 --- a/src/bin/lttng-sessiond/ust-app.cpp +++ b/src/bin/lttng-sessiond/ust-app.cpp @@ -49,7 +49,7 @@ #include "rotate.h" #include "event.h" #include "event-notifier-error-accounting.h" - +#include "ust-field-utils.h" struct lttng_ht *ust_app_ht; struct lttng_ht *ust_app_ht_by_sock; @@ -6386,6 +6386,9 @@ 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; + if (!ust_reg_chan->register_done) { /* * TODO: eventually use the registry event count for @@ -6400,9 +6403,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) { diff --git a/src/bin/lttng-sessiond/ust-field-utils.cpp b/src/bin/lttng-sessiond/ust-field-utils.cpp index a89fade5e..a8f3da2ba 100644 --- a/src/bin/lttng-sessiond/ust-field-utils.cpp +++ b/src/bin/lttng-sessiond/ust-field-utils.cpp @@ -338,3 +338,33 @@ int match_lttng_ust_ctl_field(const struct lttng_ust_ctl_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 lttng_ust_ctl_field *first, + size_t nr_first, + const struct lttng_ust_ctl_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_lttng_ust_ctl_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 ea629d5d5..39cd50b48 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_lttng_ust_ctl_field(const struct lttng_ust_ctl_field *first, const struct lttng_ust_ctl_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 lttng_ust_ctl_field *first, + size_t nr_first, + const struct lttng_ust_ctl_field *second, + size_t nr_second); + #endif /* LTTNG_UST_FIELD_UTILS_H */ diff --git a/src/bin/lttng-sessiond/ust-registry.cpp b/src/bin/lttng-sessiond/ust-registry.cpp index 173465203..088e8d64f 100644 --- a/src/bin/lttng-sessiond/ust-registry.cpp +++ b/src/bin/lttng-sessiond/ust-registry.cpp @@ -19,7 +19,6 @@ #include "lttng-sessiond.h" #include "notification-thread-commands.h" - /* * Hash table match function for event in the registry. */ @@ -27,7 +26,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; LTTNG_ASSERT(node); LTTNG_ASSERT(_key); @@ -46,18 +44,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_lttng_ust_ctl_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