Validate channel context mismatch across UST applications
authorMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Wed, 24 Nov 2021 20:56:16 +0000 (15:56 -0500)
committerJérémie Galarneau <jeremie.galarneau@efficios.com>
Fri, 17 Dec 2021 16:08:37 +0000 (11:08 -0500)
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 <mathieu.desnoyers@efficios.com>
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
Change-Id: I8b49032bf4f766e549dfccfafdce8cddcbb2873f

src/bin/lttng-sessiond/ust-app.c
src/bin/lttng-sessiond/ust-field-utils.c
src/bin/lttng-sessiond/ust-field-utils.h
src/bin/lttng-sessiond/ust-registry.c

index ddc7c2336bfac5cfa7029308eaec23b67f14d844..808a5dfcb31567e06e442f88ecafc92363e84b1c 100644 (file)
@@ -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) {
index 954581d3ce85cf6dfdfb3c53fa06bd82f6865c20..cef0261564c9034beef23846bd9d23b1521e4144 100644 (file)
@@ -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;
+}
index 286111f0880adeec5b26a44cb94f77fba878850c..2f753033054b4ff19f0937dc72ff43a93b5a84d9 100644 (file)
 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 */
index 205eef6aa625eccdde4426898e72d4f95c31d02c..5d2487cd2eca63f8de2d5bd08ea752daaea851a4 100644 (file)
@@ -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;
This page took 0.031428 seconds and 5 git commands to generate.