diff options
| author | Peter Marko <peter.marko@siemens.com> | 2024-06-09 00:16:33 +0200 |
|---|---|---|
| committer | Steve Sakoman <steve@sakoman.com> | 2024-06-26 05:04:39 -0700 |
| commit | f27a1997b6f48f77c5085ce9b6572494e7dd864e (patch) | |
| tree | e45622fee6af51e3be072d8dec9c4844f28df167 /meta | |
| parent | 35a517b7bd56a60acb85604fa335b5c6a21a698f (diff) | |
| download | poky-f27a1997b6f48f77c5085ce9b6572494e7dd864e.tar.gz | |
glib-2.0: patch CVE-2024-34397
This is taken from https://gitlab.gnome.org/GNOME/glib/-/merge_requests/4047
That MR was not merged as 2.72 is inactive branch now.
But it can be used by distributions, like Ubuntu did under
https://git.launchpad.net/ubuntu/+source/glib2.0/commit/?h=applied/ubuntu/jammy-security&id=94425c909b037c63c9dbbf72015f628ed4ad4aea
(From OE-Core rev: 95e8507848e3143eca83621f6572439e22f60bd4)
Signed-off-by: Peter Marko <peter.marko@siemens.com>
Signed-off-by: Steve Sakoman <steve@sakoman.com>
Diffstat (limited to 'meta')
19 files changed, 3374 insertions, 0 deletions
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2024-34397_01.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2024-34397_01.patch new file mode 100644 index 0000000000..6a476fe307 --- /dev/null +++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2024-34397_01.patch | |||
| @@ -0,0 +1,129 @@ | |||
| 1 | From c4e3022918565253ffad52449dd0e648b6d772c7 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Philip Withnall <pwithnall@gnome.org> | ||
| 3 | Date: Tue, 28 Nov 2023 12:58:20 +0000 | ||
| 4 | Subject: [PATCH 01/18] gdbusmessage: Cache the arg0 value | ||
| 5 | MIME-Version: 1.0 | ||
| 6 | Content-Type: text/plain; charset=UTF-8 | ||
| 7 | Content-Transfer-Encoding: 8bit | ||
| 8 | |||
| 9 | Technically we can’t rely on it being kept alive by the `message->body` | ||
| 10 | pointer, unless we can guarantee that the `GVariant` is always | ||
| 11 | serialised. That’s not necessarily the case, so keep a separate ref on | ||
| 12 | the arg0 value at all times. | ||
| 13 | |||
| 14 | This avoids a potential use-after-free. | ||
| 15 | |||
| 16 | Spotted by Thomas Haller in | ||
| 17 | https://gitlab.gnome.org/GNOME/glib/-/merge_requests/3720#note_1924707. | ||
| 18 | |||
| 19 | [This is a prerequisite for having tests pass after fixing the | ||
| 20 | vulnerability described in glib#3268, because after fixing that | ||
| 21 | vulnerability, the use-after-free genuinely does happen during | ||
| 22 | regression testing. -smcv] | ||
| 23 | |||
| 24 | Signed-off-by: Philip Withnall <pwithnall@gnome.org> | ||
| 25 | |||
| 26 | Helps: #3183, #3268 | ||
| 27 | (cherry picked from commit 10e9a917be7fb92b6b27837ef7a7f1d0be6095d5) | ||
| 28 | |||
| 29 | CVE: CVE-2024-34397 | ||
| 30 | Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/glib/-/commit/c4e3022918565253ffad52449dd0e648b6d772c7] | ||
| 31 | Signed-off-by: Peter Marko <peter.marko@siemens.com> | ||
| 32 | --- | ||
| 33 | gio/gdbusmessage.c | 35 ++++++++++++++++++++++------------- | ||
| 34 | 1 file changed, 22 insertions(+), 13 deletions(-) | ||
| 35 | |||
| 36 | diff --git a/gio/gdbusmessage.c b/gio/gdbusmessage.c | ||
| 37 | index ecef6cd3c..3fd1151ca 100644 | ||
| 38 | --- a/gio/gdbusmessage.c | ||
| 39 | +++ b/gio/gdbusmessage.c | ||
| 40 | @@ -506,6 +506,7 @@ struct _GDBusMessage | ||
| 41 | guint32 serial; | ||
| 42 | GHashTable *headers; | ||
| 43 | GVariant *body; | ||
| 44 | + GVariant *arg0_cache; /* (nullable) (owned) */ | ||
| 45 | #ifdef G_OS_UNIX | ||
| 46 | GUnixFDList *fd_list; | ||
| 47 | #endif | ||
| 48 | @@ -528,6 +529,7 @@ g_dbus_message_finalize (GObject *object) | ||
| 49 | g_hash_table_unref (message->headers); | ||
| 50 | if (message->body != NULL) | ||
| 51 | g_variant_unref (message->body); | ||
| 52 | + g_clear_pointer (&message->arg0_cache, g_variant_unref); | ||
| 53 | #ifdef G_OS_UNIX | ||
| 54 | if (message->fd_list != NULL) | ||
| 55 | g_object_unref (message->fd_list); | ||
| 56 | @@ -1163,6 +1165,7 @@ g_dbus_message_set_body (GDBusMessage *message, | ||
| 57 | if (body == NULL) | ||
| 58 | { | ||
| 59 | message->body = NULL; | ||
| 60 | + message->arg0_cache = NULL; | ||
| 61 | g_dbus_message_set_signature (message, NULL); | ||
| 62 | } | ||
| 63 | else | ||
| 64 | @@ -1173,6 +1176,12 @@ g_dbus_message_set_body (GDBusMessage *message, | ||
| 65 | |||
| 66 | message->body = g_variant_ref_sink (body); | ||
| 67 | |||
| 68 | + if (g_variant_is_of_type (message->body, G_VARIANT_TYPE_TUPLE) && | ||
| 69 | + g_variant_n_children (message->body) > 0) | ||
| 70 | + message->arg0_cache = g_variant_get_child_value (message->body, 0); | ||
| 71 | + else | ||
| 72 | + message->arg0_cache = NULL; | ||
| 73 | + | ||
| 74 | type_string = g_variant_get_type_string (body); | ||
| 75 | type_string_len = strlen (type_string); | ||
| 76 | g_assert (type_string_len >= 2); | ||
| 77 | @@ -2325,6 +2334,14 @@ g_dbus_message_new_from_blob (guchar *blob, | ||
| 78 | 2, | ||
| 79 | &local_error); | ||
| 80 | g_variant_type_free (variant_type); | ||
| 81 | + | ||
| 82 | + if (message->body != NULL && | ||
| 83 | + g_variant_is_of_type (message->body, G_VARIANT_TYPE_TUPLE) && | ||
| 84 | + g_variant_n_children (message->body) > 0) | ||
| 85 | + message->arg0_cache = g_variant_get_child_value (message->body, 0); | ||
| 86 | + else | ||
| 87 | + message->arg0_cache = NULL; | ||
| 88 | + | ||
| 89 | if (message->body == NULL) | ||
| 90 | goto fail; | ||
| 91 | } | ||
| 92 | @@ -3364,22 +3381,13 @@ g_dbus_message_set_signature (GDBusMessage *message, | ||
| 93 | const gchar * | ||
| 94 | g_dbus_message_get_arg0 (GDBusMessage *message) | ||
| 95 | { | ||
| 96 | - const gchar *ret; | ||
| 97 | - | ||
| 98 | g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL); | ||
| 99 | |||
| 100 | - ret = NULL; | ||
| 101 | + if (message->arg0_cache != NULL && | ||
| 102 | + g_variant_is_of_type (message->arg0_cache, G_VARIANT_TYPE_STRING)) | ||
| 103 | + return g_variant_get_string (message->arg0_cache, NULL); | ||
| 104 | |||
| 105 | - if (message->body != NULL && g_variant_is_of_type (message->body, G_VARIANT_TYPE_TUPLE)) | ||
| 106 | - { | ||
| 107 | - GVariant *item; | ||
| 108 | - item = g_variant_get_child_value (message->body, 0); | ||
| 109 | - if (g_variant_is_of_type (item, G_VARIANT_TYPE_STRING)) | ||
| 110 | - ret = g_variant_get_string (item, NULL); | ||
| 111 | - g_variant_unref (item); | ||
| 112 | - } | ||
| 113 | - | ||
| 114 | - return ret; | ||
| 115 | + return NULL; | ||
| 116 | } | ||
| 117 | |||
| 118 | /* ---------------------------------------------------------------------------------------------------- */ | ||
| 119 | @@ -3822,6 +3830,7 @@ g_dbus_message_copy (GDBusMessage *message, | ||
| 120 | * to just ref (as opposed to deep-copying) the GVariant instances | ||
| 121 | */ | ||
| 122 | ret->body = message->body != NULL ? g_variant_ref (message->body) : NULL; | ||
| 123 | + ret->arg0_cache = message->arg0_cache != NULL ? g_variant_ref (message->arg0_cache) : NULL; | ||
| 124 | g_hash_table_iter_init (&iter, message->headers); | ||
| 125 | while (g_hash_table_iter_next (&iter, &header_key, (gpointer) &header_value)) | ||
| 126 | g_hash_table_insert (ret->headers, header_key, g_variant_ref (header_value)); | ||
| 127 | -- | ||
| 128 | 2.30.2 | ||
| 129 | |||
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2024-34397_02.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2024-34397_02.patch new file mode 100644 index 0000000000..aecc1686d5 --- /dev/null +++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2024-34397_02.patch | |||
| @@ -0,0 +1,62 @@ | |||
| 1 | From c805fd3862baaa114d1cceee27cc931264894c98 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Simon McVittie <smcv@collabora.com> | ||
| 3 | Date: Wed, 1 May 2024 15:51:42 +0100 | ||
| 4 | Subject: [PATCH 02/18] gdbusconnection: Make a backport of g_set_str() | ||
| 5 | available | ||
| 6 | |||
| 7 | A subsequent commit will need this. Copying all of g_set_str() into a | ||
| 8 | private header seems cleaner than replacing the call to it. | ||
| 9 | |||
| 10 | Helps: GNOME/glib#3268 | ||
| 11 | Signed-off-by: Simon McVittie <smcv@collabora.com> | ||
| 12 | |||
| 13 | CVE: CVE-2024-34397 | ||
| 14 | Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/glib/-/commit/c805fd3862baaa114d1cceee27cc931264894c98] | ||
| 15 | Signed-off-by: Peter Marko <peter.marko@siemens.com> | ||
| 16 | --- | ||
| 17 | gio/gdbusconnection.c | 1 + | ||
| 18 | glib/glib-private.h | 18 ++++++++++++++++++ | ||
| 19 | 2 files changed, 19 insertions(+) | ||
| 20 | |||
| 21 | diff --git a/gio/gdbusconnection.c b/gio/gdbusconnection.c | ||
| 22 | index 1159c2db4..82a68437b 100644 | ||
| 23 | --- a/gio/gdbusconnection.c | ||
| 24 | +++ b/gio/gdbusconnection.c | ||
| 25 | @@ -95,6 +95,7 @@ | ||
| 26 | #include <stdlib.h> | ||
| 27 | #include <string.h> | ||
| 28 | |||
| 29 | +#include "glib-private.h" | ||
| 30 | #include "gdbusauth.h" | ||
| 31 | #include "gdbusutils.h" | ||
| 32 | #include "gdbusaddress.h" | ||
| 33 | diff --git a/glib/glib-private.h b/glib/glib-private.h | ||
| 34 | index 943252f1b..f02828ff5 100644 | ||
| 35 | --- a/glib/glib-private.h | ||
| 36 | +++ b/glib/glib-private.h | ||
| 37 | @@ -201,4 +201,22 @@ GLibPrivateVTable *glib__private__ (void); | ||
| 38 | # define GLIB_DEFAULT_LOCALE "" | ||
| 39 | #endif | ||
| 40 | |||
| 41 | +/* Backported from GLib 2.78.x, where it is public API in gstrfuncs.h */ | ||
| 42 | +static inline gboolean | ||
| 43 | +g_set_str (char **str_pointer, | ||
| 44 | + const char *new_str) | ||
| 45 | +{ | ||
| 46 | + char *copy; | ||
| 47 | + | ||
| 48 | + if (*str_pointer == new_str || | ||
| 49 | + (*str_pointer && new_str && strcmp (*str_pointer, new_str) == 0)) | ||
| 50 | + return FALSE; | ||
| 51 | + | ||
| 52 | + copy = g_strdup (new_str); | ||
| 53 | + g_free (*str_pointer); | ||
| 54 | + *str_pointer = copy; | ||
| 55 | + | ||
| 56 | + return TRUE; | ||
| 57 | +} | ||
| 58 | + | ||
| 59 | #endif /* __GLIB_PRIVATE_H__ */ | ||
| 60 | -- | ||
| 61 | 2.30.2 | ||
| 62 | |||
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2024-34397_03.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2024-34397_03.patch new file mode 100644 index 0000000000..833e2b51a4 --- /dev/null +++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2024-34397_03.patch | |||
| @@ -0,0 +1,985 @@ | |||
| 1 | From 8b1d90457e2e72f1d7db7cb77b74754af3a5c4ef Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Simon McVittie <smcv@collabora.com> | ||
| 3 | Date: Fri, 8 Mar 2024 14:19:46 +0000 | ||
| 4 | Subject: [PATCH 03/18] tests: Add a data-driven test for signal subscriptions | ||
| 5 | |||
| 6 | This somewhat duplicates test_connection_signals(), but is easier to | ||
| 7 | extend to cover different scenarios. | ||
| 8 | |||
| 9 | Each scenario is tested three times: once with lower-level | ||
| 10 | GDBusConnection APIs, once with the higher-level GDBusProxy (which | ||
| 11 | cannot implement all of the subscription scenarios, so some message | ||
| 12 | counts are lower), and once with both (to check that delivery of the | ||
| 13 | same message to multiple destinations is handled appropriately). | ||
| 14 | |||
| 15 | [Backported to glib-2-74, resolving conflicts in gio/tests/meson.build] | ||
| 16 | Signed-off-by: Simon McVittie <smcv@collabora.com> | ||
| 17 | |||
| 18 | CVE: CVE-2024-34397 | ||
| 19 | Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/glib/-/commit/8b1d90457e2e72f1d7db7cb77b74754af3a5c4ef] | ||
| 20 | Signed-off-by: Peter Marko <peter.marko@siemens.com> | ||
| 21 | --- | ||
| 22 | gio/tests/gdbus-subscribe.c | 938 ++++++++++++++++++++++++++++++++++++ | ||
| 23 | gio/tests/meson.build | 1 + | ||
| 24 | 2 files changed, 939 insertions(+) | ||
| 25 | create mode 100644 gio/tests/gdbus-subscribe.c | ||
| 26 | |||
| 27 | diff --git a/gio/tests/gdbus-subscribe.c b/gio/tests/gdbus-subscribe.c | ||
| 28 | new file mode 100644 | ||
| 29 | index 000000000..3f53e1d7f | ||
| 30 | --- /dev/null | ||
| 31 | +++ b/gio/tests/gdbus-subscribe.c | ||
| 32 | @@ -0,0 +1,938 @@ | ||
| 33 | +/* | ||
| 34 | + * Copyright 2024 Collabora Ltd. | ||
| 35 | + * SPDX-License-Identifier: LGPL-2.1-or-later | ||
| 36 | + */ | ||
| 37 | + | ||
| 38 | +#include <gio/gio.h> | ||
| 39 | + | ||
| 40 | +#include "gdbus-tests.h" | ||
| 41 | + | ||
| 42 | +#define DBUS_SERVICE_DBUS "org.freedesktop.DBus" | ||
| 43 | +#define DBUS_PATH_DBUS "/org/freedesktop/DBus" | ||
| 44 | +#define DBUS_INTERFACE_DBUS DBUS_SERVICE_DBUS | ||
| 45 | + | ||
| 46 | +/* A signal that each connection emits to indicate that it has finished | ||
| 47 | + * emitting other signals */ | ||
| 48 | +#define FINISHED_PATH "/org/gtk/Test/Finished" | ||
| 49 | +#define FINISHED_INTERFACE "org.gtk.Test.Finished" | ||
| 50 | +#define FINISHED_SIGNAL "Finished" | ||
| 51 | + | ||
| 52 | +/* A signal emitted during testing */ | ||
| 53 | +#define EXAMPLE_PATH "/org/gtk/GDBus/ExampleInterface" | ||
| 54 | +#define EXAMPLE_INTERFACE "org.gtk.GDBus.ExampleInterface" | ||
| 55 | +#define FOO_SIGNAL "Foo" | ||
| 56 | + | ||
| 57 | +/* Log @s in a debug message. */ | ||
| 58 | +static inline const char * | ||
| 59 | +nonnull (const char *s, | ||
| 60 | + const char *if_null) | ||
| 61 | +{ | ||
| 62 | + return (s == NULL) ? if_null : s; | ||
| 63 | +} | ||
| 64 | + | ||
| 65 | +typedef enum | ||
| 66 | +{ | ||
| 67 | + TEST_CONN_NONE, | ||
| 68 | + TEST_CONN_FIRST, | ||
| 69 | + /* A connection that subscribes to signals */ | ||
| 70 | + TEST_CONN_SUBSCRIBER = TEST_CONN_FIRST, | ||
| 71 | + /* A mockup of a legitimate service */ | ||
| 72 | + TEST_CONN_SERVICE, | ||
| 73 | + /* A mockup of a second legitimate service */ | ||
| 74 | + TEST_CONN_SERVICE2, | ||
| 75 | + /* A connection that tries to trick @subscriber into processing its signals | ||
| 76 | + * as if they came from @service */ | ||
| 77 | + TEST_CONN_ATTACKER, | ||
| 78 | + NUM_TEST_CONNS | ||
| 79 | +} TestConn; | ||
| 80 | + | ||
| 81 | +static const char * const test_conn_descriptions[NUM_TEST_CONNS] = | ||
| 82 | +{ | ||
| 83 | + "(unused)", | ||
| 84 | + "subscriber", | ||
| 85 | + "service", | ||
| 86 | + "service 2", | ||
| 87 | + "attacker" | ||
| 88 | +}; | ||
| 89 | + | ||
| 90 | +typedef enum | ||
| 91 | +{ | ||
| 92 | + SUBSCRIPTION_MODE_CONN, | ||
| 93 | + SUBSCRIPTION_MODE_PROXY, | ||
| 94 | + SUBSCRIPTION_MODE_PARALLEL | ||
| 95 | +} SubscriptionMode; | ||
| 96 | + | ||
| 97 | +typedef struct | ||
| 98 | +{ | ||
| 99 | + GDBusProxy *received_by_proxy; | ||
| 100 | + TestConn sender; | ||
| 101 | + char *path; | ||
| 102 | + char *iface; | ||
| 103 | + char *member; | ||
| 104 | + GVariant *parameters; | ||
| 105 | + char *arg0; | ||
| 106 | + guint32 step; | ||
| 107 | +} ReceivedMessage; | ||
| 108 | + | ||
| 109 | +static void | ||
| 110 | +received_message_free (ReceivedMessage *self) | ||
| 111 | +{ | ||
| 112 | + | ||
| 113 | + g_clear_object (&self->received_by_proxy); | ||
| 114 | + g_free (self->path); | ||
| 115 | + g_free (self->iface); | ||
| 116 | + g_free (self->member); | ||
| 117 | + g_clear_pointer (&self->parameters, g_variant_unref); | ||
| 118 | + g_free (self->arg0); | ||
| 119 | + g_free (self); | ||
| 120 | +} | ||
| 121 | + | ||
| 122 | +typedef struct | ||
| 123 | +{ | ||
| 124 | + TestConn sender; | ||
| 125 | + TestConn unicast_to; | ||
| 126 | + const char *path; | ||
| 127 | + const char *iface; | ||
| 128 | + const char *member; | ||
| 129 | + const char *arg0; | ||
| 130 | + guint received_by_conn; | ||
| 131 | + guint received_by_proxy; | ||
| 132 | +} TestEmitSignal; | ||
| 133 | + | ||
| 134 | +typedef struct | ||
| 135 | +{ | ||
| 136 | + TestConn sender; | ||
| 137 | + const char *path; | ||
| 138 | + const char *iface; | ||
| 139 | + const char *member; | ||
| 140 | + const char *arg0; | ||
| 141 | + GDBusSignalFlags flags; | ||
| 142 | +} TestSubscribe; | ||
| 143 | + | ||
| 144 | +typedef enum | ||
| 145 | +{ | ||
| 146 | + TEST_ACTION_NONE = 0, | ||
| 147 | + TEST_ACTION_SUBSCRIBE, | ||
| 148 | + TEST_ACTION_EMIT_SIGNAL, | ||
| 149 | +} TestAction; | ||
| 150 | + | ||
| 151 | +typedef struct | ||
| 152 | +{ | ||
| 153 | + TestAction action; | ||
| 154 | + union { | ||
| 155 | + TestEmitSignal signal; | ||
| 156 | + TestSubscribe subscribe; | ||
| 157 | + } u; | ||
| 158 | +} TestStep; | ||
| 159 | + | ||
| 160 | +/* Arbitrary, extend as necessary to accommodate the longest test */ | ||
| 161 | +#define MAX_TEST_STEPS 10 | ||
| 162 | + | ||
| 163 | +typedef struct | ||
| 164 | +{ | ||
| 165 | + const char *description; | ||
| 166 | + TestStep steps[MAX_TEST_STEPS]; | ||
| 167 | +} TestPlan; | ||
| 168 | + | ||
| 169 | +static const TestPlan plan_simple = | ||
| 170 | +{ | ||
| 171 | + .description = "A broadcast is only received after subscribing to it", | ||
| 172 | + .steps = { | ||
| 173 | + { | ||
| 174 | + /* We don't receive a signal if we haven't subscribed yet */ | ||
| 175 | + .action = TEST_ACTION_EMIT_SIGNAL, | ||
| 176 | + .u.signal = { | ||
| 177 | + .sender = TEST_CONN_SERVICE, | ||
| 178 | + .path = EXAMPLE_PATH, | ||
| 179 | + .iface = EXAMPLE_INTERFACE, | ||
| 180 | + .member = FOO_SIGNAL, | ||
| 181 | + .received_by_conn = 0, | ||
| 182 | + .received_by_proxy = 0 | ||
| 183 | + }, | ||
| 184 | + }, | ||
| 185 | + { | ||
| 186 | + .action = TEST_ACTION_SUBSCRIBE, | ||
| 187 | + .u.subscribe = { | ||
| 188 | + .path = EXAMPLE_PATH, | ||
| 189 | + .iface = EXAMPLE_INTERFACE, | ||
| 190 | + }, | ||
| 191 | + }, | ||
| 192 | + { | ||
| 193 | + /* Now it works */ | ||
| 194 | + .action = TEST_ACTION_EMIT_SIGNAL, | ||
| 195 | + .u.signal = { | ||
| 196 | + .sender = TEST_CONN_SERVICE, | ||
| 197 | + .path = EXAMPLE_PATH, | ||
| 198 | + .iface = EXAMPLE_INTERFACE, | ||
| 199 | + .member = FOO_SIGNAL, | ||
| 200 | + .received_by_conn = 1, | ||
| 201 | + /* The proxy can't be used in this case, because it needs | ||
| 202 | + * a bus name to subscribe to */ | ||
| 203 | + .received_by_proxy = 0 | ||
| 204 | + }, | ||
| 205 | + }, | ||
| 206 | + }, | ||
| 207 | +}; | ||
| 208 | + | ||
| 209 | +static const TestPlan plan_broadcast_from_anyone = | ||
| 210 | +{ | ||
| 211 | + .description = "A subscription with NULL sender accepts broadcast and unicast", | ||
| 212 | + .steps = { | ||
| 213 | + { | ||
| 214 | + /* Subscriber wants to receive signals from anyone */ | ||
| 215 | + .action = TEST_ACTION_SUBSCRIBE, | ||
| 216 | + .u.subscribe = { | ||
| 217 | + .path = EXAMPLE_PATH, | ||
| 218 | + .iface = EXAMPLE_INTERFACE, | ||
| 219 | + }, | ||
| 220 | + }, | ||
| 221 | + { | ||
| 222 | + /* First service sends a broadcast */ | ||
| 223 | + .action = TEST_ACTION_EMIT_SIGNAL, | ||
| 224 | + .u.signal = { | ||
| 225 | + .sender = TEST_CONN_SERVICE, | ||
| 226 | + .path = EXAMPLE_PATH, | ||
| 227 | + .iface = EXAMPLE_INTERFACE, | ||
| 228 | + .member = FOO_SIGNAL, | ||
| 229 | + .received_by_conn = 1, | ||
| 230 | + .received_by_proxy = 0 | ||
| 231 | + }, | ||
| 232 | + }, | ||
| 233 | + { | ||
| 234 | + /* Second service also sends a broadcast */ | ||
| 235 | + .action = TEST_ACTION_EMIT_SIGNAL, | ||
| 236 | + .u.signal = { | ||
| 237 | + .sender = TEST_CONN_SERVICE2, | ||
| 238 | + .path = EXAMPLE_PATH, | ||
| 239 | + .iface = EXAMPLE_INTERFACE, | ||
| 240 | + .member = FOO_SIGNAL, | ||
| 241 | + .received_by_conn = 1, | ||
| 242 | + .received_by_proxy = 0 | ||
| 243 | + }, | ||
| 244 | + }, | ||
| 245 | + { | ||
| 246 | + /* First service sends a unicast signal */ | ||
| 247 | + .action = TEST_ACTION_EMIT_SIGNAL, | ||
| 248 | + .u.signal = { | ||
| 249 | + .sender = TEST_CONN_SERVICE, | ||
| 250 | + .unicast_to = TEST_CONN_SUBSCRIBER, | ||
| 251 | + .path = EXAMPLE_PATH, | ||
| 252 | + .iface = EXAMPLE_INTERFACE, | ||
| 253 | + .member = FOO_SIGNAL, | ||
| 254 | + .received_by_conn = 1, | ||
| 255 | + .received_by_proxy = 0 | ||
| 256 | + }, | ||
| 257 | + }, | ||
| 258 | + { | ||
| 259 | + /* Second service also sends a unicast signal */ | ||
| 260 | + .action = TEST_ACTION_EMIT_SIGNAL, | ||
| 261 | + .u.signal = { | ||
| 262 | + .sender = TEST_CONN_SERVICE2, | ||
| 263 | + .unicast_to = TEST_CONN_SUBSCRIBER, | ||
| 264 | + .path = EXAMPLE_PATH, | ||
| 265 | + .iface = EXAMPLE_INTERFACE, | ||
| 266 | + .member = FOO_SIGNAL, | ||
| 267 | + .received_by_conn = 1, | ||
| 268 | + .received_by_proxy = 0 | ||
| 269 | + }, | ||
| 270 | + }, | ||
| 271 | + }, | ||
| 272 | +}; | ||
| 273 | + | ||
| 274 | +static const TestPlan plan_match_twice = | ||
| 275 | +{ | ||
| 276 | + .description = "A message matching more than one subscription is received " | ||
| 277 | + "once per subscription", | ||
| 278 | + .steps = { | ||
| 279 | + { | ||
| 280 | + .action = TEST_ACTION_SUBSCRIBE, | ||
| 281 | + .u.subscribe = { | ||
| 282 | + .sender = TEST_CONN_SERVICE, | ||
| 283 | + .path = EXAMPLE_PATH, | ||
| 284 | + .iface = EXAMPLE_INTERFACE, | ||
| 285 | + }, | ||
| 286 | + }, | ||
| 287 | + { | ||
| 288 | + .action = TEST_ACTION_SUBSCRIBE, | ||
| 289 | + .u.subscribe = { | ||
| 290 | + .path = EXAMPLE_PATH, | ||
| 291 | + }, | ||
| 292 | + }, | ||
| 293 | + { | ||
| 294 | + .action = TEST_ACTION_SUBSCRIBE, | ||
| 295 | + .u.subscribe = { | ||
| 296 | + .iface = EXAMPLE_INTERFACE, | ||
| 297 | + }, | ||
| 298 | + }, | ||
| 299 | + { | ||
| 300 | + .action = TEST_ACTION_SUBSCRIBE, | ||
| 301 | + .u.subscribe = { | ||
| 302 | + .sender = TEST_CONN_SERVICE, | ||
| 303 | + .path = EXAMPLE_PATH, | ||
| 304 | + .iface = EXAMPLE_INTERFACE, | ||
| 305 | + }, | ||
| 306 | + }, | ||
| 307 | + { | ||
| 308 | + .action = TEST_ACTION_EMIT_SIGNAL, | ||
| 309 | + .u.signal = { | ||
| 310 | + .sender = TEST_CONN_SERVICE, | ||
| 311 | + .path = EXAMPLE_PATH, | ||
| 312 | + .iface = EXAMPLE_INTERFACE, | ||
| 313 | + .member = FOO_SIGNAL, | ||
| 314 | + .received_by_conn = 4, | ||
| 315 | + /* Only the first and last work with GDBusProxy */ | ||
| 316 | + .received_by_proxy = 2 | ||
| 317 | + }, | ||
| 318 | + }, | ||
| 319 | + }, | ||
| 320 | +}; | ||
| 321 | + | ||
| 322 | +static const TestPlan plan_limit_by_unique_name = | ||
| 323 | +{ | ||
| 324 | + .description = "A subscription via a unique name only accepts messages " | ||
| 325 | + "sent by that same unique name", | ||
| 326 | + .steps = { | ||
| 327 | + { | ||
| 328 | + /* Subscriber wants to receive signals from service */ | ||
| 329 | + .action = TEST_ACTION_SUBSCRIBE, | ||
| 330 | + .u.subscribe = { | ||
| 331 | + .sender = TEST_CONN_SERVICE, | ||
| 332 | + .path = EXAMPLE_PATH, | ||
| 333 | + .iface = EXAMPLE_INTERFACE, | ||
| 334 | + }, | ||
| 335 | + }, | ||
| 336 | + { | ||
| 337 | + /* Attacker wants to trick subscriber into thinking that service | ||
| 338 | + * sent a signal */ | ||
| 339 | + .action = TEST_ACTION_EMIT_SIGNAL, | ||
| 340 | + .u.signal = { | ||
| 341 | + .sender = TEST_CONN_ATTACKER, | ||
| 342 | + .path = EXAMPLE_PATH, | ||
| 343 | + .iface = EXAMPLE_INTERFACE, | ||
| 344 | + .member = FOO_SIGNAL, | ||
| 345 | + .received_by_conn = 0, | ||
| 346 | + .received_by_proxy = 0 | ||
| 347 | + }, | ||
| 348 | + }, | ||
| 349 | + { | ||
| 350 | + /* Attacker tries harder, by sending a signal unicast directly to | ||
| 351 | + * the subscriber */ | ||
| 352 | + .action = TEST_ACTION_EMIT_SIGNAL, | ||
| 353 | + .u.signal = { | ||
| 354 | + .sender = TEST_CONN_ATTACKER, | ||
| 355 | + .unicast_to = TEST_CONN_SUBSCRIBER, | ||
| 356 | + .path = EXAMPLE_PATH, | ||
| 357 | + .iface = EXAMPLE_INTERFACE, | ||
| 358 | + .member = FOO_SIGNAL, | ||
| 359 | + .received_by_conn = 0, | ||
| 360 | + .received_by_proxy = 0 | ||
| 361 | + }, | ||
| 362 | + }, | ||
| 363 | + { | ||
| 364 | + /* When the real service sends a signal, it should still get through */ | ||
| 365 | + .action = TEST_ACTION_EMIT_SIGNAL, | ||
| 366 | + .u.signal = { | ||
| 367 | + .sender = TEST_CONN_SERVICE, | ||
| 368 | + .path = EXAMPLE_PATH, | ||
| 369 | + .iface = EXAMPLE_INTERFACE, | ||
| 370 | + .member = FOO_SIGNAL, | ||
| 371 | + .received_by_conn = 1, | ||
| 372 | + .received_by_proxy = 1 | ||
| 373 | + }, | ||
| 374 | + }, | ||
| 375 | + }, | ||
| 376 | +}; | ||
| 377 | + | ||
| 378 | +typedef struct | ||
| 379 | +{ | ||
| 380 | + const TestPlan *plan; | ||
| 381 | + SubscriptionMode mode; | ||
| 382 | + GError *error; | ||
| 383 | + /* (element-type ReceivedMessage) */ | ||
| 384 | + GPtrArray *received; | ||
| 385 | + /* conns[TEST_CONN_NONE] is unused and remains NULL */ | ||
| 386 | + GDBusConnection *conns[NUM_TEST_CONNS]; | ||
| 387 | + /* Proxies on conns[TEST_CONN_SUBSCRIBER] */ | ||
| 388 | + GPtrArray *proxies; | ||
| 389 | + /* unique_names[TEST_CONN_NONE] is unused and remains NULL */ | ||
| 390 | + const char *unique_names[NUM_TEST_CONNS]; | ||
| 391 | + /* finished[TEST_CONN_NONE] is unused and remains FALSE */ | ||
| 392 | + gboolean finished[NUM_TEST_CONNS]; | ||
| 393 | + /* Remains 0 for any step that is not a subscription */ | ||
| 394 | + guint subscriptions[MAX_TEST_STEPS]; | ||
| 395 | + /* Number of times the signal from step n was received */ | ||
| 396 | + guint received_by_conn[MAX_TEST_STEPS]; | ||
| 397 | + /* Number of times the signal from step n was received */ | ||
| 398 | + guint received_by_proxy[MAX_TEST_STEPS]; | ||
| 399 | + guint finished_subscription; | ||
| 400 | +} Fixture; | ||
| 401 | + | ||
| 402 | +/* Wait for asynchronous messages from @conn to have been processed | ||
| 403 | + * by the message bus, as a sequence point so that we can make | ||
| 404 | + * "happens before" and "happens after" assertions relative to this. | ||
| 405 | + * The easiest way to achieve this is to call a message bus method that has | ||
| 406 | + * no arguments and wait for it to return: because the message bus processes | ||
| 407 | + * messages in-order, anything we sent before this must have been processed | ||
| 408 | + * by the time this call arrives. */ | ||
| 409 | +static void | ||
| 410 | +connection_wait_for_bus (GDBusConnection *conn) | ||
| 411 | +{ | ||
| 412 | + GError *error = NULL; | ||
| 413 | + GVariant *call_result; | ||
| 414 | + | ||
| 415 | + call_result = g_dbus_connection_call_sync (conn, | ||
| 416 | + DBUS_SERVICE_DBUS, | ||
| 417 | + DBUS_PATH_DBUS, | ||
| 418 | + DBUS_INTERFACE_DBUS, | ||
| 419 | + "GetId", | ||
| 420 | + NULL, /* arguments */ | ||
| 421 | + NULL, /* result type */ | ||
| 422 | + G_DBUS_CALL_FLAGS_NONE, | ||
| 423 | + -1, | ||
| 424 | + NULL, | ||
| 425 | + &error); | ||
| 426 | + g_assert_no_error (error); | ||
| 427 | + g_assert_nonnull (call_result); | ||
| 428 | + g_variant_unref (call_result); | ||
| 429 | +} | ||
| 430 | + | ||
| 431 | +/* | ||
| 432 | + * Called when the subscriber receives a message from any connection | ||
| 433 | + * announcing that it has emitted all the signals that it plans to emit. | ||
| 434 | + */ | ||
| 435 | +static void | ||
| 436 | +subscriber_finished_cb (GDBusConnection *conn, | ||
| 437 | + const char *sender_name, | ||
| 438 | + const char *path, | ||
| 439 | + const char *iface, | ||
| 440 | + const char *member, | ||
| 441 | + GVariant *parameters, | ||
| 442 | + void *user_data) | ||
| 443 | +{ | ||
| 444 | + Fixture *f = user_data; | ||
| 445 | + GDBusConnection *subscriber = f->conns[TEST_CONN_SUBSCRIBER]; | ||
| 446 | + guint i; | ||
| 447 | + | ||
| 448 | + g_assert_true (conn == subscriber); | ||
| 449 | + | ||
| 450 | + for (i = TEST_CONN_FIRST; i < G_N_ELEMENTS (f->conns); i++) | ||
| 451 | + { | ||
| 452 | + if (g_str_equal (sender_name, f->unique_names[i])) | ||
| 453 | + { | ||
| 454 | + g_assert_false (f->finished[i]); | ||
| 455 | + f->finished[i] = TRUE; | ||
| 456 | + | ||
| 457 | + g_test_message ("Received Finished signal from %s %s", | ||
| 458 | + test_conn_descriptions[i], sender_name); | ||
| 459 | + return; | ||
| 460 | + } | ||
| 461 | + } | ||
| 462 | + | ||
| 463 | + g_error ("Received Finished signal from unknown sender %s", sender_name); | ||
| 464 | +} | ||
| 465 | + | ||
| 466 | +/* | ||
| 467 | + * Called when we receive a signal, either via the GDBusProxy (proxy != NULL) | ||
| 468 | + * or via the GDBusConnection (proxy == NULL). | ||
| 469 | + */ | ||
| 470 | +static void | ||
| 471 | +fixture_received_signal (Fixture *f, | ||
| 472 | + GDBusProxy *proxy, | ||
| 473 | + const char *sender_name, | ||
| 474 | + const char *path, | ||
| 475 | + const char *iface, | ||
| 476 | + const char *member, | ||
| 477 | + GVariant *parameters) | ||
| 478 | +{ | ||
| 479 | + guint i; | ||
| 480 | + ReceivedMessage *received; | ||
| 481 | + | ||
| 482 | + /* Ignore the Finished signal if it matches a wildcard subscription */ | ||
| 483 | + if (g_str_equal (member, FINISHED_SIGNAL)) | ||
| 484 | + return; | ||
| 485 | + | ||
| 486 | + received = g_new0 (ReceivedMessage, 1); | ||
| 487 | + | ||
| 488 | + if (proxy != NULL) | ||
| 489 | + received->received_by_proxy = g_object_ref (proxy); | ||
| 490 | + else | ||
| 491 | + received->received_by_proxy = NULL; | ||
| 492 | + | ||
| 493 | + received->path = g_strdup (path); | ||
| 494 | + received->iface = g_strdup (iface); | ||
| 495 | + received->member = g_strdup (member); | ||
| 496 | + received->parameters = g_variant_ref (parameters); | ||
| 497 | + | ||
| 498 | + for (i = TEST_CONN_FIRST; i < G_N_ELEMENTS (f->conns); i++) | ||
| 499 | + { | ||
| 500 | + if (g_str_equal (sender_name, f->unique_names[i])) | ||
| 501 | + { | ||
| 502 | + received->sender = i; | ||
| 503 | + g_assert_false (f->finished[i]); | ||
| 504 | + break; | ||
| 505 | + } | ||
| 506 | + } | ||
| 507 | + | ||
| 508 | + g_assert_cmpint (received->sender, !=, TEST_CONN_NONE); | ||
| 509 | + | ||
| 510 | + g_test_message ("Signal received from %s %s via %s", | ||
| 511 | + test_conn_descriptions[received->sender], | ||
| 512 | + sender_name, | ||
| 513 | + proxy != NULL ? "proxy" : "connection"); | ||
| 514 | + g_test_message ("\tPath: %s", path); | ||
| 515 | + g_test_message ("\tInterface: %s", iface); | ||
| 516 | + g_test_message ("\tMember: %s", member); | ||
| 517 | + | ||
| 518 | + if (g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(su)"))) | ||
| 519 | + { | ||
| 520 | + g_variant_get (parameters, "(su)", &received->arg0, &received->step); | ||
| 521 | + g_test_message ("\tString argument 0: %s", received->arg0); | ||
| 522 | + g_test_message ("\tSent in step: %u", received->step); | ||
| 523 | + } | ||
| 524 | + else | ||
| 525 | + { | ||
| 526 | + g_assert_cmpstr (g_variant_get_type_string (parameters), ==, "(uu)"); | ||
| 527 | + g_variant_get (parameters, "(uu)", NULL, &received->step); | ||
| 528 | + g_test_message ("\tArgument 0: (not a string)"); | ||
| 529 | + g_test_message ("\tSent in step: %u", received->step); | ||
| 530 | + } | ||
| 531 | + | ||
| 532 | + g_ptr_array_add (f->received, g_steal_pointer (&received)); | ||
| 533 | +} | ||
| 534 | + | ||
| 535 | +static void | ||
| 536 | +proxy_signal_cb (GDBusProxy *proxy, | ||
| 537 | + const char *sender_name, | ||
| 538 | + const char *member, | ||
| 539 | + GVariant *parameters, | ||
| 540 | + void *user_data) | ||
| 541 | +{ | ||
| 542 | + Fixture *f = user_data; | ||
| 543 | + | ||
| 544 | + fixture_received_signal (f, proxy, sender_name, | ||
| 545 | + g_dbus_proxy_get_object_path (proxy), | ||
| 546 | + g_dbus_proxy_get_interface_name (proxy), | ||
| 547 | + member, parameters); | ||
| 548 | +} | ||
| 549 | + | ||
| 550 | +static void | ||
| 551 | +subscribed_signal_cb (GDBusConnection *conn, | ||
| 552 | + const char *sender_name, | ||
| 553 | + const char *path, | ||
| 554 | + const char *iface, | ||
| 555 | + const char *member, | ||
| 556 | + GVariant *parameters, | ||
| 557 | + void *user_data) | ||
| 558 | +{ | ||
| 559 | + Fixture *f = user_data; | ||
| 560 | + GDBusConnection *subscriber = f->conns[TEST_CONN_SUBSCRIBER]; | ||
| 561 | + | ||
| 562 | + g_assert_true (conn == subscriber); | ||
| 563 | + | ||
| 564 | + fixture_received_signal (f, NULL, sender_name, path, iface, member, parameters); | ||
| 565 | +} | ||
| 566 | + | ||
| 567 | +static void | ||
| 568 | +fixture_subscribe (Fixture *f, | ||
| 569 | + const TestSubscribe *subscribe, | ||
| 570 | + guint step_number) | ||
| 571 | +{ | ||
| 572 | + GDBusConnection *subscriber = f->conns[TEST_CONN_SUBSCRIBER]; | ||
| 573 | + const char *sender; | ||
| 574 | + | ||
| 575 | + if (subscribe->sender != TEST_CONN_NONE) | ||
| 576 | + { | ||
| 577 | + sender = f->unique_names[subscribe->sender]; | ||
| 578 | + g_test_message ("\tSender: %s %s", | ||
| 579 | + test_conn_descriptions[subscribe->sender], | ||
| 580 | + sender); | ||
| 581 | + } | ||
| 582 | + else | ||
| 583 | + { | ||
| 584 | + sender = NULL; | ||
| 585 | + g_test_message ("\tSender: (any)"); | ||
| 586 | + } | ||
| 587 | + | ||
| 588 | + g_test_message ("\tPath: %s", nonnull (subscribe->path, "(any)")); | ||
| 589 | + g_test_message ("\tInterface: %s", | ||
| 590 | + nonnull (subscribe->iface, "(any)")); | ||
| 591 | + g_test_message ("\tMember: %s", | ||
| 592 | + nonnull (subscribe->member, "(any)")); | ||
| 593 | + g_test_message ("\tString argument 0: %s", | ||
| 594 | + nonnull (subscribe->arg0, "(any)")); | ||
| 595 | + g_test_message ("\tFlags: %x", subscribe->flags); | ||
| 596 | + | ||
| 597 | + if (f->mode != SUBSCRIPTION_MODE_PROXY) | ||
| 598 | + { | ||
| 599 | + /* CONN or PARALLEL */ | ||
| 600 | + guint id; | ||
| 601 | + | ||
| 602 | + g_test_message ("\tSubscribing via connection"); | ||
| 603 | + id = g_dbus_connection_signal_subscribe (subscriber, | ||
| 604 | + sender, | ||
| 605 | + subscribe->iface, | ||
| 606 | + subscribe->member, | ||
| 607 | + subscribe->path, | ||
| 608 | + subscribe->arg0, | ||
| 609 | + subscribe->flags, | ||
| 610 | + subscribed_signal_cb, | ||
| 611 | + f, NULL); | ||
| 612 | + g_assert_cmpuint (id, !=, 0); | ||
| 613 | + f->subscriptions[step_number] = id; | ||
| 614 | + } | ||
| 615 | + | ||
| 616 | + if (f->mode != SUBSCRIPTION_MODE_CONN) | ||
| 617 | + { | ||
| 618 | + /* PROXY or PARALLEL */ | ||
| 619 | + | ||
| 620 | + if (sender == NULL) | ||
| 621 | + { | ||
| 622 | + g_test_message ("\tCannot subscribe via proxy: no bus name"); | ||
| 623 | + } | ||
| 624 | + else if (subscribe->path == NULL) | ||
| 625 | + { | ||
| 626 | + g_test_message ("\tCannot subscribe via proxy: no path"); | ||
| 627 | + } | ||
| 628 | + else if (subscribe->iface == NULL) | ||
| 629 | + { | ||
| 630 | + g_test_message ("\tCannot subscribe via proxy: no interface"); | ||
| 631 | + } | ||
| 632 | + else | ||
| 633 | + { | ||
| 634 | + GDBusProxy *proxy; | ||
| 635 | + | ||
| 636 | + g_test_message ("\tSubscribing via proxy"); | ||
| 637 | + proxy = g_dbus_proxy_new_sync (subscriber, | ||
| 638 | + (G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | ||
| 639 | + | G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START), | ||
| 640 | + NULL, /* GDBusInterfaceInfo */ | ||
| 641 | + sender, | ||
| 642 | + subscribe->path, | ||
| 643 | + subscribe->iface, | ||
| 644 | + NULL, /* GCancellable */ | ||
| 645 | + &f->error); | ||
| 646 | + g_assert_no_error (f->error); | ||
| 647 | + g_assert_nonnull (proxy); | ||
| 648 | + g_signal_connect (proxy, "g-signal", G_CALLBACK (proxy_signal_cb), f); | ||
| 649 | + g_ptr_array_add (f->proxies, g_steal_pointer (&proxy)); | ||
| 650 | + } | ||
| 651 | + } | ||
| 652 | + | ||
| 653 | + /* As in setup(), we need to wait for AddMatch to happen. */ | ||
| 654 | + g_test_message ("Waiting for AddMatch to be processed"); | ||
| 655 | + connection_wait_for_bus (subscriber); | ||
| 656 | +} | ||
| 657 | + | ||
| 658 | +static void | ||
| 659 | +fixture_emit_signal (Fixture *f, | ||
| 660 | + const TestEmitSignal *signal, | ||
| 661 | + guint step_number) | ||
| 662 | +{ | ||
| 663 | + GVariant *body; | ||
| 664 | + const char *destination; | ||
| 665 | + gboolean ok; | ||
| 666 | + | ||
| 667 | + g_test_message ("\tSender: %s", | ||
| 668 | + test_conn_descriptions[signal->sender]); | ||
| 669 | + | ||
| 670 | + if (signal->unicast_to != TEST_CONN_NONE) | ||
| 671 | + { | ||
| 672 | + destination = f->unique_names[signal->unicast_to]; | ||
| 673 | + g_test_message ("\tDestination: %s %s", | ||
| 674 | + test_conn_descriptions[signal->unicast_to], | ||
| 675 | + destination); | ||
| 676 | + } | ||
| 677 | + else | ||
| 678 | + { | ||
| 679 | + destination = NULL; | ||
| 680 | + g_test_message ("\tDestination: (broadcast)"); | ||
| 681 | + } | ||
| 682 | + | ||
| 683 | + g_assert_nonnull (signal->path); | ||
| 684 | + g_test_message ("\tPath: %s", signal->path); | ||
| 685 | + g_assert_nonnull (signal->iface); | ||
| 686 | + g_test_message ("\tInterface: %s", signal->iface); | ||
| 687 | + g_assert_nonnull (signal->member); | ||
| 688 | + g_test_message ("\tMember: %s", signal->member); | ||
| 689 | + | ||
| 690 | + /* If arg0 is non-NULL, put it in the message's argument 0. | ||
| 691 | + * Otherwise put something that will not match any arg0. | ||
| 692 | + * Either way, put the sequence number in argument 1 so we can | ||
| 693 | + * correlate sent messages with received messages later. */ | ||
| 694 | + if (signal->arg0 != NULL) | ||
| 695 | + { | ||
| 696 | + g_test_message ("\tString argument 0: %s", signal->arg0); | ||
| 697 | + /* floating */ | ||
| 698 | + body = g_variant_new ("(su)", signal->arg0, (guint32) step_number); | ||
| 699 | + } | ||
| 700 | + else | ||
| 701 | + { | ||
| 702 | + g_test_message ("\tArgument 0: (not a string)"); | ||
| 703 | + body = g_variant_new ("(uu)", (guint32) 0, (guint32) step_number); | ||
| 704 | + } | ||
| 705 | + | ||
| 706 | + ok = g_dbus_connection_emit_signal (f->conns[signal->sender], | ||
| 707 | + destination, | ||
| 708 | + signal->path, | ||
| 709 | + signal->iface, | ||
| 710 | + signal->member, | ||
| 711 | + /* steals floating reference */ | ||
| 712 | + g_steal_pointer (&body), | ||
| 713 | + &f->error); | ||
| 714 | + g_assert_no_error (f->error); | ||
| 715 | + g_assert_true (ok); | ||
| 716 | + | ||
| 717 | + /* Emitting the signal is asynchronous, so if we want subsequent steps | ||
| 718 | + * to be guaranteed to happen after the signal from the message bus's | ||
| 719 | + * perspective, we have to do a round-trip to the message bus to sync up. */ | ||
| 720 | + g_test_message ("Waiting for signal to reach message bus"); | ||
| 721 | + connection_wait_for_bus (f->conns[signal->sender]); | ||
| 722 | +} | ||
| 723 | + | ||
| 724 | +static void | ||
| 725 | +fixture_run_plan (Fixture *f, | ||
| 726 | + const TestPlan *plan, | ||
| 727 | + SubscriptionMode mode) | ||
| 728 | +{ | ||
| 729 | + guint i; | ||
| 730 | + | ||
| 731 | + G_STATIC_ASSERT (G_N_ELEMENTS (plan->steps) == G_N_ELEMENTS (f->subscriptions)); | ||
| 732 | + G_STATIC_ASSERT (G_N_ELEMENTS (plan->steps) == G_N_ELEMENTS (f->received_by_conn)); | ||
| 733 | + G_STATIC_ASSERT (G_N_ELEMENTS (plan->steps) == G_N_ELEMENTS (f->received_by_proxy)); | ||
| 734 | + | ||
| 735 | + f->mode = mode; | ||
| 736 | + f->plan = plan; | ||
| 737 | + | ||
| 738 | + g_test_summary (plan->description); | ||
| 739 | + | ||
| 740 | + for (i = 0; i < G_N_ELEMENTS (plan->steps); i++) | ||
| 741 | + { | ||
| 742 | + const TestStep *step = &plan->steps[i]; | ||
| 743 | + | ||
| 744 | + switch (step->action) | ||
| 745 | + { | ||
| 746 | + case TEST_ACTION_SUBSCRIBE: | ||
| 747 | + g_test_message ("Step %u: adding subscription", i); | ||
| 748 | + fixture_subscribe (f, &step->u.subscribe, i); | ||
| 749 | + break; | ||
| 750 | + | ||
| 751 | + case TEST_ACTION_EMIT_SIGNAL: | ||
| 752 | + g_test_message ("Step %u: emitting signal", i); | ||
| 753 | + fixture_emit_signal (f, &step->u.signal, i); | ||
| 754 | + break; | ||
| 755 | + | ||
| 756 | + case TEST_ACTION_NONE: | ||
| 757 | + /* Padding to fill the rest of the array, do nothing */ | ||
| 758 | + break; | ||
| 759 | + | ||
| 760 | + default: | ||
| 761 | + g_return_if_reached (); | ||
| 762 | + } | ||
| 763 | + } | ||
| 764 | + | ||
| 765 | + /* Now that we have done everything we wanted to do, emit Finished | ||
| 766 | + * from each connection. */ | ||
| 767 | + for (i = TEST_CONN_FIRST; i < G_N_ELEMENTS (f->conns); i++) | ||
| 768 | + { | ||
| 769 | + gboolean ok; | ||
| 770 | + | ||
| 771 | + ok = g_dbus_connection_emit_signal (f->conns[i], | ||
| 772 | + NULL, | ||
| 773 | + FINISHED_PATH, | ||
| 774 | + FINISHED_INTERFACE, | ||
| 775 | + FINISHED_SIGNAL, | ||
| 776 | + NULL, | ||
| 777 | + &f->error); | ||
| 778 | + g_assert_no_error (f->error); | ||
| 779 | + g_assert_true (ok); | ||
| 780 | + } | ||
| 781 | + | ||
| 782 | + /* Wait until we have seen the Finished signal from each sender */ | ||
| 783 | + while (TRUE) | ||
| 784 | + { | ||
| 785 | + gboolean all_finished = TRUE; | ||
| 786 | + | ||
| 787 | + for (i = TEST_CONN_FIRST; i < G_N_ELEMENTS (f->conns); i++) | ||
| 788 | + all_finished = all_finished && f->finished[i]; | ||
| 789 | + | ||
| 790 | + if (all_finished) | ||
| 791 | + break; | ||
| 792 | + | ||
| 793 | + g_main_context_iteration (NULL, TRUE); | ||
| 794 | + } | ||
| 795 | + | ||
| 796 | + /* Assert that the correct things happened before each Finished signal */ | ||
| 797 | + for (i = 0; i < f->received->len; i++) | ||
| 798 | + { | ||
| 799 | + const ReceivedMessage *received = g_ptr_array_index (f->received, i); | ||
| 800 | + | ||
| 801 | + g_assert_cmpuint (received->step, <, G_N_ELEMENTS (f->received_by_conn)); | ||
| 802 | + g_assert_cmpuint (received->step, <, G_N_ELEMENTS (f->received_by_proxy)); | ||
| 803 | + g_assert_cmpint (plan->steps[received->step].action, | ||
| 804 | + ==, TEST_ACTION_EMIT_SIGNAL); | ||
| 805 | + | ||
| 806 | + if (received->received_by_proxy != NULL) | ||
| 807 | + f->received_by_proxy[received->step] += 1; | ||
| 808 | + else | ||
| 809 | + f->received_by_conn[received->step] += 1; | ||
| 810 | + } | ||
| 811 | + | ||
| 812 | + for (i = 0; i < G_N_ELEMENTS (plan->steps); i++) | ||
| 813 | + { | ||
| 814 | + const TestStep *step = &plan->steps[i]; | ||
| 815 | + | ||
| 816 | + if (step->action == TEST_ACTION_EMIT_SIGNAL) | ||
| 817 | + { | ||
| 818 | + const TestEmitSignal *signal = &plan->steps[i].u.signal; | ||
| 819 | + | ||
| 820 | + if (mode != SUBSCRIPTION_MODE_PROXY) | ||
| 821 | + { | ||
| 822 | + g_test_message ("Signal from step %u was received %u times by " | ||
| 823 | + "GDBusConnection, expected %u", | ||
| 824 | + i, f->received_by_conn[i], signal->received_by_conn); | ||
| 825 | + g_assert_cmpuint (f->received_by_conn[i], ==, signal->received_by_conn); | ||
| 826 | + } | ||
| 827 | + else | ||
| 828 | + { | ||
| 829 | + g_assert_cmpuint (f->received_by_conn[i], ==, 0); | ||
| 830 | + } | ||
| 831 | + | ||
| 832 | + if (mode != SUBSCRIPTION_MODE_CONN) | ||
| 833 | + { | ||
| 834 | + g_test_message ("Signal from step %u was received %u times by " | ||
| 835 | + "GDBusProxy, expected %u", | ||
| 836 | + i, f->received_by_proxy[i], signal->received_by_proxy); | ||
| 837 | + g_assert_cmpuint (f->received_by_proxy[i], ==, signal->received_by_proxy); | ||
| 838 | + } | ||
| 839 | + else | ||
| 840 | + { | ||
| 841 | + g_assert_cmpuint (f->received_by_proxy[i], ==, 0); | ||
| 842 | + } | ||
| 843 | + } | ||
| 844 | + } | ||
| 845 | +} | ||
| 846 | + | ||
| 847 | +static void | ||
| 848 | +setup (Fixture *f, | ||
| 849 | + G_GNUC_UNUSED const void *context) | ||
| 850 | +{ | ||
| 851 | + GDBusConnection *subscriber; | ||
| 852 | + guint i; | ||
| 853 | + | ||
| 854 | + session_bus_up (); | ||
| 855 | + | ||
| 856 | + f->proxies = g_ptr_array_new_full (MAX_TEST_STEPS, g_object_unref); | ||
| 857 | + f->received = g_ptr_array_new_full (MAX_TEST_STEPS, | ||
| 858 | + (GDestroyNotify) received_message_free); | ||
| 859 | + | ||
| 860 | + for (i = TEST_CONN_FIRST; i < G_N_ELEMENTS (f->conns); i++) | ||
| 861 | + { | ||
| 862 | + f->conns[i] = _g_bus_get_priv (G_BUS_TYPE_SESSION, NULL, &f->error); | ||
| 863 | + g_assert_no_error (f->error); | ||
| 864 | + g_assert_nonnull (f->conns[i]); | ||
| 865 | + | ||
| 866 | + f->unique_names[i] = g_dbus_connection_get_unique_name (f->conns[i]); | ||
| 867 | + g_assert_nonnull (f->unique_names[i]); | ||
| 868 | + g_test_message ("%s is %s", | ||
| 869 | + test_conn_descriptions[i], | ||
| 870 | + f->unique_names[i]); | ||
| 871 | + } | ||
| 872 | + | ||
| 873 | + subscriber = f->conns[TEST_CONN_SUBSCRIBER]; | ||
| 874 | + | ||
| 875 | + /* Used to wait for all connections to finish sending whatever they | ||
| 876 | + * wanted to send */ | ||
| 877 | + f->finished_subscription = g_dbus_connection_signal_subscribe (subscriber, | ||
| 878 | + NULL, | ||
| 879 | + FINISHED_INTERFACE, | ||
| 880 | + FINISHED_SIGNAL, | ||
| 881 | + FINISHED_PATH, | ||
| 882 | + NULL, | ||
| 883 | + G_DBUS_SIGNAL_FLAGS_NONE, | ||
| 884 | + subscriber_finished_cb, | ||
| 885 | + f, NULL); | ||
| 886 | + /* AddMatch is sent asynchronously, so we don't know how | ||
| 887 | + * soon it will be processed. Before emitting signals, we | ||
| 888 | + * need to wait for the message bus to get as far as processing | ||
| 889 | + * AddMatch. */ | ||
| 890 | + g_test_message ("Waiting for AddMatch to be processed"); | ||
| 891 | + connection_wait_for_bus (subscriber); | ||
| 892 | +} | ||
| 893 | + | ||
| 894 | +static void | ||
| 895 | +test_conn_subscribe (Fixture *f, | ||
| 896 | + const void *context) | ||
| 897 | +{ | ||
| 898 | + fixture_run_plan (f, context, SUBSCRIPTION_MODE_CONN); | ||
| 899 | +} | ||
| 900 | + | ||
| 901 | +static void | ||
| 902 | +test_proxy_subscribe (Fixture *f, | ||
| 903 | + const void *context) | ||
| 904 | +{ | ||
| 905 | + fixture_run_plan (f, context, SUBSCRIPTION_MODE_PROXY); | ||
| 906 | +} | ||
| 907 | + | ||
| 908 | +static void | ||
| 909 | +test_parallel_subscribe (Fixture *f, | ||
| 910 | + const void *context) | ||
| 911 | +{ | ||
| 912 | + fixture_run_plan (f, context, SUBSCRIPTION_MODE_PARALLEL); | ||
| 913 | +} | ||
| 914 | + | ||
| 915 | +static void | ||
| 916 | +teardown (Fixture *f, | ||
| 917 | + G_GNUC_UNUSED const void *context) | ||
| 918 | +{ | ||
| 919 | + GDBusConnection *subscriber = f->conns[TEST_CONN_SUBSCRIBER]; | ||
| 920 | + guint i; | ||
| 921 | + | ||
| 922 | + g_ptr_array_unref (f->proxies); | ||
| 923 | + | ||
| 924 | + if (f->finished_subscription != 0) | ||
| 925 | + g_dbus_connection_signal_unsubscribe (subscriber, f->finished_subscription); | ||
| 926 | + | ||
| 927 | + for (i = 0; i < G_N_ELEMENTS (f->subscriptions); i++) | ||
| 928 | + { | ||
| 929 | + if (f->subscriptions[i] != 0) | ||
| 930 | + g_dbus_connection_signal_unsubscribe (subscriber, f->subscriptions[i]); | ||
| 931 | + } | ||
| 932 | + | ||
| 933 | + g_ptr_array_unref (f->received); | ||
| 934 | + | ||
| 935 | + for (i = TEST_CONN_FIRST; i < G_N_ELEMENTS (f->conns); i++) | ||
| 936 | + g_clear_object (&f->conns[i]); | ||
| 937 | + | ||
| 938 | + g_clear_error (&f->error); | ||
| 939 | + | ||
| 940 | + session_bus_down (); | ||
| 941 | +} | ||
| 942 | + | ||
| 943 | +int | ||
| 944 | +main (int argc, | ||
| 945 | + char *argv[]) | ||
| 946 | +{ | ||
| 947 | + g_test_init (&argc, &argv, G_TEST_OPTION_ISOLATE_DIRS, NULL); | ||
| 948 | + | ||
| 949 | + g_test_dbus_unset (); | ||
| 950 | + | ||
| 951 | +#define ADD_SUBSCRIBE_TEST(name) \ | ||
| 952 | + do { \ | ||
| 953 | + g_test_add ("/gdbus/subscribe/conn/" #name, \ | ||
| 954 | + Fixture, &plan_ ## name, \ | ||
| 955 | + setup, test_conn_subscribe, teardown); \ | ||
| 956 | + g_test_add ("/gdbus/subscribe/proxy/" #name, \ | ||
| 957 | + Fixture, &plan_ ## name, \ | ||
| 958 | + setup, test_proxy_subscribe, teardown); \ | ||
| 959 | + g_test_add ("/gdbus/subscribe/parallel/" #name, \ | ||
| 960 | + Fixture, &plan_ ## name, \ | ||
| 961 | + setup, test_parallel_subscribe, teardown); \ | ||
| 962 | + } while (0) | ||
| 963 | + | ||
| 964 | + ADD_SUBSCRIBE_TEST (simple); | ||
| 965 | + ADD_SUBSCRIBE_TEST (broadcast_from_anyone); | ||
| 966 | + ADD_SUBSCRIBE_TEST (match_twice); | ||
| 967 | + ADD_SUBSCRIBE_TEST (limit_by_unique_name); | ||
| 968 | + | ||
| 969 | + return g_test_run(); | ||
| 970 | +} | ||
| 971 | diff --git a/gio/tests/meson.build b/gio/tests/meson.build | ||
| 972 | index 383d84319..a1551aa53 100644 | ||
| 973 | --- a/gio/tests/meson.build | ||
| 974 | +++ b/gio/tests/meson.build | ||
| 975 | @@ -354,6 +354,7 @@ if host_machine.system() != 'windows' | ||
| 976 | }, | ||
| 977 | 'gdbus-proxy-unique-name' : {'extra_sources' : extra_sources}, | ||
| 978 | 'gdbus-proxy-well-known-name' : {'extra_sources' : extra_sources}, | ||
| 979 | + 'gdbus-subscribe' : {'extra_sources' : extra_sources}, | ||
| 980 | 'gdbus-test-codegen' : { | ||
| 981 | 'extra_sources' : [extra_sources, gdbus_test_codegen_generated, gdbus_test_codegen_generated_interface_info], | ||
| 982 | 'c_args' : ['-DGLIB_VERSION_MIN_REQUIRED=GLIB_VERSION_2_32'], | ||
| 983 | -- | ||
| 984 | 2.30.2 | ||
| 985 | |||
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2024-34397_04.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2024-34397_04.patch new file mode 100644 index 0000000000..144afd0d51 --- /dev/null +++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2024-34397_04.patch | |||
| @@ -0,0 +1,253 @@ | |||
| 1 | From a87931c257a6bb1b7c104623beadd9b14d766ca6 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Simon McVittie <smcv@collabora.com> | ||
| 3 | Date: Fri, 8 Mar 2024 19:28:15 +0000 | ||
| 4 | Subject: [PATCH 04/18] tests: Add support for subscribing to signals from a | ||
| 5 | well-known name | ||
| 6 | |||
| 7 | Signed-off-by: Simon McVittie <smcv@collabora.com> | ||
| 8 | |||
| 9 | CVE: CVE-2024-34397 | ||
| 10 | Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/glib/-/commit/a87931c257a6bb1b7c104623beadd9b14d766ca6] | ||
| 11 | Signed-off-by: Peter Marko <peter.marko@siemens.com> | ||
| 12 | --- | ||
| 13 | gio/tests/gdbus-subscribe.c | 133 ++++++++++++++++++++++++++++++++++-- | ||
| 14 | 1 file changed, 126 insertions(+), 7 deletions(-) | ||
| 15 | |||
| 16 | diff --git a/gio/tests/gdbus-subscribe.c b/gio/tests/gdbus-subscribe.c | ||
| 17 | index 3f53e1d7f..3d2a14e03 100644 | ||
| 18 | --- a/gio/tests/gdbus-subscribe.c | ||
| 19 | +++ b/gio/tests/gdbus-subscribe.c | ||
| 20 | @@ -7,6 +7,9 @@ | ||
| 21 | |||
| 22 | #include "gdbus-tests.h" | ||
| 23 | |||
| 24 | +/* From the D-Bus Specification */ | ||
| 25 | +#define DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER 1 | ||
| 26 | + | ||
| 27 | #define DBUS_SERVICE_DBUS "org.freedesktop.DBus" | ||
| 28 | #define DBUS_PATH_DBUS "/org/freedesktop/DBus" | ||
| 29 | #define DBUS_INTERFACE_DBUS DBUS_SERVICE_DBUS | ||
| 30 | @@ -22,6 +25,9 @@ | ||
| 31 | #define EXAMPLE_INTERFACE "org.gtk.GDBus.ExampleInterface" | ||
| 32 | #define FOO_SIGNAL "Foo" | ||
| 33 | |||
| 34 | +#define ALREADY_OWNED_NAME "org.gtk.Test.AlreadyOwned" | ||
| 35 | +#define OWNED_LATER_NAME "org.gtk.Test.OwnedLater" | ||
| 36 | + | ||
| 37 | /* Log @s in a debug message. */ | ||
| 38 | static inline const char * | ||
| 39 | nonnull (const char *s, | ||
| 40 | @@ -101,7 +107,8 @@ typedef struct | ||
| 41 | |||
| 42 | typedef struct | ||
| 43 | { | ||
| 44 | - TestConn sender; | ||
| 45 | + const char *string_sender; | ||
| 46 | + TestConn unique_sender; | ||
| 47 | const char *path; | ||
| 48 | const char *iface; | ||
| 49 | const char *member; | ||
| 50 | @@ -109,11 +116,18 @@ typedef struct | ||
| 51 | GDBusSignalFlags flags; | ||
| 52 | } TestSubscribe; | ||
| 53 | |||
| 54 | +typedef struct | ||
| 55 | +{ | ||
| 56 | + const char *name; | ||
| 57 | + TestConn owner; | ||
| 58 | +} TestOwnName; | ||
| 59 | + | ||
| 60 | typedef enum | ||
| 61 | { | ||
| 62 | TEST_ACTION_NONE = 0, | ||
| 63 | TEST_ACTION_SUBSCRIBE, | ||
| 64 | TEST_ACTION_EMIT_SIGNAL, | ||
| 65 | + TEST_ACTION_OWN_NAME, | ||
| 66 | } TestAction; | ||
| 67 | |||
| 68 | typedef struct | ||
| 69 | @@ -122,6 +136,7 @@ typedef struct | ||
| 70 | union { | ||
| 71 | TestEmitSignal signal; | ||
| 72 | TestSubscribe subscribe; | ||
| 73 | + TestOwnName own_name; | ||
| 74 | } u; | ||
| 75 | } TestStep; | ||
| 76 | |||
| 77 | @@ -247,7 +262,7 @@ static const TestPlan plan_match_twice = | ||
| 78 | { | ||
| 79 | .action = TEST_ACTION_SUBSCRIBE, | ||
| 80 | .u.subscribe = { | ||
| 81 | - .sender = TEST_CONN_SERVICE, | ||
| 82 | + .unique_sender = TEST_CONN_SERVICE, | ||
| 83 | .path = EXAMPLE_PATH, | ||
| 84 | .iface = EXAMPLE_INTERFACE, | ||
| 85 | }, | ||
| 86 | @@ -267,7 +282,7 @@ static const TestPlan plan_match_twice = | ||
| 87 | { | ||
| 88 | .action = TEST_ACTION_SUBSCRIBE, | ||
| 89 | .u.subscribe = { | ||
| 90 | - .sender = TEST_CONN_SERVICE, | ||
| 91 | + .unique_sender = TEST_CONN_SERVICE, | ||
| 92 | .path = EXAMPLE_PATH, | ||
| 93 | .iface = EXAMPLE_INTERFACE, | ||
| 94 | }, | ||
| 95 | @@ -296,7 +311,7 @@ static const TestPlan plan_limit_by_unique_name = | ||
| 96 | /* Subscriber wants to receive signals from service */ | ||
| 97 | .action = TEST_ACTION_SUBSCRIBE, | ||
| 98 | .u.subscribe = { | ||
| 99 | - .sender = TEST_CONN_SERVICE, | ||
| 100 | + .unique_sender = TEST_CONN_SERVICE, | ||
| 101 | .path = EXAMPLE_PATH, | ||
| 102 | .iface = EXAMPLE_INTERFACE, | ||
| 103 | }, | ||
| 104 | @@ -343,6 +358,62 @@ static const TestPlan plan_limit_by_unique_name = | ||
| 105 | }, | ||
| 106 | }; | ||
| 107 | |||
| 108 | +static const TestPlan plan_limit_by_well_known_name = | ||
| 109 | +{ | ||
| 110 | + .description = "A subscription via a well-known name only accepts messages " | ||
| 111 | + "sent by the owner of that well-known name", | ||
| 112 | + .steps = { | ||
| 113 | + { | ||
| 114 | + /* Service already owns one name */ | ||
| 115 | + .action = TEST_ACTION_OWN_NAME, | ||
| 116 | + .u.own_name = { | ||
| 117 | + .name = ALREADY_OWNED_NAME, | ||
| 118 | + .owner = TEST_CONN_SERVICE | ||
| 119 | + }, | ||
| 120 | + }, | ||
| 121 | + { | ||
| 122 | + /* Subscriber wants to receive signals from service */ | ||
| 123 | + .action = TEST_ACTION_SUBSCRIBE, | ||
| 124 | + .u.subscribe = { | ||
| 125 | + .string_sender = ALREADY_OWNED_NAME, | ||
| 126 | + .path = EXAMPLE_PATH, | ||
| 127 | + .iface = EXAMPLE_INTERFACE, | ||
| 128 | + }, | ||
| 129 | + }, | ||
| 130 | + { | ||
| 131 | + /* Subscriber wants to receive signals from service by another name */ | ||
| 132 | + .action = TEST_ACTION_SUBSCRIBE, | ||
| 133 | + .u.subscribe = { | ||
| 134 | + .string_sender = OWNED_LATER_NAME, | ||
| 135 | + .path = EXAMPLE_PATH, | ||
| 136 | + .iface = EXAMPLE_INTERFACE, | ||
| 137 | + }, | ||
| 138 | + }, | ||
| 139 | + { | ||
| 140 | + /* Service claims another name */ | ||
| 141 | + .action = TEST_ACTION_OWN_NAME, | ||
| 142 | + .u.own_name = { | ||
| 143 | + .name = OWNED_LATER_NAME, | ||
| 144 | + .owner = TEST_CONN_SERVICE | ||
| 145 | + }, | ||
| 146 | + }, | ||
| 147 | + { | ||
| 148 | + /* Now the subscriber gets this signal twice, once for each | ||
| 149 | + * subscription; and similarly each of the two proxies gets this | ||
| 150 | + * signal twice */ | ||
| 151 | + .action = TEST_ACTION_EMIT_SIGNAL, | ||
| 152 | + .u.signal = { | ||
| 153 | + .sender = TEST_CONN_SERVICE, | ||
| 154 | + .path = EXAMPLE_PATH, | ||
| 155 | + .iface = EXAMPLE_INTERFACE, | ||
| 156 | + .member = FOO_SIGNAL, | ||
| 157 | + .received_by_conn = 2, | ||
| 158 | + .received_by_proxy = 2 | ||
| 159 | + }, | ||
| 160 | + }, | ||
| 161 | + }, | ||
| 162 | +}; | ||
| 163 | + | ||
| 164 | typedef struct | ||
| 165 | { | ||
| 166 | const TestPlan *plan; | ||
| 167 | @@ -540,11 +611,16 @@ fixture_subscribe (Fixture *f, | ||
| 168 | GDBusConnection *subscriber = f->conns[TEST_CONN_SUBSCRIBER]; | ||
| 169 | const char *sender; | ||
| 170 | |||
| 171 | - if (subscribe->sender != TEST_CONN_NONE) | ||
| 172 | + if (subscribe->string_sender != NULL) | ||
| 173 | { | ||
| 174 | - sender = f->unique_names[subscribe->sender]; | ||
| 175 | + sender = subscribe->string_sender; | ||
| 176 | + g_test_message ("\tSender: %s", sender); | ||
| 177 | + } | ||
| 178 | + else if (subscribe->unique_sender != TEST_CONN_NONE) | ||
| 179 | + { | ||
| 180 | + sender = f->unique_names[subscribe->unique_sender]; | ||
| 181 | g_test_message ("\tSender: %s %s", | ||
| 182 | - test_conn_descriptions[subscribe->sender], | ||
| 183 | + test_conn_descriptions[subscribe->unique_sender], | ||
| 184 | sender); | ||
| 185 | } | ||
| 186 | else | ||
| 187 | @@ -689,6 +765,43 @@ fixture_emit_signal (Fixture *f, | ||
| 188 | connection_wait_for_bus (f->conns[signal->sender]); | ||
| 189 | } | ||
| 190 | |||
| 191 | +static void | ||
| 192 | +fixture_own_name (Fixture *f, | ||
| 193 | + const TestOwnName *own_name) | ||
| 194 | +{ | ||
| 195 | + GVariant *call_result; | ||
| 196 | + guint32 flags; | ||
| 197 | + guint32 result_code; | ||
| 198 | + | ||
| 199 | + g_test_message ("\tName: %s", own_name->name); | ||
| 200 | + g_test_message ("\tOwner: %s", | ||
| 201 | + test_conn_descriptions[own_name->owner]); | ||
| 202 | + | ||
| 203 | + /* For simplicity, we do this via a direct bus call rather than | ||
| 204 | + * using g_bus_own_name_on_connection(). The flags in | ||
| 205 | + * GBusNameOwnerFlags are numerically equal to those in the | ||
| 206 | + * D-Bus wire protocol. */ | ||
| 207 | + flags = G_BUS_NAME_OWNER_FLAGS_DO_NOT_QUEUE; | ||
| 208 | + call_result = g_dbus_connection_call_sync (f->conns[own_name->owner], | ||
| 209 | + DBUS_SERVICE_DBUS, | ||
| 210 | + DBUS_PATH_DBUS, | ||
| 211 | + DBUS_INTERFACE_DBUS, | ||
| 212 | + "RequestName", | ||
| 213 | + g_variant_new ("(su)", | ||
| 214 | + own_name->name, | ||
| 215 | + flags), | ||
| 216 | + G_VARIANT_TYPE ("(u)"), | ||
| 217 | + G_DBUS_CALL_FLAGS_NONE, | ||
| 218 | + -1, | ||
| 219 | + NULL, | ||
| 220 | + &f->error); | ||
| 221 | + g_assert_no_error (f->error); | ||
| 222 | + g_assert_nonnull (call_result); | ||
| 223 | + g_variant_get (call_result, "(u)", &result_code); | ||
| 224 | + g_assert_cmpuint (result_code, ==, DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER); | ||
| 225 | + g_variant_unref (call_result); | ||
| 226 | +} | ||
| 227 | + | ||
| 228 | static void | ||
| 229 | fixture_run_plan (Fixture *f, | ||
| 230 | const TestPlan *plan, | ||
| 231 | @@ -721,6 +834,11 @@ fixture_run_plan (Fixture *f, | ||
| 232 | fixture_emit_signal (f, &step->u.signal, i); | ||
| 233 | break; | ||
| 234 | |||
| 235 | + case TEST_ACTION_OWN_NAME: | ||
| 236 | + g_test_message ("Step %u: claiming bus name", i); | ||
| 237 | + fixture_own_name (f, &step->u.own_name); | ||
| 238 | + break; | ||
| 239 | + | ||
| 240 | case TEST_ACTION_NONE: | ||
| 241 | /* Padding to fill the rest of the array, do nothing */ | ||
| 242 | break; | ||
| 243 | @@ -933,6 +1051,7 @@ main (int argc, | ||
| 244 | ADD_SUBSCRIBE_TEST (broadcast_from_anyone); | ||
| 245 | ADD_SUBSCRIBE_TEST (match_twice); | ||
| 246 | ADD_SUBSCRIBE_TEST (limit_by_unique_name); | ||
| 247 | + ADD_SUBSCRIBE_TEST (limit_by_well_known_name); | ||
| 248 | |||
| 249 | return g_test_run(); | ||
| 250 | } | ||
| 251 | -- | ||
| 252 | 2.30.2 | ||
| 253 | |||
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2024-34397_05.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2024-34397_05.patch new file mode 100644 index 0000000000..7d929b579a --- /dev/null +++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2024-34397_05.patch | |||
| @@ -0,0 +1,88 @@ | |||
| 1 | From 4d4c40e858cb71a229b19f89196e6e02e235eb5b Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Simon McVittie <smcv@collabora.com> | ||
| 3 | Date: Fri, 8 Mar 2024 19:44:03 +0000 | ||
| 4 | Subject: [PATCH 05/18] tests: Add a test-case for what happens if a unique | ||
| 5 | name doesn't exist | ||
| 6 | |||
| 7 | On GNOME/glib#3268 there was some concern about whether this would | ||
| 8 | allow an attacker to send signals and have them be matched to a | ||
| 9 | GDBusProxy in this situation, but it seems that was a false alarm. | ||
| 10 | |||
| 11 | Signed-off-by: Simon McVittie <smcv@collabora.com> | ||
| 12 | |||
| 13 | CVE: CVE-2024-34397 | ||
| 14 | Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/glib/-/commit/4d4c40e858cb71a229b19f89196e6e02e235eb5b] | ||
| 15 | Signed-off-by: Peter Marko <peter.marko@siemens.com> | ||
| 16 | --- | ||
| 17 | gio/tests/gdbus-subscribe.c | 48 +++++++++++++++++++++++++++++++++++++ | ||
| 18 | 1 file changed, 48 insertions(+) | ||
| 19 | |||
| 20 | diff --git a/gio/tests/gdbus-subscribe.c b/gio/tests/gdbus-subscribe.c | ||
| 21 | index 3d2a14e03..350ec9f52 100644 | ||
| 22 | --- a/gio/tests/gdbus-subscribe.c | ||
| 23 | +++ b/gio/tests/gdbus-subscribe.c | ||
| 24 | @@ -358,6 +358,53 @@ static const TestPlan plan_limit_by_unique_name = | ||
| 25 | }, | ||
| 26 | }; | ||
| 27 | |||
| 28 | +static const TestPlan plan_nonexistent_unique_name = | ||
| 29 | +{ | ||
| 30 | + .description = "A subscription via a unique name that doesn't exist " | ||
| 31 | + "accepts no messages", | ||
| 32 | + .steps = { | ||
| 33 | + { | ||
| 34 | + /* Subscriber wants to receive signals from service */ | ||
| 35 | + .action = TEST_ACTION_SUBSCRIBE, | ||
| 36 | + .u.subscribe = { | ||
| 37 | + /* This relies on the implementation detail that the dbus-daemon | ||
| 38 | + * (and presumably other bus implementations) never actually generates | ||
| 39 | + * a unique name in this format */ | ||
| 40 | + .string_sender = ":0.this.had.better.not.exist", | ||
| 41 | + .path = EXAMPLE_PATH, | ||
| 42 | + .iface = EXAMPLE_INTERFACE, | ||
| 43 | + }, | ||
| 44 | + }, | ||
| 45 | + { | ||
| 46 | + /* Attacker wants to trick subscriber into thinking that service | ||
| 47 | + * sent a signal */ | ||
| 48 | + .action = TEST_ACTION_EMIT_SIGNAL, | ||
| 49 | + .u.signal = { | ||
| 50 | + .sender = TEST_CONN_ATTACKER, | ||
| 51 | + .path = EXAMPLE_PATH, | ||
| 52 | + .iface = EXAMPLE_INTERFACE, | ||
| 53 | + .member = FOO_SIGNAL, | ||
| 54 | + .received_by_conn = 0, | ||
| 55 | + .received_by_proxy = 0 | ||
| 56 | + }, | ||
| 57 | + }, | ||
| 58 | + { | ||
| 59 | + /* Attacker tries harder, by sending a signal unicast directly to | ||
| 60 | + * the subscriber */ | ||
| 61 | + .action = TEST_ACTION_EMIT_SIGNAL, | ||
| 62 | + .u.signal = { | ||
| 63 | + .sender = TEST_CONN_ATTACKER, | ||
| 64 | + .unicast_to = TEST_CONN_SUBSCRIBER, | ||
| 65 | + .path = EXAMPLE_PATH, | ||
| 66 | + .iface = EXAMPLE_INTERFACE, | ||
| 67 | + .member = FOO_SIGNAL, | ||
| 68 | + .received_by_conn = 0, | ||
| 69 | + .received_by_proxy = 0 | ||
| 70 | + }, | ||
| 71 | + }, | ||
| 72 | + }, | ||
| 73 | +}; | ||
| 74 | + | ||
| 75 | static const TestPlan plan_limit_by_well_known_name = | ||
| 76 | { | ||
| 77 | .description = "A subscription via a well-known name only accepts messages " | ||
| 78 | @@ -1051,6 +1098,7 @@ main (int argc, | ||
| 79 | ADD_SUBSCRIBE_TEST (broadcast_from_anyone); | ||
| 80 | ADD_SUBSCRIBE_TEST (match_twice); | ||
| 81 | ADD_SUBSCRIBE_TEST (limit_by_unique_name); | ||
| 82 | + ADD_SUBSCRIBE_TEST (nonexistent_unique_name); | ||
| 83 | ADD_SUBSCRIBE_TEST (limit_by_well_known_name); | ||
| 84 | |||
| 85 | return g_test_run(); | ||
| 86 | -- | ||
| 87 | 2.30.2 | ||
| 88 | |||
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2024-34397_06.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2024-34397_06.patch new file mode 100644 index 0000000000..ec79bda045 --- /dev/null +++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2024-34397_06.patch | |||
| @@ -0,0 +1,263 @@ | |||
| 1 | From 4d8106ba534c7f3c2037cca4c654fd13ce0b93d9 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Simon McVittie <smcv@collabora.com> | ||
| 3 | Date: Fri, 8 Mar 2024 20:10:29 +0000 | ||
| 4 | Subject: [PATCH 06/18] tests: Add test coverage for signals that match the | ||
| 5 | message bus's name | ||
| 6 | |||
| 7 | This is a special case of unique names, even though it's syntactically | ||
| 8 | a well-known name. | ||
| 9 | |||
| 10 | Signed-off-by: Simon McVittie <smcv@collabora.com> | ||
| 11 | |||
| 12 | CVE: CVE-2024-34397 | ||
| 13 | Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/glib/-/commit/4d8106ba534c7f3c2037cca4c654fd13ce0b93d9] | ||
| 14 | Signed-off-by: Peter Marko <peter.marko@siemens.com> | ||
| 15 | --- | ||
| 16 | gio/tests/gdbus-subscribe.c | 161 ++++++++++++++++++++++++++++++++++-- | ||
| 17 | 1 file changed, 154 insertions(+), 7 deletions(-) | ||
| 18 | |||
| 19 | diff --git a/gio/tests/gdbus-subscribe.c b/gio/tests/gdbus-subscribe.c | ||
| 20 | index 350ec9f52..af100de7d 100644 | ||
| 21 | --- a/gio/tests/gdbus-subscribe.c | ||
| 22 | +++ b/gio/tests/gdbus-subscribe.c | ||
| 23 | @@ -13,6 +13,7 @@ | ||
| 24 | #define DBUS_SERVICE_DBUS "org.freedesktop.DBus" | ||
| 25 | #define DBUS_PATH_DBUS "/org/freedesktop/DBus" | ||
| 26 | #define DBUS_INTERFACE_DBUS DBUS_SERVICE_DBUS | ||
| 27 | +#define NAME_OWNER_CHANGED "NameOwnerChanged" | ||
| 28 | |||
| 29 | /* A signal that each connection emits to indicate that it has finished | ||
| 30 | * emitting other signals */ | ||
| 31 | @@ -101,6 +102,7 @@ typedef struct | ||
| 32 | const char *iface; | ||
| 33 | const char *member; | ||
| 34 | const char *arg0; | ||
| 35 | + const char *args; | ||
| 36 | guint received_by_conn; | ||
| 37 | guint received_by_proxy; | ||
| 38 | } TestEmitSignal; | ||
| 39 | @@ -120,6 +122,8 @@ typedef struct | ||
| 40 | { | ||
| 41 | const char *name; | ||
| 42 | TestConn owner; | ||
| 43 | + guint received_by_conn; | ||
| 44 | + guint received_by_proxy; | ||
| 45 | } TestOwnName; | ||
| 46 | |||
| 47 | typedef enum | ||
| 48 | @@ -461,6 +465,63 @@ static const TestPlan plan_limit_by_well_known_name = | ||
| 49 | }, | ||
| 50 | }; | ||
| 51 | |||
| 52 | +static const TestPlan plan_limit_to_message_bus = | ||
| 53 | +{ | ||
| 54 | + .description = "A subscription to the message bus only accepts messages " | ||
| 55 | + "from the message bus", | ||
| 56 | + .steps = { | ||
| 57 | + { | ||
| 58 | + /* Subscriber wants to receive signals from the message bus itself */ | ||
| 59 | + .action = TEST_ACTION_SUBSCRIBE, | ||
| 60 | + .u.subscribe = { | ||
| 61 | + .string_sender = DBUS_SERVICE_DBUS, | ||
| 62 | + .path = DBUS_PATH_DBUS, | ||
| 63 | + .iface = DBUS_INTERFACE_DBUS, | ||
| 64 | + }, | ||
| 65 | + }, | ||
| 66 | + { | ||
| 67 | + /* Attacker wants to trick subscriber into thinking that the message | ||
| 68 | + * bus sent a signal */ | ||
| 69 | + .action = TEST_ACTION_EMIT_SIGNAL, | ||
| 70 | + .u.signal = { | ||
| 71 | + .sender = TEST_CONN_ATTACKER, | ||
| 72 | + .path = DBUS_PATH_DBUS, | ||
| 73 | + .iface = DBUS_INTERFACE_DBUS, | ||
| 74 | + .member = NAME_OWNER_CHANGED, | ||
| 75 | + .arg0 = "would I lie to you?", | ||
| 76 | + .received_by_conn = 0, | ||
| 77 | + .received_by_proxy = 0 | ||
| 78 | + }, | ||
| 79 | + }, | ||
| 80 | + { | ||
| 81 | + /* Attacker tries harder, by sending a signal unicast directly to | ||
| 82 | + * the subscriber, and using more realistic arguments */ | ||
| 83 | + .action = TEST_ACTION_EMIT_SIGNAL, | ||
| 84 | + .u.signal = { | ||
| 85 | + .unicast_to = TEST_CONN_SUBSCRIBER, | ||
| 86 | + .sender = TEST_CONN_ATTACKER, | ||
| 87 | + .path = DBUS_PATH_DBUS, | ||
| 88 | + .iface = DBUS_INTERFACE_DBUS, | ||
| 89 | + .member = NAME_OWNER_CHANGED, | ||
| 90 | + .args = "('com.example.Name', '', ':1.12')", | ||
| 91 | + .received_by_conn = 0, | ||
| 92 | + .received_by_proxy = 0 | ||
| 93 | + }, | ||
| 94 | + }, | ||
| 95 | + { | ||
| 96 | + /* When the message bus sends a signal (in this case triggered by | ||
| 97 | + * owning a name), it should still get through */ | ||
| 98 | + .action = TEST_ACTION_OWN_NAME, | ||
| 99 | + .u.own_name = { | ||
| 100 | + .name = OWNED_LATER_NAME, | ||
| 101 | + .owner = TEST_CONN_SERVICE, | ||
| 102 | + .received_by_conn = 1, | ||
| 103 | + .received_by_proxy = 1 | ||
| 104 | + }, | ||
| 105 | + }, | ||
| 106 | + }, | ||
| 107 | +}; | ||
| 108 | + | ||
| 109 | typedef struct | ||
| 110 | { | ||
| 111 | const TestPlan *plan; | ||
| 112 | @@ -591,7 +652,18 @@ fixture_received_signal (Fixture *f, | ||
| 113 | } | ||
| 114 | } | ||
| 115 | |||
| 116 | - g_assert_cmpint (received->sender, !=, TEST_CONN_NONE); | ||
| 117 | + if (g_str_equal (sender_name, DBUS_SERVICE_DBUS)) | ||
| 118 | + { | ||
| 119 | + g_test_message ("Signal received from message bus %s", | ||
| 120 | + sender_name); | ||
| 121 | + } | ||
| 122 | + else | ||
| 123 | + { | ||
| 124 | + g_test_message ("Signal received from %s %s", | ||
| 125 | + test_conn_descriptions[received->sender], | ||
| 126 | + sender_name); | ||
| 127 | + g_assert_cmpint (received->sender, !=, TEST_CONN_NONE); | ||
| 128 | + } | ||
| 129 | |||
| 130 | g_test_message ("Signal received from %s %s via %s", | ||
| 131 | test_conn_descriptions[received->sender], | ||
| 132 | @@ -607,13 +679,56 @@ fixture_received_signal (Fixture *f, | ||
| 133 | g_test_message ("\tString argument 0: %s", received->arg0); | ||
| 134 | g_test_message ("\tSent in step: %u", received->step); | ||
| 135 | } | ||
| 136 | - else | ||
| 137 | + else if (g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(uu)"))) | ||
| 138 | { | ||
| 139 | - g_assert_cmpstr (g_variant_get_type_string (parameters), ==, "(uu)"); | ||
| 140 | g_variant_get (parameters, "(uu)", NULL, &received->step); | ||
| 141 | g_test_message ("\tArgument 0: (not a string)"); | ||
| 142 | g_test_message ("\tSent in step: %u", received->step); | ||
| 143 | } | ||
| 144 | + else if (g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(sss)"))) | ||
| 145 | + { | ||
| 146 | + const char *name; | ||
| 147 | + const char *old_owner; | ||
| 148 | + const char *new_owner; | ||
| 149 | + | ||
| 150 | + /* The only signal of this signature that we legitimately receive | ||
| 151 | + * during this test is NameOwnerChanged, so just assert that it | ||
| 152 | + * is from the message bus and can be matched to a plausible step. | ||
| 153 | + * (This is less thorough than the above, and will not work if we | ||
| 154 | + * add a test scenario where a name's ownership is repeatedly | ||
| 155 | + * changed while watching NameOwnerChanged - so don't do that.) */ | ||
| 156 | + g_assert_cmpstr (sender_name, ==, DBUS_SERVICE_DBUS); | ||
| 157 | + g_assert_cmpstr (path, ==, DBUS_PATH_DBUS); | ||
| 158 | + g_assert_cmpstr (iface, ==, DBUS_INTERFACE_DBUS); | ||
| 159 | + g_assert_cmpstr (member, ==, NAME_OWNER_CHANGED); | ||
| 160 | + | ||
| 161 | + g_variant_get (parameters, "(&s&s&s)", &name, &old_owner, &new_owner); | ||
| 162 | + | ||
| 163 | + for (i = 0; i < G_N_ELEMENTS (f->plan->steps); i++) | ||
| 164 | + { | ||
| 165 | + const TestStep *step = &f->plan->steps[i]; | ||
| 166 | + | ||
| 167 | + if (step->action == TEST_ACTION_OWN_NAME) | ||
| 168 | + { | ||
| 169 | + const TestOwnName *own_name = &step->u.own_name; | ||
| 170 | + | ||
| 171 | + if (g_str_equal (name, own_name->name) | ||
| 172 | + && g_str_equal (new_owner, f->unique_names[own_name->owner]) | ||
| 173 | + && own_name->received_by_conn > 0) | ||
| 174 | + { | ||
| 175 | + received->step = i; | ||
| 176 | + break; | ||
| 177 | + } | ||
| 178 | + } | ||
| 179 | + | ||
| 180 | + if (i >= G_N_ELEMENTS (f->plan->steps)) | ||
| 181 | + g_error ("Could not match message to a test step"); | ||
| 182 | + } | ||
| 183 | + } | ||
| 184 | + else | ||
| 185 | + { | ||
| 186 | + g_error ("Unexpected message received"); | ||
| 187 | + } | ||
| 188 | |||
| 189 | g_ptr_array_add (f->received, g_steal_pointer (&received)); | ||
| 190 | } | ||
| 191 | @@ -782,10 +897,15 @@ fixture_emit_signal (Fixture *f, | ||
| 192 | * Otherwise put something that will not match any arg0. | ||
| 193 | * Either way, put the sequence number in argument 1 so we can | ||
| 194 | * correlate sent messages with received messages later. */ | ||
| 195 | - if (signal->arg0 != NULL) | ||
| 196 | + if (signal->args != NULL) | ||
| 197 | { | ||
| 198 | - g_test_message ("\tString argument 0: %s", signal->arg0); | ||
| 199 | /* floating */ | ||
| 200 | + body = g_variant_new_parsed (signal->args); | ||
| 201 | + g_assert_nonnull (body); | ||
| 202 | + } | ||
| 203 | + else if (signal->arg0 != NULL) | ||
| 204 | + { | ||
| 205 | + g_test_message ("\tString argument 0: %s", signal->arg0); | ||
| 206 | body = g_variant_new ("(su)", signal->arg0, (guint32) step_number); | ||
| 207 | } | ||
| 208 | else | ||
| 209 | @@ -933,8 +1053,6 @@ fixture_run_plan (Fixture *f, | ||
| 210 | |||
| 211 | g_assert_cmpuint (received->step, <, G_N_ELEMENTS (f->received_by_conn)); | ||
| 212 | g_assert_cmpuint (received->step, <, G_N_ELEMENTS (f->received_by_proxy)); | ||
| 213 | - g_assert_cmpint (plan->steps[received->step].action, | ||
| 214 | - ==, TEST_ACTION_EMIT_SIGNAL); | ||
| 215 | |||
| 216 | if (received->received_by_proxy != NULL) | ||
| 217 | f->received_by_proxy[received->step] += 1; | ||
| 218 | @@ -974,6 +1092,34 @@ fixture_run_plan (Fixture *f, | ||
| 219 | g_assert_cmpuint (f->received_by_proxy[i], ==, 0); | ||
| 220 | } | ||
| 221 | } | ||
| 222 | + else if (step->action == TEST_ACTION_OWN_NAME) | ||
| 223 | + { | ||
| 224 | + const TestOwnName *own_name = &plan->steps[i].u.own_name; | ||
| 225 | + | ||
| 226 | + if (mode != SUBSCRIPTION_MODE_PROXY) | ||
| 227 | + { | ||
| 228 | + g_test_message ("NameOwnerChanged from step %u was received %u " | ||
| 229 | + "times by GDBusConnection, expected %u", | ||
| 230 | + i, f->received_by_conn[i], own_name->received_by_conn); | ||
| 231 | + g_assert_cmpuint (f->received_by_conn[i], ==, own_name->received_by_conn); | ||
| 232 | + } | ||
| 233 | + else | ||
| 234 | + { | ||
| 235 | + g_assert_cmpuint (f->received_by_conn[i], ==, 0); | ||
| 236 | + } | ||
| 237 | + | ||
| 238 | + if (mode != SUBSCRIPTION_MODE_CONN) | ||
| 239 | + { | ||
| 240 | + g_test_message ("NameOwnerChanged from step %u was received %u " | ||
| 241 | + "times by GDBusProxy, expected %u", | ||
| 242 | + i, f->received_by_proxy[i], own_name->received_by_proxy); | ||
| 243 | + g_assert_cmpuint (f->received_by_proxy[i], ==, own_name->received_by_proxy); | ||
| 244 | + } | ||
| 245 | + else | ||
| 246 | + { | ||
| 247 | + g_assert_cmpuint (f->received_by_proxy[i], ==, 0); | ||
| 248 | + } | ||
| 249 | + } | ||
| 250 | } | ||
| 251 | } | ||
| 252 | |||
| 253 | @@ -1100,6 +1246,7 @@ main (int argc, | ||
| 254 | ADD_SUBSCRIBE_TEST (limit_by_unique_name); | ||
| 255 | ADD_SUBSCRIBE_TEST (nonexistent_unique_name); | ||
| 256 | ADD_SUBSCRIBE_TEST (limit_by_well_known_name); | ||
| 257 | + ADD_SUBSCRIBE_TEST (limit_to_message_bus); | ||
| 258 | |||
| 259 | return g_test_run(); | ||
| 260 | } | ||
| 261 | -- | ||
| 262 | 2.30.2 | ||
| 263 | |||
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2024-34397_07.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2024-34397_07.patch new file mode 100644 index 0000000000..f19846761a --- /dev/null +++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2024-34397_07.patch | |||
| @@ -0,0 +1,45 @@ | |||
| 1 | From 5057b6a0e488af6495146cfe96e93eb5e7beb66b Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Simon McVittie <smcv@collabora.com> | ||
| 3 | Date: Thu, 14 Mar 2024 19:18:15 +0000 | ||
| 4 | Subject: [PATCH 07/18] gdbusprivate: Add symbolic constants for the message | ||
| 5 | bus itself | ||
| 6 | |||
| 7 | Using these is a bit more clearly correct than repeating them everywhere. | ||
| 8 | To avoid excessive diffstat in a branch for a bug fix, I'm not | ||
| 9 | immediately replacing all existing occurrences of the same literals with | ||
| 10 | these names. | ||
| 11 | |||
| 12 | The names of these constants are chosen to be consistent with libdbus, | ||
| 13 | despite using somewhat outdated terminology (D-Bus now uses the term | ||
| 14 | "well-known bus name" for what used to be called a service name, | ||
| 15 | reserving the word "service" to mean specifically the programs that | ||
| 16 | have .service files and participate in service activation). | ||
| 17 | |||
| 18 | Signed-off-by: Simon McVittie <smcv@collabora.com> | ||
| 19 | |||
| 20 | CVE: CVE-2024-34397 | ||
| 21 | Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/glib/-/commit/5057b6a0e488af6495146cfe96e93eb5e7beb66b] | ||
| 22 | Signed-off-by: Peter Marko <peter.marko@siemens.com> | ||
| 23 | --- | ||
| 24 | gio/gdbusprivate.h | 5 +++++ | ||
| 25 | 1 file changed, 5 insertions(+) | ||
| 26 | |||
| 27 | diff --git a/gio/gdbusprivate.h b/gio/gdbusprivate.h | ||
| 28 | index 72d2c32a9..ac737bd7a 100644 | ||
| 29 | --- a/gio/gdbusprivate.h | ||
| 30 | +++ b/gio/gdbusprivate.h | ||
| 31 | @@ -29,6 +29,11 @@ | ||
| 32 | |||
| 33 | G_BEGIN_DECLS | ||
| 34 | |||
| 35 | +/* Bus name, interface and object path of the message bus itself */ | ||
| 36 | +#define DBUS_SERVICE_DBUS "org.freedesktop.DBus" | ||
| 37 | +#define DBUS_INTERFACE_DBUS DBUS_SERVICE_DBUS | ||
| 38 | +#define DBUS_PATH_DBUS "/org/freedesktop/DBus" | ||
| 39 | + | ||
| 40 | /* ---------------------------------------------------------------------------------------------------- */ | ||
| 41 | |||
| 42 | typedef struct GDBusWorker GDBusWorker; | ||
| 43 | -- | ||
| 44 | 2.30.2 | ||
| 45 | |||
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2024-34397_08.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2024-34397_08.patch new file mode 100644 index 0000000000..cd367478ff --- /dev/null +++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2024-34397_08.patch | |||
| @@ -0,0 +1,168 @@ | |||
| 1 | From 467ff27a5a08c21705e20da70a988a55b9f15513 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Simon McVittie <smcv@collabora.com> | ||
| 3 | Date: Thu, 14 Mar 2024 19:24:24 +0000 | ||
| 4 | Subject: [PATCH 08/18] gdbusconnection: Move SignalData, SignalSubscriber | ||
| 5 | higher up | ||
| 6 | |||
| 7 | Subsequent changes will need to access these data structures from | ||
| 8 | on_worker_message_received(). No functional change here, only moving | ||
| 9 | code around. | ||
| 10 | |||
| 11 | Signed-off-by: Simon McVittie <smcv@collabora.com> | ||
| 12 | |||
| 13 | CVE: CVE-2024-34397 | ||
| 14 | Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/glib/-/commit/467ff27a5a08c21705e20da70a988a55b9f15513] | ||
| 15 | Signed-off-by: Peter Marko <peter.marko@siemens.com> | ||
| 16 | --- | ||
| 17 | gio/gdbusconnection.c | 128 +++++++++++++++++++++--------------------- | ||
| 18 | 1 file changed, 65 insertions(+), 63 deletions(-) | ||
| 19 | |||
| 20 | diff --git a/gio/gdbusconnection.c b/gio/gdbusconnection.c | ||
| 21 | index 82a68437b..4f31e8502 100644 | ||
| 22 | --- a/gio/gdbusconnection.c | ||
| 23 | +++ b/gio/gdbusconnection.c | ||
| 24 | @@ -283,6 +283,71 @@ call_destroy_notify (GMainContext *context, | ||
| 25 | |||
| 26 | /* ---------------------------------------------------------------------------------------------------- */ | ||
| 27 | |||
| 28 | +typedef struct | ||
| 29 | +{ | ||
| 30 | + /* All fields are immutable after construction. */ | ||
| 31 | + gatomicrefcount ref_count; | ||
| 32 | + GDBusSignalCallback callback; | ||
| 33 | + gpointer user_data; | ||
| 34 | + GDestroyNotify user_data_free_func; | ||
| 35 | + guint id; | ||
| 36 | + GMainContext *context; | ||
| 37 | +} SignalSubscriber; | ||
| 38 | + | ||
| 39 | +static SignalSubscriber * | ||
| 40 | +signal_subscriber_ref (SignalSubscriber *subscriber) | ||
| 41 | +{ | ||
| 42 | + g_atomic_ref_count_inc (&subscriber->ref_count); | ||
| 43 | + return subscriber; | ||
| 44 | +} | ||
| 45 | + | ||
| 46 | +static void | ||
| 47 | +signal_subscriber_unref (SignalSubscriber *subscriber) | ||
| 48 | +{ | ||
| 49 | + if (g_atomic_ref_count_dec (&subscriber->ref_count)) | ||
| 50 | + { | ||
| 51 | + /* Destroy the user data. It doesn’t matter which thread | ||
| 52 | + * signal_subscriber_unref() is called in (or whether it’s called with a | ||
| 53 | + * lock held), as call_destroy_notify() always defers to the next | ||
| 54 | + * #GMainContext iteration. */ | ||
| 55 | + call_destroy_notify (subscriber->context, | ||
| 56 | + subscriber->user_data_free_func, | ||
| 57 | + subscriber->user_data); | ||
| 58 | + | ||
| 59 | + g_main_context_unref (subscriber->context); | ||
| 60 | + g_free (subscriber); | ||
| 61 | + } | ||
| 62 | +} | ||
| 63 | + | ||
| 64 | +typedef struct | ||
| 65 | +{ | ||
| 66 | + gchar *rule; | ||
| 67 | + gchar *sender; | ||
| 68 | + gchar *sender_unique_name; /* if sender is unique or org.freedesktop.DBus, then that name... otherwise blank */ | ||
| 69 | + gchar *interface_name; | ||
| 70 | + gchar *member; | ||
| 71 | + gchar *object_path; | ||
| 72 | + gchar *arg0; | ||
| 73 | + GDBusSignalFlags flags; | ||
| 74 | + GPtrArray *subscribers; /* (owned) (element-type SignalSubscriber) */ | ||
| 75 | +} SignalData; | ||
| 76 | + | ||
| 77 | +static void | ||
| 78 | +signal_data_free (SignalData *signal_data) | ||
| 79 | +{ | ||
| 80 | + g_free (signal_data->rule); | ||
| 81 | + g_free (signal_data->sender); | ||
| 82 | + g_free (signal_data->sender_unique_name); | ||
| 83 | + g_free (signal_data->interface_name); | ||
| 84 | + g_free (signal_data->member); | ||
| 85 | + g_free (signal_data->object_path); | ||
| 86 | + g_free (signal_data->arg0); | ||
| 87 | + g_ptr_array_unref (signal_data->subscribers); | ||
| 88 | + g_free (signal_data); | ||
| 89 | +} | ||
| 90 | + | ||
| 91 | +/* ---------------------------------------------------------------------------------------------------- */ | ||
| 92 | + | ||
| 93 | #ifdef G_OS_WIN32 | ||
| 94 | #define CONNECTION_ENSURE_LOCK(obj) do { ; } while (FALSE) | ||
| 95 | #else | ||
| 96 | @@ -3238,69 +3303,6 @@ g_dbus_connection_remove_filter (GDBusConnection *connection, | ||
| 97 | |||
| 98 | /* ---------------------------------------------------------------------------------------------------- */ | ||
| 99 | |||
| 100 | -typedef struct | ||
| 101 | -{ | ||
| 102 | - gchar *rule; | ||
| 103 | - gchar *sender; | ||
| 104 | - gchar *sender_unique_name; /* if sender is unique or org.freedesktop.DBus, then that name... otherwise blank */ | ||
| 105 | - gchar *interface_name; | ||
| 106 | - gchar *member; | ||
| 107 | - gchar *object_path; | ||
| 108 | - gchar *arg0; | ||
| 109 | - GDBusSignalFlags flags; | ||
| 110 | - GPtrArray *subscribers; /* (owned) (element-type SignalSubscriber) */ | ||
| 111 | -} SignalData; | ||
| 112 | - | ||
| 113 | -static void | ||
| 114 | -signal_data_free (SignalData *signal_data) | ||
| 115 | -{ | ||
| 116 | - g_free (signal_data->rule); | ||
| 117 | - g_free (signal_data->sender); | ||
| 118 | - g_free (signal_data->sender_unique_name); | ||
| 119 | - g_free (signal_data->interface_name); | ||
| 120 | - g_free (signal_data->member); | ||
| 121 | - g_free (signal_data->object_path); | ||
| 122 | - g_free (signal_data->arg0); | ||
| 123 | - g_ptr_array_unref (signal_data->subscribers); | ||
| 124 | - g_free (signal_data); | ||
| 125 | -} | ||
| 126 | - | ||
| 127 | -typedef struct | ||
| 128 | -{ | ||
| 129 | - /* All fields are immutable after construction. */ | ||
| 130 | - gatomicrefcount ref_count; | ||
| 131 | - GDBusSignalCallback callback; | ||
| 132 | - gpointer user_data; | ||
| 133 | - GDestroyNotify user_data_free_func; | ||
| 134 | - guint id; | ||
| 135 | - GMainContext *context; | ||
| 136 | -} SignalSubscriber; | ||
| 137 | - | ||
| 138 | -static SignalSubscriber * | ||
| 139 | -signal_subscriber_ref (SignalSubscriber *subscriber) | ||
| 140 | -{ | ||
| 141 | - g_atomic_ref_count_inc (&subscriber->ref_count); | ||
| 142 | - return subscriber; | ||
| 143 | -} | ||
| 144 | - | ||
| 145 | -static void | ||
| 146 | -signal_subscriber_unref (SignalSubscriber *subscriber) | ||
| 147 | -{ | ||
| 148 | - if (g_atomic_ref_count_dec (&subscriber->ref_count)) | ||
| 149 | - { | ||
| 150 | - /* Destroy the user data. It doesn’t matter which thread | ||
| 151 | - * signal_subscriber_unref() is called in (or whether it’s called with a | ||
| 152 | - * lock held), as call_destroy_notify() always defers to the next | ||
| 153 | - * #GMainContext iteration. */ | ||
| 154 | - call_destroy_notify (subscriber->context, | ||
| 155 | - subscriber->user_data_free_func, | ||
| 156 | - subscriber->user_data); | ||
| 157 | - | ||
| 158 | - g_main_context_unref (subscriber->context); | ||
| 159 | - g_free (subscriber); | ||
| 160 | - } | ||
| 161 | -} | ||
| 162 | - | ||
| 163 | static gchar * | ||
| 164 | args_to_rule (const gchar *sender, | ||
| 165 | const gchar *interface_name, | ||
| 166 | -- | ||
| 167 | 2.30.2 | ||
| 168 | |||
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2024-34397_09.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2024-34397_09.patch new file mode 100644 index 0000000000..581aa04983 --- /dev/null +++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2024-34397_09.patch | |||
| @@ -0,0 +1,81 @@ | |||
| 1 | From f75e2d73645598e5f3aa064adfece95da435525f Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Simon McVittie <smcv@collabora.com> | ||
| 3 | Date: Thu, 14 Mar 2024 19:30:12 +0000 | ||
| 4 | Subject: [PATCH 09/18] gdbusconnection: Factor out signal_data_new_take() | ||
| 5 | |||
| 6 | No functional changes, except that the implicit ownership-transfer | ||
| 7 | for the rule field becomes explicit (the local variable is set to NULL | ||
| 8 | afterwards). | ||
| 9 | |||
| 10 | Signed-off-by: Simon McVittie <smcv@collabora.com> | ||
| 11 | |||
| 12 | CVE: CVE-2024-34397 | ||
| 13 | Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/glib/-/commit/f75e2d73645598e5f3aa064adfece95da435525f] | ||
| 14 | Signed-off-by: Peter Marko <peter.marko@siemens.com> | ||
| 15 | --- | ||
| 16 | gio/gdbusconnection.c | 42 ++++++++++++++++++++++++++++++++---------- | ||
| 17 | 1 file changed, 32 insertions(+), 10 deletions(-) | ||
| 18 | |||
| 19 | diff --git a/gio/gdbusconnection.c b/gio/gdbusconnection.c | ||
| 20 | index 4f31e8502..b8fd920d9 100644 | ||
| 21 | --- a/gio/gdbusconnection.c | ||
| 22 | +++ b/gio/gdbusconnection.c | ||
| 23 | @@ -332,6 +332,30 @@ typedef struct | ||
| 24 | GPtrArray *subscribers; /* (owned) (element-type SignalSubscriber) */ | ||
| 25 | } SignalData; | ||
| 26 | |||
| 27 | +static SignalData * | ||
| 28 | +signal_data_new_take (gchar *rule, | ||
| 29 | + gchar *sender, | ||
| 30 | + gchar *sender_unique_name, | ||
| 31 | + gchar *interface_name, | ||
| 32 | + gchar *member, | ||
| 33 | + gchar *object_path, | ||
| 34 | + gchar *arg0, | ||
| 35 | + GDBusSignalFlags flags) | ||
| 36 | +{ | ||
| 37 | + SignalData *signal_data = g_new0 (SignalData, 1); | ||
| 38 | + | ||
| 39 | + signal_data->rule = rule; | ||
| 40 | + signal_data->sender = sender; | ||
| 41 | + signal_data->sender_unique_name = sender_unique_name; | ||
| 42 | + signal_data->interface_name = interface_name; | ||
| 43 | + signal_data->member = member; | ||
| 44 | + signal_data->object_path = object_path; | ||
| 45 | + signal_data->arg0 = arg0; | ||
| 46 | + signal_data->flags = flags; | ||
| 47 | + signal_data->subscribers = g_ptr_array_new_with_free_func ((GDestroyNotify) signal_subscriber_unref); | ||
| 48 | + return g_steal_pointer (&signal_data); | ||
| 49 | +} | ||
| 50 | + | ||
| 51 | static void | ||
| 52 | signal_data_free (SignalData *signal_data) | ||
| 53 | { | ||
| 54 | @@ -3569,16 +3593,14 @@ g_dbus_connection_signal_subscribe (GDBusConnection *connection, | ||
| 55 | goto out; | ||
| 56 | } | ||
| 57 | |||
| 58 | - signal_data = g_new0 (SignalData, 1); | ||
| 59 | - signal_data->rule = rule; | ||
| 60 | - signal_data->sender = g_strdup (sender); | ||
| 61 | - signal_data->sender_unique_name = g_strdup (sender_unique_name); | ||
| 62 | - signal_data->interface_name = g_strdup (interface_name); | ||
| 63 | - signal_data->member = g_strdup (member); | ||
| 64 | - signal_data->object_path = g_strdup (object_path); | ||
| 65 | - signal_data->arg0 = g_strdup (arg0); | ||
| 66 | - signal_data->flags = flags; | ||
| 67 | - signal_data->subscribers = g_ptr_array_new_with_free_func ((GDestroyNotify) signal_subscriber_unref); | ||
| 68 | + signal_data = signal_data_new_take (g_steal_pointer (&rule), | ||
| 69 | + g_strdup (sender), | ||
| 70 | + g_strdup (sender_unique_name), | ||
| 71 | + g_strdup (interface_name), | ||
| 72 | + g_strdup (member), | ||
| 73 | + g_strdup (object_path), | ||
| 74 | + g_strdup (arg0), | ||
| 75 | + flags); | ||
| 76 | g_ptr_array_add (signal_data->subscribers, subscriber); | ||
| 77 | |||
| 78 | g_hash_table_insert (connection->map_rule_to_signal_data, | ||
| 79 | -- | ||
| 80 | 2.30.2 | ||
| 81 | |||
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2024-34397_10.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2024-34397_10.patch new file mode 100644 index 0000000000..37b261eccd --- /dev/null +++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2024-34397_10.patch | |||
| @@ -0,0 +1,108 @@ | |||
| 1 | From 7f8b44ecdf5bc02e132de4c3242e961f8f27e9f2 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Simon McVittie <smcv@collabora.com> | ||
| 3 | Date: Tue, 23 Apr 2024 20:31:57 +0100 | ||
| 4 | Subject: [PATCH 10/18] gdbusconnection: Factor out add_signal_data() | ||
| 5 | |||
| 6 | No functional changes. | ||
| 7 | |||
| 8 | Signed-off-by: Simon McVittie <smcv@collabora.com> | ||
| 9 | |||
| 10 | CVE: CVE-2024-34397 | ||
| 11 | Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/glib/-/commit/7f8b44ecdf5bc02e132de4c3242e961f8f27e9f2] | ||
| 12 | Signed-off-by: Peter Marko <peter.marko@siemens.com> | ||
| 13 | --- | ||
| 14 | gio/gdbusconnection.c | 64 +++++++++++++++++++++++++------------------ | ||
| 15 | 1 file changed, 37 insertions(+), 27 deletions(-) | ||
| 16 | |||
| 17 | diff --git a/gio/gdbusconnection.c b/gio/gdbusconnection.c | ||
| 18 | index b8fd920d9..3b170845c 100644 | ||
| 19 | --- a/gio/gdbusconnection.c | ||
| 20 | +++ b/gio/gdbusconnection.c | ||
| 21 | @@ -3447,6 +3447,42 @@ is_signal_data_for_name_lost_or_acquired (SignalData *signal_data) | ||
| 22 | |||
| 23 | /* ---------------------------------------------------------------------------------------------------- */ | ||
| 24 | |||
| 25 | +/* called in any thread, connection lock is held */ | ||
| 26 | +static void | ||
| 27 | +add_signal_data (GDBusConnection *connection, | ||
| 28 | + SignalData *signal_data) | ||
| 29 | +{ | ||
| 30 | + GPtrArray *signal_data_array; | ||
| 31 | + | ||
| 32 | + g_hash_table_insert (connection->map_rule_to_signal_data, | ||
| 33 | + signal_data->rule, | ||
| 34 | + signal_data); | ||
| 35 | + | ||
| 36 | + /* Add the match rule to the bus... | ||
| 37 | + * | ||
| 38 | + * Avoid adding match rules for NameLost and NameAcquired messages - the bus will | ||
| 39 | + * always send such messages to us. | ||
| 40 | + */ | ||
| 41 | + if (connection->flags & G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION) | ||
| 42 | + { | ||
| 43 | + if (!is_signal_data_for_name_lost_or_acquired (signal_data)) | ||
| 44 | + add_match_rule (connection, signal_data->rule); | ||
| 45 | + } | ||
| 46 | + | ||
| 47 | + signal_data_array = g_hash_table_lookup (connection->map_sender_unique_name_to_signal_data_array, | ||
| 48 | + signal_data->sender_unique_name); | ||
| 49 | + if (signal_data_array == NULL) | ||
| 50 | + { | ||
| 51 | + signal_data_array = g_ptr_array_new (); | ||
| 52 | + g_hash_table_insert (connection->map_sender_unique_name_to_signal_data_array, | ||
| 53 | + g_strdup (signal_data->sender_unique_name), | ||
| 54 | + signal_data_array); | ||
| 55 | + } | ||
| 56 | + g_ptr_array_add (signal_data_array, signal_data); | ||
| 57 | +} | ||
| 58 | + | ||
| 59 | +/* ---------------------------------------------------------------------------------------------------- */ | ||
| 60 | + | ||
| 61 | /** | ||
| 62 | * g_dbus_connection_signal_subscribe: | ||
| 63 | * @connection: a #GDBusConnection | ||
| 64 | @@ -3536,7 +3572,6 @@ g_dbus_connection_signal_subscribe (GDBusConnection *connection, | ||
| 65 | gchar *rule; | ||
| 66 | SignalData *signal_data; | ||
| 67 | SignalSubscriber *subscriber; | ||
| 68 | - GPtrArray *signal_data_array; | ||
| 69 | const gchar *sender_unique_name; | ||
| 70 | |||
| 71 | /* Right now we abort if AddMatch() fails since it can only fail with the bus being in | ||
| 72 | @@ -3602,32 +3637,7 @@ g_dbus_connection_signal_subscribe (GDBusConnection *connection, | ||
| 73 | g_strdup (arg0), | ||
| 74 | flags); | ||
| 75 | g_ptr_array_add (signal_data->subscribers, subscriber); | ||
| 76 | - | ||
| 77 | - g_hash_table_insert (connection->map_rule_to_signal_data, | ||
| 78 | - signal_data->rule, | ||
| 79 | - signal_data); | ||
| 80 | - | ||
| 81 | - /* Add the match rule to the bus... | ||
| 82 | - * | ||
| 83 | - * Avoid adding match rules for NameLost and NameAcquired messages - the bus will | ||
| 84 | - * always send such messages to us. | ||
| 85 | - */ | ||
| 86 | - if (connection->flags & G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION) | ||
| 87 | - { | ||
| 88 | - if (!is_signal_data_for_name_lost_or_acquired (signal_data)) | ||
| 89 | - add_match_rule (connection, signal_data->rule); | ||
| 90 | - } | ||
| 91 | - | ||
| 92 | - signal_data_array = g_hash_table_lookup (connection->map_sender_unique_name_to_signal_data_array, | ||
| 93 | - signal_data->sender_unique_name); | ||
| 94 | - if (signal_data_array == NULL) | ||
| 95 | - { | ||
| 96 | - signal_data_array = g_ptr_array_new (); | ||
| 97 | - g_hash_table_insert (connection->map_sender_unique_name_to_signal_data_array, | ||
| 98 | - g_strdup (signal_data->sender_unique_name), | ||
| 99 | - signal_data_array); | ||
| 100 | - } | ||
| 101 | - g_ptr_array_add (signal_data_array, signal_data); | ||
| 102 | + add_signal_data (connection, signal_data); | ||
| 103 | |||
| 104 | out: | ||
| 105 | g_hash_table_insert (connection->map_id_to_signal_data, | ||
| 106 | -- | ||
| 107 | 2.30.2 | ||
| 108 | |||
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2024-34397_11.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2024-34397_11.patch new file mode 100644 index 0000000000..aa5c3ceaf5 --- /dev/null +++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2024-34397_11.patch | |||
| @@ -0,0 +1,133 @@ | |||
| 1 | From 1704bc6a70c0dcdc5555f23ebab8e3e7ed697998 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Simon McVittie <smcv@collabora.com> | ||
| 3 | Date: Thu, 14 Mar 2024 19:51:59 +0000 | ||
| 4 | Subject: [PATCH 11/18] gdbusconnection: Factor out | ||
| 5 | remove_signal_data_if_unused | ||
| 6 | |||
| 7 | No functional change, just removing some nesting. The check for whether | ||
| 8 | signal_data->subscribers is empty changes from a conditional that tests | ||
| 9 | whether it is into an early-return if it isn't. | ||
| 10 | |||
| 11 | A subsequent commit will add additional conditions that make us consider | ||
| 12 | a SignalData to be still in use and therefore not eligible to be removed. | ||
| 13 | |||
| 14 | Signed-off-by: Simon McVittie <smcv@collabora.com> | ||
| 15 | |||
| 16 | CVE: CVE-2024-34397 | ||
| 17 | Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/glib/-/commit/1704bc6a70c0dcdc5555f23ebab8e3e7ed697998] | ||
| 18 | Signed-off-by: Peter Marko <peter.marko@siemens.com> | ||
| 19 | --- | ||
| 20 | gio/gdbusconnection.c | 83 +++++++++++++++++++++++++------------------ | ||
| 21 | 1 file changed, 48 insertions(+), 35 deletions(-) | ||
| 22 | |||
| 23 | diff --git a/gio/gdbusconnection.c b/gio/gdbusconnection.c | ||
| 24 | index 3b170845c..114cdde29 100644 | ||
| 25 | --- a/gio/gdbusconnection.c | ||
| 26 | +++ b/gio/gdbusconnection.c | ||
| 27 | @@ -3651,6 +3651,52 @@ g_dbus_connection_signal_subscribe (GDBusConnection *connection, | ||
| 28 | |||
| 29 | /* ---------------------------------------------------------------------------------------------------- */ | ||
| 30 | |||
| 31 | +/* | ||
| 32 | + * Called in any thread. | ||
| 33 | + * Must hold the connection lock when calling this, unless | ||
| 34 | + * connection->finalizing is TRUE. | ||
| 35 | + * May free signal_data, so do not dereference it after this. | ||
| 36 | + */ | ||
| 37 | +static void | ||
| 38 | +remove_signal_data_if_unused (GDBusConnection *connection, | ||
| 39 | + SignalData *signal_data) | ||
| 40 | +{ | ||
| 41 | + GPtrArray *signal_data_array; | ||
| 42 | + | ||
| 43 | + if (signal_data->subscribers->len != 0) | ||
| 44 | + return; | ||
| 45 | + | ||
| 46 | + g_warn_if_fail (g_hash_table_remove (connection->map_rule_to_signal_data, signal_data->rule)); | ||
| 47 | + | ||
| 48 | + signal_data_array = g_hash_table_lookup (connection->map_sender_unique_name_to_signal_data_array, | ||
| 49 | + signal_data->sender_unique_name); | ||
| 50 | + g_warn_if_fail (signal_data_array != NULL); | ||
| 51 | + g_warn_if_fail (g_ptr_array_remove (signal_data_array, signal_data)); | ||
| 52 | + | ||
| 53 | + if (signal_data_array->len == 0) | ||
| 54 | + { | ||
| 55 | + g_warn_if_fail (g_hash_table_remove (connection->map_sender_unique_name_to_signal_data_array, | ||
| 56 | + signal_data->sender_unique_name)); | ||
| 57 | + } | ||
| 58 | + | ||
| 59 | + /* remove the match rule from the bus unless NameLost or NameAcquired (see subscribe()) */ | ||
| 60 | + if ((connection->flags & G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION) && | ||
| 61 | + !is_signal_data_for_name_lost_or_acquired (signal_data) && | ||
| 62 | + !g_dbus_connection_is_closed (connection) && | ||
| 63 | + !connection->finalizing) | ||
| 64 | + { | ||
| 65 | + /* The check for g_dbus_connection_is_closed() means that | ||
| 66 | + * sending the RemoveMatch message can't fail with | ||
| 67 | + * G_IO_ERROR_CLOSED, because we're holding the lock, | ||
| 68 | + * so on_worker_closed() can't happen between the check we just | ||
| 69 | + * did, and releasing the lock later. | ||
| 70 | + */ | ||
| 71 | + remove_match_rule (connection, signal_data->rule); | ||
| 72 | + } | ||
| 73 | + | ||
| 74 | + signal_data_free (signal_data); | ||
| 75 | +} | ||
| 76 | + | ||
| 77 | /* called in any thread */ | ||
| 78 | /* must hold lock when calling this (except if connection->finalizing is TRUE) | ||
| 79 | * returns the number of removed subscribers */ | ||
| 80 | @@ -3659,7 +3705,6 @@ unsubscribe_id_internal (GDBusConnection *connection, | ||
| 81 | guint subscription_id) | ||
| 82 | { | ||
| 83 | SignalData *signal_data; | ||
| 84 | - GPtrArray *signal_data_array; | ||
| 85 | guint n; | ||
| 86 | guint n_removed = 0; | ||
| 87 | |||
| 88 | @@ -3686,40 +3731,8 @@ unsubscribe_id_internal (GDBusConnection *connection, | ||
| 89 | GUINT_TO_POINTER (subscription_id))); | ||
| 90 | n_removed++; | ||
| 91 | g_ptr_array_remove_index_fast (signal_data->subscribers, n); | ||
| 92 | - | ||
| 93 | - if (signal_data->subscribers->len == 0) | ||
| 94 | - { | ||
| 95 | - g_warn_if_fail (g_hash_table_remove (connection->map_rule_to_signal_data, signal_data->rule)); | ||
| 96 | - | ||
| 97 | - signal_data_array = g_hash_table_lookup (connection->map_sender_unique_name_to_signal_data_array, | ||
| 98 | - signal_data->sender_unique_name); | ||
| 99 | - g_warn_if_fail (signal_data_array != NULL); | ||
| 100 | - g_warn_if_fail (g_ptr_array_remove (signal_data_array, signal_data)); | ||
| 101 | - | ||
| 102 | - if (signal_data_array->len == 0) | ||
| 103 | - { | ||
| 104 | - g_warn_if_fail (g_hash_table_remove (connection->map_sender_unique_name_to_signal_data_array, | ||
| 105 | - signal_data->sender_unique_name)); | ||
| 106 | - } | ||
| 107 | - | ||
| 108 | - /* remove the match rule from the bus unless NameLost or NameAcquired (see subscribe()) */ | ||
| 109 | - if ((connection->flags & G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION) && | ||
| 110 | - !is_signal_data_for_name_lost_or_acquired (signal_data) && | ||
| 111 | - !g_dbus_connection_is_closed (connection) && | ||
| 112 | - !connection->finalizing) | ||
| 113 | - { | ||
| 114 | - /* The check for g_dbus_connection_is_closed() means that | ||
| 115 | - * sending the RemoveMatch message can't fail with | ||
| 116 | - * G_IO_ERROR_CLOSED, because we're holding the lock, | ||
| 117 | - * so on_worker_closed() can't happen between the check we just | ||
| 118 | - * did, and releasing the lock later. | ||
| 119 | - */ | ||
| 120 | - remove_match_rule (connection, signal_data->rule); | ||
| 121 | - } | ||
| 122 | - | ||
| 123 | - signal_data_free (signal_data); | ||
| 124 | - } | ||
| 125 | - | ||
| 126 | + /* May free signal_data */ | ||
| 127 | + remove_signal_data_if_unused (connection, signal_data); | ||
| 128 | goto out; | ||
| 129 | } | ||
| 130 | |||
| 131 | -- | ||
| 132 | 2.30.2 | ||
| 133 | |||
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2024-34397_12.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2024-34397_12.patch new file mode 100644 index 0000000000..281143554f --- /dev/null +++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2024-34397_12.patch | |||
| @@ -0,0 +1,173 @@ | |||
| 1 | From 5377b4d9061b73bb47af85cc99253a18dc58e83e Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Simon McVittie <smcv@collabora.com> | ||
| 3 | Date: Tue, 23 Apr 2024 20:39:05 +0100 | ||
| 4 | Subject: [PATCH 12/18] gdbusconnection: Stop storing sender_unique_name in | ||
| 5 | SignalData | ||
| 6 | |||
| 7 | This will become confusing when we start tracking the owner of a | ||
| 8 | well-known-name sender, and it's redundant anyway. Instead, track the | ||
| 9 | 1 bit of data that we actually need: whether it's a well-known name. | ||
| 10 | |||
| 11 | Strictly speaking this too is redundant, because it's syntactically | ||
| 12 | derivable from the sender, but only via extra string operations. | ||
| 13 | A subsequent commit will add a data structure to keep track of the | ||
| 14 | owner of a well-known-name sender, at which point this boolean will | ||
| 15 | be replaced by the presence or absence of that data structure. | ||
| 16 | |||
| 17 | Signed-off-by: Simon McVittie <smcv@collabora.com> | ||
| 18 | |||
| 19 | CVE: CVE-2024-34397 | ||
| 20 | Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/glib/-/commit/5377b4d9061b73bb47af85cc99253a18dc58e83e] | ||
| 21 | Signed-off-by: Peter Marko <peter.marko@siemens.com> | ||
| 22 | --- | ||
| 23 | gio/gdbusconnection.c | 36 ++++++++++++++++++++++++------------ | ||
| 24 | 1 file changed, 24 insertions(+), 12 deletions(-) | ||
| 25 | |||
| 26 | diff --git a/gio/gdbusconnection.c b/gio/gdbusconnection.c | ||
| 27 | index 114cdde29..8c1d77b62 100644 | ||
| 28 | --- a/gio/gdbusconnection.c | ||
| 29 | +++ b/gio/gdbusconnection.c | ||
| 30 | @@ -323,19 +323,19 @@ typedef struct | ||
| 31 | { | ||
| 32 | gchar *rule; | ||
| 33 | gchar *sender; | ||
| 34 | - gchar *sender_unique_name; /* if sender is unique or org.freedesktop.DBus, then that name... otherwise blank */ | ||
| 35 | gchar *interface_name; | ||
| 36 | gchar *member; | ||
| 37 | gchar *object_path; | ||
| 38 | gchar *arg0; | ||
| 39 | GDBusSignalFlags flags; | ||
| 40 | GPtrArray *subscribers; /* (owned) (element-type SignalSubscriber) */ | ||
| 41 | + gboolean sender_is_its_own_owner; | ||
| 42 | } SignalData; | ||
| 43 | |||
| 44 | static SignalData * | ||
| 45 | signal_data_new_take (gchar *rule, | ||
| 46 | gchar *sender, | ||
| 47 | - gchar *sender_unique_name, | ||
| 48 | + gboolean sender_is_its_own_owner, | ||
| 49 | gchar *interface_name, | ||
| 50 | gchar *member, | ||
| 51 | gchar *object_path, | ||
| 52 | @@ -346,7 +346,7 @@ signal_data_new_take (gchar *rule, | ||
| 53 | |||
| 54 | signal_data->rule = rule; | ||
| 55 | signal_data->sender = sender; | ||
| 56 | - signal_data->sender_unique_name = sender_unique_name; | ||
| 57 | + signal_data->sender_is_its_own_owner = sender_is_its_own_owner; | ||
| 58 | signal_data->interface_name = interface_name; | ||
| 59 | signal_data->member = member; | ||
| 60 | signal_data->object_path = object_path; | ||
| 61 | @@ -361,7 +361,6 @@ signal_data_free (SignalData *signal_data) | ||
| 62 | { | ||
| 63 | g_free (signal_data->rule); | ||
| 64 | g_free (signal_data->sender); | ||
| 65 | - g_free (signal_data->sender_unique_name); | ||
| 66 | g_free (signal_data->interface_name); | ||
| 67 | g_free (signal_data->member); | ||
| 68 | g_free (signal_data->object_path); | ||
| 69 | @@ -3438,7 +3437,7 @@ remove_match_rule (GDBusConnection *connection, | ||
| 70 | static gboolean | ||
| 71 | is_signal_data_for_name_lost_or_acquired (SignalData *signal_data) | ||
| 72 | { | ||
| 73 | - return g_strcmp0 (signal_data->sender_unique_name, "org.freedesktop.DBus") == 0 && | ||
| 74 | + return g_strcmp0 (signal_data->sender, "org.freedesktop.DBus") == 0 && | ||
| 75 | g_strcmp0 (signal_data->interface_name, "org.freedesktop.DBus") == 0 && | ||
| 76 | g_strcmp0 (signal_data->object_path, "/org/freedesktop/DBus") == 0 && | ||
| 77 | (g_strcmp0 (signal_data->member, "NameLost") == 0 || | ||
| 78 | @@ -3450,7 +3449,8 @@ is_signal_data_for_name_lost_or_acquired (SignalData *signal_data) | ||
| 79 | /* called in any thread, connection lock is held */ | ||
| 80 | static void | ||
| 81 | add_signal_data (GDBusConnection *connection, | ||
| 82 | - SignalData *signal_data) | ||
| 83 | + SignalData *signal_data, | ||
| 84 | + const char *sender_unique_name) | ||
| 85 | { | ||
| 86 | GPtrArray *signal_data_array; | ||
| 87 | |||
| 88 | @@ -3470,12 +3470,12 @@ add_signal_data (GDBusConnection *connection, | ||
| 89 | } | ||
| 90 | |||
| 91 | signal_data_array = g_hash_table_lookup (connection->map_sender_unique_name_to_signal_data_array, | ||
| 92 | - signal_data->sender_unique_name); | ||
| 93 | + sender_unique_name); | ||
| 94 | if (signal_data_array == NULL) | ||
| 95 | { | ||
| 96 | signal_data_array = g_ptr_array_new (); | ||
| 97 | g_hash_table_insert (connection->map_sender_unique_name_to_signal_data_array, | ||
| 98 | - g_strdup (signal_data->sender_unique_name), | ||
| 99 | + g_strdup (sender_unique_name), | ||
| 100 | signal_data_array); | ||
| 101 | } | ||
| 102 | g_ptr_array_add (signal_data_array, signal_data); | ||
| 103 | @@ -3572,6 +3572,7 @@ g_dbus_connection_signal_subscribe (GDBusConnection *connection, | ||
| 104 | gchar *rule; | ||
| 105 | SignalData *signal_data; | ||
| 106 | SignalSubscriber *subscriber; | ||
| 107 | + gboolean sender_is_its_own_owner; | ||
| 108 | const gchar *sender_unique_name; | ||
| 109 | |||
| 110 | /* Right now we abort if AddMatch() fails since it can only fail with the bus being in | ||
| 111 | @@ -3607,6 +3608,11 @@ g_dbus_connection_signal_subscribe (GDBusConnection *connection, | ||
| 112 | rule = args_to_rule (sender, interface_name, member, object_path, arg0, flags); | ||
| 113 | |||
| 114 | if (sender != NULL && (g_dbus_is_unique_name (sender) || g_strcmp0 (sender, "org.freedesktop.DBus") == 0)) | ||
| 115 | + sender_is_its_own_owner = TRUE; | ||
| 116 | + else | ||
| 117 | + sender_is_its_own_owner = FALSE; | ||
| 118 | + | ||
| 119 | + if (sender_is_its_own_owner) | ||
| 120 | sender_unique_name = sender; | ||
| 121 | else | ||
| 122 | sender_unique_name = ""; | ||
| 123 | @@ -3630,14 +3636,14 @@ g_dbus_connection_signal_subscribe (GDBusConnection *connection, | ||
| 124 | |||
| 125 | signal_data = signal_data_new_take (g_steal_pointer (&rule), | ||
| 126 | g_strdup (sender), | ||
| 127 | - g_strdup (sender_unique_name), | ||
| 128 | + sender_is_its_own_owner, | ||
| 129 | g_strdup (interface_name), | ||
| 130 | g_strdup (member), | ||
| 131 | g_strdup (object_path), | ||
| 132 | g_strdup (arg0), | ||
| 133 | flags); | ||
| 134 | g_ptr_array_add (signal_data->subscribers, subscriber); | ||
| 135 | - add_signal_data (connection, signal_data); | ||
| 136 | + add_signal_data (connection, signal_data, sender_unique_name); | ||
| 137 | |||
| 138 | out: | ||
| 139 | g_hash_table_insert (connection->map_id_to_signal_data, | ||
| 140 | @@ -3661,22 +3667,28 @@ static void | ||
| 141 | remove_signal_data_if_unused (GDBusConnection *connection, | ||
| 142 | SignalData *signal_data) | ||
| 143 | { | ||
| 144 | + const gchar *sender_unique_name; | ||
| 145 | GPtrArray *signal_data_array; | ||
| 146 | |||
| 147 | if (signal_data->subscribers->len != 0) | ||
| 148 | return; | ||
| 149 | |||
| 150 | + if (signal_data->sender_is_its_own_owner) | ||
| 151 | + sender_unique_name = signal_data->sender; | ||
| 152 | + else | ||
| 153 | + sender_unique_name = ""; | ||
| 154 | + | ||
| 155 | g_warn_if_fail (g_hash_table_remove (connection->map_rule_to_signal_data, signal_data->rule)); | ||
| 156 | |||
| 157 | signal_data_array = g_hash_table_lookup (connection->map_sender_unique_name_to_signal_data_array, | ||
| 158 | - signal_data->sender_unique_name); | ||
| 159 | + sender_unique_name); | ||
| 160 | g_warn_if_fail (signal_data_array != NULL); | ||
| 161 | g_warn_if_fail (g_ptr_array_remove (signal_data_array, signal_data)); | ||
| 162 | |||
| 163 | if (signal_data_array->len == 0) | ||
| 164 | { | ||
| 165 | g_warn_if_fail (g_hash_table_remove (connection->map_sender_unique_name_to_signal_data_array, | ||
| 166 | - signal_data->sender_unique_name)); | ||
| 167 | + sender_unique_name)); | ||
| 168 | } | ||
| 169 | |||
| 170 | /* remove the match rule from the bus unless NameLost or NameAcquired (see subscribe()) */ | ||
| 171 | -- | ||
| 172 | 2.30.2 | ||
| 173 | |||
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2024-34397_13.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2024-34397_13.patch new file mode 100644 index 0000000000..aaa7cf8589 --- /dev/null +++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2024-34397_13.patch | |||
| @@ -0,0 +1,513 @@ | |||
| 1 | From 9114439d886137cfb903e109b612869535aa05b6 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Simon McVittie <smcv@collabora.com> | ||
| 3 | Date: Wed, 1 May 2024 15:43:09 +0100 | ||
| 4 | Subject: [PATCH 13/18] gdbus: Track name owners for signal subscriptions | ||
| 5 | |||
| 6 | We will use this in a subsequent commit to prevent signals from an | ||
| 7 | impostor from being delivered to a subscriber. | ||
| 8 | |||
| 9 | To avoid message reordering leading to misleading situations, this does | ||
| 10 | not use the existing mechanism for watching bus name ownership, which | ||
| 11 | delivers the ownership changes to other main-contexts. Instead, it all | ||
| 12 | happens on the single thread used by the GDBusWorker, so the order in | ||
| 13 | which messages are received is the order in which they are processed. | ||
| 14 | |||
| 15 | [Backported to glib-2-74, resolving minor conflicts] | ||
| 16 | Signed-off-by: Simon McVittie <smcv@collabora.com> | ||
| 17 | |||
| 18 | CVE: CVE-2024-34397 | ||
| 19 | Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/glib/-/commit/9114439d886137cfb903e109b612869535aa05b6] | ||
| 20 | Signed-off-by: Peter Marko <peter.marko@siemens.com> | ||
| 21 | --- | ||
| 22 | gio/gdbusconnection.c | 350 +++++++++++++++++++++++++++++++++++++++++- | ||
| 23 | 1 file changed, 343 insertions(+), 7 deletions(-) | ||
| 24 | |||
| 25 | diff --git a/gio/gdbusconnection.c b/gio/gdbusconnection.c | ||
| 26 | index 8c1d77b62..1ac120bc5 100644 | ||
| 27 | --- a/gio/gdbusconnection.c | ||
| 28 | +++ b/gio/gdbusconnection.c | ||
| 29 | @@ -320,6 +320,31 @@ signal_subscriber_unref (SignalSubscriber *subscriber) | ||
| 30 | } | ||
| 31 | |||
| 32 | typedef struct | ||
| 33 | +{ | ||
| 34 | + /* | ||
| 35 | + * 1 reference while waiting for GetNameOwner() to finish | ||
| 36 | + * 1 reference for each SignalData that points to this one as its | ||
| 37 | + * shared_name_watcher | ||
| 38 | + */ | ||
| 39 | + grefcount ref_count; | ||
| 40 | + | ||
| 41 | + gchar *owner; | ||
| 42 | + guint32 get_name_owner_serial; | ||
| 43 | +} WatchedName; | ||
| 44 | + | ||
| 45 | +static WatchedName * | ||
| 46 | +watched_name_new (void) | ||
| 47 | +{ | ||
| 48 | + WatchedName *watched_name = g_new0 (WatchedName, 1); | ||
| 49 | + | ||
| 50 | + g_ref_count_init (&watched_name->ref_count); | ||
| 51 | + watched_name->owner = NULL; | ||
| 52 | + return g_steal_pointer (&watched_name); | ||
| 53 | +} | ||
| 54 | + | ||
| 55 | +typedef struct SignalData SignalData; | ||
| 56 | + | ||
| 57 | +struct SignalData | ||
| 58 | { | ||
| 59 | gchar *rule; | ||
| 60 | gchar *sender; | ||
| 61 | @@ -329,13 +354,36 @@ typedef struct | ||
| 62 | gchar *arg0; | ||
| 63 | GDBusSignalFlags flags; | ||
| 64 | GPtrArray *subscribers; /* (owned) (element-type SignalSubscriber) */ | ||
| 65 | - gboolean sender_is_its_own_owner; | ||
| 66 | -} SignalData; | ||
| 67 | + | ||
| 68 | + /* | ||
| 69 | + * If the sender is a well-known name, this is an unowned SignalData | ||
| 70 | + * representing the NameOwnerChanged signal that tracks its owner. | ||
| 71 | + * NULL if sender is NULL. | ||
| 72 | + * NULL if sender is its own owner (a unique name or DBUS_SERVICE_DBUS). | ||
| 73 | + * | ||
| 74 | + * Invariants: if not NULL, then | ||
| 75 | + * shared_name_watcher->sender == DBUS_SERVICE_DBUS | ||
| 76 | + * shared_name_watcher->interface_name == DBUS_INTERFACE_DBUS | ||
| 77 | + * shared_name_watcher->member == "NameOwnerChanged" | ||
| 78 | + * shared_name_watcher->object_path == DBUS_PATH_DBUS | ||
| 79 | + * shared_name_watcher->arg0 == sender | ||
| 80 | + * shared_name_watcher->flags == NONE | ||
| 81 | + * shared_name_watcher->watched_name == NULL | ||
| 82 | + */ | ||
| 83 | + SignalData *shared_name_watcher; | ||
| 84 | + | ||
| 85 | + /* | ||
| 86 | + * Non-NULL if this SignalData is another SignalData's shared_name_watcher. | ||
| 87 | + * One reference for each SignalData that has this one as its | ||
| 88 | + * shared_name_watcher. | ||
| 89 | + * Otherwise NULL. | ||
| 90 | + */ | ||
| 91 | + WatchedName *watched_name; | ||
| 92 | +}; | ||
| 93 | |||
| 94 | static SignalData * | ||
| 95 | signal_data_new_take (gchar *rule, | ||
| 96 | gchar *sender, | ||
| 97 | - gboolean sender_is_its_own_owner, | ||
| 98 | gchar *interface_name, | ||
| 99 | gchar *member, | ||
| 100 | gchar *object_path, | ||
| 101 | @@ -346,7 +394,6 @@ signal_data_new_take (gchar *rule, | ||
| 102 | |||
| 103 | signal_data->rule = rule; | ||
| 104 | signal_data->sender = sender; | ||
| 105 | - signal_data->sender_is_its_own_owner = sender_is_its_own_owner; | ||
| 106 | signal_data->interface_name = interface_name; | ||
| 107 | signal_data->member = member; | ||
| 108 | signal_data->object_path = object_path; | ||
| 109 | @@ -359,6 +406,17 @@ signal_data_new_take (gchar *rule, | ||
| 110 | static void | ||
| 111 | signal_data_free (SignalData *signal_data) | ||
| 112 | { | ||
| 113 | + /* The SignalData should not be freed while it still has subscribers */ | ||
| 114 | + g_assert (signal_data->subscribers->len == 0); | ||
| 115 | + | ||
| 116 | + /* The SignalData should not be freed while it is watching for | ||
| 117 | + * NameOwnerChanged on behalf of another SignalData */ | ||
| 118 | + g_assert (signal_data->watched_name == NULL); | ||
| 119 | + | ||
| 120 | + /* The SignalData should be detached from its name watcher, if any, | ||
| 121 | + * before it is freed */ | ||
| 122 | + g_assert (signal_data->shared_name_watcher == NULL); | ||
| 123 | + | ||
| 124 | g_free (signal_data->rule); | ||
| 125 | g_free (signal_data->sender); | ||
| 126 | g_free (signal_data->interface_name); | ||
| 127 | @@ -366,6 +424,7 @@ signal_data_free (SignalData *signal_data) | ||
| 128 | g_free (signal_data->object_path); | ||
| 129 | g_free (signal_data->arg0); | ||
| 130 | g_ptr_array_unref (signal_data->subscribers); | ||
| 131 | + | ||
| 132 | g_free (signal_data); | ||
| 133 | } | ||
| 134 | |||
| 135 | @@ -497,6 +556,7 @@ struct _GDBusConnection | ||
| 136 | |||
| 137 | /* Map used for managing method replies, protected by @lock */ | ||
| 138 | GHashTable *map_method_serial_to_task; /* guint32 -> GTask* */ | ||
| 139 | + GHashTable *map_method_serial_to_name_watcher; /* guint32 -> unowned SignalData* */ | ||
| 140 | |||
| 141 | /* Maps used for managing signal subscription, protected by @lock */ | ||
| 142 | GHashTable *map_rule_to_signal_data; /* match rule (gchar*) -> SignalData */ | ||
| 143 | @@ -745,6 +805,7 @@ g_dbus_connection_finalize (GObject *object) | ||
| 144 | g_error_free (connection->initialization_error); | ||
| 145 | |||
| 146 | g_hash_table_unref (connection->map_method_serial_to_task); | ||
| 147 | + g_hash_table_unref (connection->map_method_serial_to_name_watcher); | ||
| 148 | |||
| 149 | g_hash_table_unref (connection->map_rule_to_signal_data); | ||
| 150 | g_hash_table_unref (connection->map_id_to_signal_data); | ||
| 151 | @@ -1149,6 +1210,7 @@ g_dbus_connection_init (GDBusConnection *connection) | ||
| 152 | g_mutex_init (&connection->init_lock); | ||
| 153 | |||
| 154 | connection->map_method_serial_to_task = g_hash_table_new (g_direct_hash, g_direct_equal); | ||
| 155 | + connection->map_method_serial_to_name_watcher = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, NULL); | ||
| 156 | |||
| 157 | connection->map_rule_to_signal_data = g_hash_table_new (g_str_hash, | ||
| 158 | g_str_equal); | ||
| 159 | @@ -2266,6 +2328,191 @@ g_dbus_connection_send_message_with_reply_sync (GDBusConnection *connecti | ||
| 160 | |||
| 161 | /* ---------------------------------------------------------------------------------------------------- */ | ||
| 162 | |||
| 163 | +/* | ||
| 164 | + * Called in any thread. | ||
| 165 | + * Must hold the connection lock when calling this, unless | ||
| 166 | + * connection->finalizing is TRUE. | ||
| 167 | + */ | ||
| 168 | +static void | ||
| 169 | +name_watcher_unref_watched_name (GDBusConnection *connection, | ||
| 170 | + SignalData *name_watcher) | ||
| 171 | +{ | ||
| 172 | + WatchedName *watched_name = name_watcher->watched_name; | ||
| 173 | + | ||
| 174 | + g_assert (watched_name != NULL); | ||
| 175 | + | ||
| 176 | + if (!g_ref_count_dec (&watched_name->ref_count)) | ||
| 177 | + return; | ||
| 178 | + | ||
| 179 | + /* Removing watched_name from the name_watcher may result in | ||
| 180 | + * name_watcher being freed, so we must make sure name_watcher is no | ||
| 181 | + * longer in map_method_serial_to_name_watcher. | ||
| 182 | + * | ||
| 183 | + * If we stop watching the name while our GetNameOwner call was still | ||
| 184 | + * in-flight, then when the reply eventually arrives, we will not find | ||
| 185 | + * its serial number in the map and harmlessly ignore it as a result. */ | ||
| 186 | + if (watched_name->get_name_owner_serial != 0) | ||
| 187 | + g_hash_table_remove (connection->map_method_serial_to_name_watcher, | ||
| 188 | + GUINT_TO_POINTER (watched_name->get_name_owner_serial)); | ||
| 189 | + | ||
| 190 | + name_watcher->watched_name = NULL; | ||
| 191 | + g_free (watched_name->owner); | ||
| 192 | + g_free (watched_name); | ||
| 193 | +} | ||
| 194 | + | ||
| 195 | +/* called in GDBusWorker thread with lock held */ | ||
| 196 | +static void | ||
| 197 | +name_watcher_set_name_owner_unlocked (SignalData *name_watcher, | ||
| 198 | + const char *new_owner) | ||
| 199 | +{ | ||
| 200 | + if (new_owner != NULL && new_owner[0] == '\0') | ||
| 201 | + new_owner = NULL; | ||
| 202 | + | ||
| 203 | + g_assert (name_watcher->watched_name != NULL); | ||
| 204 | + g_set_str (&name_watcher->watched_name->owner, new_owner); | ||
| 205 | +} | ||
| 206 | + | ||
| 207 | +/* called in GDBusWorker thread with lock held */ | ||
| 208 | +static void | ||
| 209 | +name_watcher_deliver_name_owner_changed_unlocked (SignalData *name_watcher, | ||
| 210 | + GDBusMessage *message) | ||
| 211 | +{ | ||
| 212 | + GVariant *body; | ||
| 213 | + | ||
| 214 | + body = g_dbus_message_get_body (message); | ||
| 215 | + | ||
| 216 | + if (G_LIKELY (body != NULL && g_variant_is_of_type (body, G_VARIANT_TYPE ("(sss)")))) | ||
| 217 | + { | ||
| 218 | + const char *name; | ||
| 219 | + const char *new_owner; | ||
| 220 | + | ||
| 221 | + g_variant_get (body, "(&s&s&s)", &name, NULL, &new_owner); | ||
| 222 | + | ||
| 223 | + /* Our caller already checked this */ | ||
| 224 | + g_assert (g_strcmp0 (name_watcher->arg0, name) == 0); | ||
| 225 | + | ||
| 226 | + if (G_LIKELY (new_owner[0] == '\0' || g_dbus_is_unique_name (new_owner))) | ||
| 227 | + name_watcher_set_name_owner_unlocked (name_watcher, new_owner); | ||
| 228 | + else | ||
| 229 | + g_warning ("Received NameOwnerChanged signal with invalid owner \"%s\" for \"%s\"", | ||
| 230 | + new_owner, name); | ||
| 231 | + } | ||
| 232 | + else | ||
| 233 | + { | ||
| 234 | + g_warning ("Received NameOwnerChanged signal with unexpected " | ||
| 235 | + "signature %s", | ||
| 236 | + body == NULL ? "()" : g_variant_get_type_string (body)); | ||
| 237 | + | ||
| 238 | + } | ||
| 239 | +} | ||
| 240 | + | ||
| 241 | +/* called in GDBusWorker thread with lock held */ | ||
| 242 | +static void | ||
| 243 | +name_watcher_deliver_get_name_owner_reply_unlocked (SignalData *name_watcher, | ||
| 244 | + GDBusConnection *connection, | ||
| 245 | + GDBusMessage *message) | ||
| 246 | +{ | ||
| 247 | + GDBusMessageType type; | ||
| 248 | + GVariant *body; | ||
| 249 | + WatchedName *watched_name; | ||
| 250 | + | ||
| 251 | + watched_name = name_watcher->watched_name; | ||
| 252 | + g_assert (watched_name != NULL); | ||
| 253 | + g_assert (watched_name->get_name_owner_serial != 0); | ||
| 254 | + | ||
| 255 | + type = g_dbus_message_get_message_type (message); | ||
| 256 | + body = g_dbus_message_get_body (message); | ||
| 257 | + | ||
| 258 | + if (type == G_DBUS_MESSAGE_TYPE_ERROR) | ||
| 259 | + { | ||
| 260 | + if (g_strcmp0 (g_dbus_message_get_error_name (message), | ||
| 261 | + "org.freedesktop.DBus.Error.NameHasNoOwner")) | ||
| 262 | + name_watcher_set_name_owner_unlocked (name_watcher, NULL); | ||
| 263 | + /* else it's something like NoReply or AccessDenied, which tells | ||
| 264 | + * us nothing - leave the owner set to whatever we most recently | ||
| 265 | + * learned from NameOwnerChanged, or NULL */ | ||
| 266 | + } | ||
| 267 | + else if (type != G_DBUS_MESSAGE_TYPE_METHOD_RETURN) | ||
| 268 | + { | ||
| 269 | + g_warning ("Received GetNameOwner reply with unexpected type %d", | ||
| 270 | + type); | ||
| 271 | + } | ||
| 272 | + else if (G_LIKELY (body != NULL && g_variant_is_of_type (body, G_VARIANT_TYPE ("(s)")))) | ||
| 273 | + { | ||
| 274 | + const char *new_owner; | ||
| 275 | + | ||
| 276 | + g_variant_get (body, "(&s)", &new_owner); | ||
| 277 | + | ||
| 278 | + if (G_LIKELY (g_dbus_is_unique_name (new_owner))) | ||
| 279 | + name_watcher_set_name_owner_unlocked (name_watcher, new_owner); | ||
| 280 | + else | ||
| 281 | + g_warning ("Received GetNameOwner reply with invalid owner \"%s\" for \"%s\"", | ||
| 282 | + new_owner, name_watcher->arg0); | ||
| 283 | + } | ||
| 284 | + else | ||
| 285 | + { | ||
| 286 | + g_warning ("Received GetNameOwner reply with unexpected signature %s", | ||
| 287 | + body == NULL ? "()" : g_variant_get_type_string (body)); | ||
| 288 | + } | ||
| 289 | + | ||
| 290 | + g_hash_table_remove (connection->map_method_serial_to_name_watcher, | ||
| 291 | + GUINT_TO_POINTER (watched_name->get_name_owner_serial)); | ||
| 292 | + watched_name->get_name_owner_serial = 0; | ||
| 293 | +} | ||
| 294 | + | ||
| 295 | +/* Called in a user thread, lock is held */ | ||
| 296 | +static void | ||
| 297 | +name_watcher_call_get_name_owner_unlocked (GDBusConnection *connection, | ||
| 298 | + SignalData *name_watcher) | ||
| 299 | +{ | ||
| 300 | + GDBusMessage *message; | ||
| 301 | + GError *local_error = NULL; | ||
| 302 | + WatchedName *watched_name; | ||
| 303 | + | ||
| 304 | + g_assert (g_strcmp0 (name_watcher->sender, DBUS_SERVICE_DBUS) == 0); | ||
| 305 | + g_assert (g_strcmp0 (name_watcher->interface_name, DBUS_INTERFACE_DBUS) == 0); | ||
| 306 | + g_assert (g_strcmp0 (name_watcher->member, "NameOwnerChanged") == 0); | ||
| 307 | + g_assert (g_strcmp0 (name_watcher->object_path, DBUS_PATH_DBUS) == 0); | ||
| 308 | + /* arg0 of the NameOwnerChanged message is the well-known name whose owner | ||
| 309 | + * we are interested in */ | ||
| 310 | + g_assert (g_dbus_is_name (name_watcher->arg0)); | ||
| 311 | + g_assert (name_watcher->flags == G_DBUS_SIGNAL_FLAGS_NONE); | ||
| 312 | + | ||
| 313 | + watched_name = name_watcher->watched_name; | ||
| 314 | + g_assert (watched_name != NULL); | ||
| 315 | + g_assert (watched_name->owner == NULL); | ||
| 316 | + g_assert (watched_name->get_name_owner_serial == 0); | ||
| 317 | + g_assert (name_watcher->shared_name_watcher == NULL); | ||
| 318 | + | ||
| 319 | + message = g_dbus_message_new_method_call (DBUS_SERVICE_DBUS, | ||
| 320 | + DBUS_PATH_DBUS, | ||
| 321 | + DBUS_INTERFACE_DBUS, | ||
| 322 | + "GetNameOwner"); | ||
| 323 | + g_dbus_message_set_body (message, g_variant_new ("(s)", name_watcher->arg0)); | ||
| 324 | + | ||
| 325 | + if (g_dbus_connection_send_message_unlocked (connection, message, | ||
| 326 | + G_DBUS_SEND_MESSAGE_FLAGS_NONE, | ||
| 327 | + &watched_name->get_name_owner_serial, | ||
| 328 | + &local_error)) | ||
| 329 | + { | ||
| 330 | + g_assert (watched_name->get_name_owner_serial != 0); | ||
| 331 | + g_hash_table_insert (connection->map_method_serial_to_name_watcher, | ||
| 332 | + GUINT_TO_POINTER (watched_name->get_name_owner_serial), | ||
| 333 | + name_watcher); | ||
| 334 | + } | ||
| 335 | + else | ||
| 336 | + { | ||
| 337 | + g_critical ("Error while sending GetNameOwner() message: %s", | ||
| 338 | + local_error->message); | ||
| 339 | + g_clear_error (&local_error); | ||
| 340 | + g_assert (watched_name->get_name_owner_serial == 0); | ||
| 341 | + } | ||
| 342 | + | ||
| 343 | + g_object_unref (message); | ||
| 344 | +} | ||
| 345 | + | ||
| 346 | +/* ---------------------------------------------------------------------------------------------------- */ | ||
| 347 | + | ||
| 348 | typedef struct | ||
| 349 | { | ||
| 350 | guint id; | ||
| 351 | @@ -2389,6 +2636,7 @@ on_worker_message_received (GDBusWorker *worker, | ||
| 352 | { | ||
| 353 | guint32 reply_serial; | ||
| 354 | GTask *task; | ||
| 355 | + SignalData *name_watcher; | ||
| 356 | |||
| 357 | reply_serial = g_dbus_message_get_reply_serial (message); | ||
| 358 | CONNECTION_LOCK (connection); | ||
| 359 | @@ -2404,6 +2652,19 @@ on_worker_message_received (GDBusWorker *worker, | ||
| 360 | { | ||
| 361 | //g_debug ("message reply/error for serial %d but no SendMessageData found for %p", reply_serial, connection); | ||
| 362 | } | ||
| 363 | + | ||
| 364 | + name_watcher = g_hash_table_lookup (connection->map_method_serial_to_name_watcher, | ||
| 365 | + GUINT_TO_POINTER (reply_serial)); | ||
| 366 | + | ||
| 367 | + if (name_watcher != NULL) | ||
| 368 | + { | ||
| 369 | + g_assert (name_watcher->watched_name != NULL); | ||
| 370 | + g_assert (name_watcher->watched_name->get_name_owner_serial == reply_serial); | ||
| 371 | + name_watcher_deliver_get_name_owner_reply_unlocked (name_watcher, | ||
| 372 | + connection, | ||
| 373 | + message); | ||
| 374 | + } | ||
| 375 | + | ||
| 376 | CONNECTION_UNLOCK (connection); | ||
| 377 | } | ||
| 378 | else if (message_type == G_DBUS_MESSAGE_TYPE_SIGNAL) | ||
| 379 | @@ -3571,6 +3832,7 @@ g_dbus_connection_signal_subscribe (GDBusConnection *connection, | ||
| 380 | { | ||
| 381 | gchar *rule; | ||
| 382 | SignalData *signal_data; | ||
| 383 | + SignalData *name_watcher = NULL; | ||
| 384 | SignalSubscriber *subscriber; | ||
| 385 | gboolean sender_is_its_own_owner; | ||
| 386 | const gchar *sender_unique_name; | ||
| 387 | @@ -3636,13 +3898,59 @@ g_dbus_connection_signal_subscribe (GDBusConnection *connection, | ||
| 388 | |||
| 389 | signal_data = signal_data_new_take (g_steal_pointer (&rule), | ||
| 390 | g_strdup (sender), | ||
| 391 | - sender_is_its_own_owner, | ||
| 392 | g_strdup (interface_name), | ||
| 393 | g_strdup (member), | ||
| 394 | g_strdup (object_path), | ||
| 395 | g_strdup (arg0), | ||
| 396 | flags); | ||
| 397 | g_ptr_array_add (signal_data->subscribers, subscriber); | ||
| 398 | + | ||
| 399 | + /* If subscribing to a signal from a specific sender with a well-known | ||
| 400 | + * name, we must first subscribe to NameOwnerChanged signals for that | ||
| 401 | + * well-known name, so that we can match the current owner of the name | ||
| 402 | + * against the sender of each signal. */ | ||
| 403 | + if (sender != NULL && !sender_is_its_own_owner) | ||
| 404 | + { | ||
| 405 | + gchar *name_owner_rule = NULL; | ||
| 406 | + | ||
| 407 | + /* We already checked that sender != NULL implies MESSAGE_BUS_CONNECTION */ | ||
| 408 | + g_assert (connection->flags & G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION); | ||
| 409 | + | ||
| 410 | + name_owner_rule = args_to_rule (DBUS_SERVICE_DBUS, | ||
| 411 | + DBUS_INTERFACE_DBUS, | ||
| 412 | + "NameOwnerChanged", | ||
| 413 | + DBUS_PATH_DBUS, | ||
| 414 | + sender, | ||
| 415 | + G_DBUS_SIGNAL_FLAGS_NONE); | ||
| 416 | + name_watcher = g_hash_table_lookup (connection->map_rule_to_signal_data, name_owner_rule); | ||
| 417 | + | ||
| 418 | + if (name_watcher == NULL) | ||
| 419 | + { | ||
| 420 | + name_watcher = signal_data_new_take (g_steal_pointer (&name_owner_rule), | ||
| 421 | + g_strdup (DBUS_SERVICE_DBUS), | ||
| 422 | + g_strdup (DBUS_INTERFACE_DBUS), | ||
| 423 | + g_strdup ("NameOwnerChanged"), | ||
| 424 | + g_strdup (DBUS_PATH_DBUS), | ||
| 425 | + g_strdup (sender), | ||
| 426 | + G_DBUS_SIGNAL_FLAGS_NONE); | ||
| 427 | + add_signal_data (connection, name_watcher, DBUS_SERVICE_DBUS); | ||
| 428 | + } | ||
| 429 | + | ||
| 430 | + if (name_watcher->watched_name == NULL) | ||
| 431 | + { | ||
| 432 | + name_watcher->watched_name = watched_name_new (); | ||
| 433 | + name_watcher_call_get_name_owner_unlocked (connection, name_watcher); | ||
| 434 | + } | ||
| 435 | + else | ||
| 436 | + { | ||
| 437 | + g_ref_count_inc (&name_watcher->watched_name->ref_count); | ||
| 438 | + } | ||
| 439 | + | ||
| 440 | + signal_data->shared_name_watcher = name_watcher; | ||
| 441 | + | ||
| 442 | + g_clear_pointer (&name_owner_rule, g_free); | ||
| 443 | + } | ||
| 444 | + | ||
| 445 | add_signal_data (connection, signal_data, sender_unique_name); | ||
| 446 | |||
| 447 | out: | ||
| 448 | @@ -3670,10 +3978,18 @@ remove_signal_data_if_unused (GDBusConnection *connection, | ||
| 449 | const gchar *sender_unique_name; | ||
| 450 | GPtrArray *signal_data_array; | ||
| 451 | |||
| 452 | + /* Cannot remove while there are still subscribers */ | ||
| 453 | if (signal_data->subscribers->len != 0) | ||
| 454 | return; | ||
| 455 | |||
| 456 | - if (signal_data->sender_is_its_own_owner) | ||
| 457 | + /* Cannot remove while another SignalData is still using this one | ||
| 458 | + * as its shared_name_watcher, which holds watched_name->ref_count > 0 */ | ||
| 459 | + if (signal_data->watched_name != NULL) | ||
| 460 | + return; | ||
| 461 | + | ||
| 462 | + /* Point of no return: we have committed to removing it */ | ||
| 463 | + | ||
| 464 | + if (signal_data->sender != NULL && signal_data->shared_name_watcher == NULL) | ||
| 465 | sender_unique_name = signal_data->sender; | ||
| 466 | else | ||
| 467 | sender_unique_name = ""; | ||
| 468 | @@ -3706,6 +4022,15 @@ remove_signal_data_if_unused (GDBusConnection *connection, | ||
| 469 | remove_match_rule (connection, signal_data->rule); | ||
| 470 | } | ||
| 471 | |||
| 472 | + if (signal_data->shared_name_watcher != NULL) | ||
| 473 | + { | ||
| 474 | + SignalData *name_watcher = g_steal_pointer (&signal_data->shared_name_watcher); | ||
| 475 | + | ||
| 476 | + name_watcher_unref_watched_name (connection, name_watcher); | ||
| 477 | + /* May free signal_data */ | ||
| 478 | + remove_signal_data_if_unused (connection, name_watcher); | ||
| 479 | + } | ||
| 480 | + | ||
| 481 | signal_data_free (signal_data); | ||
| 482 | } | ||
| 483 | |||
| 484 | @@ -3978,6 +4303,17 @@ schedule_callbacks (GDBusConnection *connection, | ||
| 485 | continue; | ||
| 486 | } | ||
| 487 | |||
| 488 | + if (signal_data->watched_name != NULL) | ||
| 489 | + { | ||
| 490 | + /* Invariant: SignalData should only have a watched_name if it | ||
| 491 | + * represents the NameOwnerChanged signal */ | ||
| 492 | + g_assert (g_strcmp0 (sender, DBUS_SERVICE_DBUS) == 0); | ||
| 493 | + g_assert (g_strcmp0 (interface, DBUS_INTERFACE_DBUS) == 0); | ||
| 494 | + g_assert (g_strcmp0 (path, DBUS_PATH_DBUS) == 0); | ||
| 495 | + g_assert (g_strcmp0 (member, "NameOwnerChanged") == 0); | ||
| 496 | + name_watcher_deliver_name_owner_changed_unlocked (signal_data, message); | ||
| 497 | + } | ||
| 498 | + | ||
| 499 | for (m = 0; m < signal_data->subscribers->len; m++) | ||
| 500 | { | ||
| 501 | SignalSubscriber *subscriber = signal_data->subscribers->pdata[m]; | ||
| 502 | @@ -4039,7 +4375,7 @@ distribute_signals (GDBusConnection *connection, | ||
| 503 | schedule_callbacks (connection, signal_data_array, message, sender); | ||
| 504 | } | ||
| 505 | |||
| 506 | - /* collect subscribers not matching on sender */ | ||
| 507 | + /* collect subscribers not matching on sender, or matching a well-known name */ | ||
| 508 | signal_data_array = g_hash_table_lookup (connection->map_sender_unique_name_to_signal_data_array, ""); | ||
| 509 | if (signal_data_array != NULL) | ||
| 510 | schedule_callbacks (connection, signal_data_array, message, sender); | ||
| 511 | -- | ||
| 512 | 2.30.2 | ||
| 513 | |||
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2024-34397_14.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2024-34397_14.patch new file mode 100644 index 0000000000..ab6c049da7 --- /dev/null +++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2024-34397_14.patch | |||
| @@ -0,0 +1,75 @@ | |||
| 1 | From 69799764cb40a2842d4891d4e1d72c3ce73964ed Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Simon McVittie <smcv@collabora.com> | ||
| 3 | Date: Thu, 14 Mar 2024 20:42:41 +0000 | ||
| 4 | Subject: [PATCH 14/18] gdbusconnection: Don't deliver signals if the sender | ||
| 5 | doesn't match | ||
| 6 | |||
| 7 | Otherwise a malicious connection on a shared bus, especially the system | ||
| 8 | bus, could trick GDBus clients into processing signals sent by the | ||
| 9 | malicious connection as though they had come from the real owner of a | ||
| 10 | well-known service name. | ||
| 11 | |||
| 12 | Resolves: https://gitlab.gnome.org/GNOME/glib/-/issues/3268 | ||
| 13 | Signed-off-by: Simon McVittie <smcv@collabora.com> | ||
| 14 | |||
| 15 | CVE: CVE-2024-34397 | ||
| 16 | Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/glib/-/commit/69799764cb40a2842d4891d4e1d72c3ce73964ed] | ||
| 17 | Signed-off-by: Peter Marko <peter.marko@siemens.com> | ||
| 18 | --- | ||
| 19 | gio/gdbusconnection.c | 40 ++++++++++++++++++++++++++++++++++++++++ | ||
| 20 | 1 file changed, 40 insertions(+) | ||
| 21 | |||
| 22 | diff --git a/gio/gdbusconnection.c b/gio/gdbusconnection.c | ||
| 23 | index 1ac120bc5..7cde0e3bf 100644 | ||
| 24 | --- a/gio/gdbusconnection.c | ||
| 25 | +++ b/gio/gdbusconnection.c | ||
| 26 | @@ -4284,6 +4284,46 @@ schedule_callbacks (GDBusConnection *connection, | ||
| 27 | if (signal_data->object_path != NULL && g_strcmp0 (signal_data->object_path, path) != 0) | ||
| 28 | continue; | ||
| 29 | |||
| 30 | + if (signal_data->shared_name_watcher != NULL) | ||
| 31 | + { | ||
| 32 | + /* We want signals from a specified well-known name, which means | ||
| 33 | + * the signal's sender needs to be the unique name that currently | ||
| 34 | + * owns that well-known name, and we will have found this | ||
| 35 | + * SignalData in | ||
| 36 | + * connection->map_sender_unique_name_to_signal_data_array[""]. */ | ||
| 37 | + const WatchedName *watched_name; | ||
| 38 | + const char *current_owner; | ||
| 39 | + | ||
| 40 | + g_assert (signal_data->sender != NULL); | ||
| 41 | + /* Invariant: We never need to watch for the owner of a unique | ||
| 42 | + * name, or for the owner of DBUS_SERVICE_DBUS, either of which | ||
| 43 | + * is always its own owner */ | ||
| 44 | + g_assert (!g_dbus_is_unique_name (signal_data->sender)); | ||
| 45 | + g_assert (g_strcmp0 (signal_data->sender, DBUS_SERVICE_DBUS) != 0); | ||
| 46 | + | ||
| 47 | + watched_name = signal_data->shared_name_watcher->watched_name; | ||
| 48 | + g_assert (watched_name != NULL); | ||
| 49 | + current_owner = watched_name->owner; | ||
| 50 | + | ||
| 51 | + /* Skip the signal if the actual sender is not known to own | ||
| 52 | + * the required name */ | ||
| 53 | + if (current_owner == NULL || g_strcmp0 (current_owner, sender) != 0) | ||
| 54 | + continue; | ||
| 55 | + } | ||
| 56 | + else if (signal_data->sender != NULL) | ||
| 57 | + { | ||
| 58 | + /* We want signals from a unique name or o.fd.DBus... */ | ||
| 59 | + g_assert (g_dbus_is_unique_name (signal_data->sender) | ||
| 60 | + || g_str_equal (signal_data->sender, DBUS_SERVICE_DBUS)); | ||
| 61 | + | ||
| 62 | + /* ... which means we must have found this SignalData in | ||
| 63 | + * connection->map_sender_unique_name_to_signal_data_array[signal_data->sender], | ||
| 64 | + * therefore we would only have found it if the signal's | ||
| 65 | + * actual sender matches the required signal_data->sender */ | ||
| 66 | + g_assert (g_strcmp0 (signal_data->sender, sender) == 0); | ||
| 67 | + } | ||
| 68 | + /* else the sender is unspecified and we will accept anything */ | ||
| 69 | + | ||
| 70 | if (signal_data->arg0 != NULL) | ||
| 71 | { | ||
| 72 | if (arg0 == NULL) | ||
| 73 | -- | ||
| 74 | 2.30.2 | ||
| 75 | |||
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2024-34397_15.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2024-34397_15.patch new file mode 100644 index 0000000000..547884b796 --- /dev/null +++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2024-34397_15.patch | |||
| @@ -0,0 +1,47 @@ | |||
| 1 | From 505e2c644d02a5cf581fb85d145e820d51dc3f1b Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Simon McVittie <smcv@collabora.com> | ||
| 3 | Date: Fri, 8 Mar 2024 19:51:50 +0000 | ||
| 4 | Subject: [PATCH 15/18] tests: Add a test for matching by two well-known names | ||
| 5 | |||
| 6 | The expected result is that because TEST_CONN_SERVICE owns | ||
| 7 | ALREADY_OWNED_NAME but not (yet) OWNED_LATER_NAME, the signal will be | ||
| 8 | delivered to the subscriber for the former but not the latter. | ||
| 9 | Before #3268 was fixed, it was incorrectly delivered to both. | ||
| 10 | |||
| 11 | Reproduces: https://gitlab.gnome.org/GNOME/glib/-/issues/3268 (partially) | ||
| 12 | Signed-off-by: Simon McVittie <smcv@collabora.com> | ||
| 13 | |||
| 14 | CVE: CVE-2024-34397 | ||
| 15 | Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/glib/-/commit/505e2c644d02a5cf581fb85d145e820d51dc3f1b] | ||
| 16 | Signed-off-by: Peter Marko <peter.marko@siemens.com> | ||
| 17 | --- | ||
| 18 | gio/tests/gdbus-subscribe.c | 13 +++++++++++++ | ||
| 19 | 1 file changed, 13 insertions(+) | ||
| 20 | |||
| 21 | diff --git a/gio/tests/gdbus-subscribe.c b/gio/tests/gdbus-subscribe.c | ||
| 22 | index af100de7d..171d6107d 100644 | ||
| 23 | --- a/gio/tests/gdbus-subscribe.c | ||
| 24 | +++ b/gio/tests/gdbus-subscribe.c | ||
| 25 | @@ -440,6 +440,19 @@ static const TestPlan plan_limit_by_well_known_name = | ||
| 26 | .iface = EXAMPLE_INTERFACE, | ||
| 27 | }, | ||
| 28 | }, | ||
| 29 | + { | ||
| 30 | + /* When the service sends a signal with the name it already owns, | ||
| 31 | + * it should get through */ | ||
| 32 | + .action = TEST_ACTION_EMIT_SIGNAL, | ||
| 33 | + .u.signal = { | ||
| 34 | + .sender = TEST_CONN_SERVICE, | ||
| 35 | + .path = EXAMPLE_PATH, | ||
| 36 | + .iface = EXAMPLE_INTERFACE, | ||
| 37 | + .member = FOO_SIGNAL, | ||
| 38 | + .received_by_conn = 1, | ||
| 39 | + .received_by_proxy = 1 | ||
| 40 | + }, | ||
| 41 | + }, | ||
| 42 | { | ||
| 43 | /* Service claims another name */ | ||
| 44 | .action = TEST_ACTION_OWN_NAME, | ||
| 45 | -- | ||
| 46 | 2.30.2 | ||
| 47 | |||
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2024-34397_16.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2024-34397_16.patch new file mode 100644 index 0000000000..d582f84a36 --- /dev/null +++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2024-34397_16.patch | |||
| @@ -0,0 +1,62 @@ | |||
| 1 | From 8338f7ac107f642283437d05d7b4d49ca8968cdf Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Simon McVittie <smcv@collabora.com> | ||
| 3 | Date: Fri, 8 Mar 2024 19:53:22 +0000 | ||
| 4 | Subject: [PATCH 16/18] tests: Add a test for signal filtering by well-known | ||
| 5 | name | ||
| 6 | |||
| 7 | The vulnerability reported as GNOME/glib#3268 can be characterized | ||
| 8 | as: these signals from an attacker should not be delivered to either | ||
| 9 | the GDBusConnection or the GDBusProxy, but in fact they are (in at | ||
| 10 | least some scenarios). | ||
| 11 | |||
| 12 | Reproduces: https://gitlab.gnome.org/GNOME/glib/-/issues/3268 | ||
| 13 | Signed-off-by: Simon McVittie <smcv@collabora.com> | ||
| 14 | |||
| 15 | CVE: CVE-2024-34397 | ||
| 16 | Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/glib/-/commit/8338f7ac107f642283437d05d7b4d49ca8968cdf] | ||
| 17 | Signed-off-by: Peter Marko <peter.marko@siemens.com> | ||
| 18 | --- | ||
| 19 | gio/tests/gdbus-subscribe.c | 27 +++++++++++++++++++++++++++ | ||
| 20 | 1 file changed, 27 insertions(+) | ||
| 21 | |||
| 22 | diff --git a/gio/tests/gdbus-subscribe.c b/gio/tests/gdbus-subscribe.c | ||
| 23 | index 171d6107d..5406ba7e2 100644 | ||
| 24 | --- a/gio/tests/gdbus-subscribe.c | ||
| 25 | +++ b/gio/tests/gdbus-subscribe.c | ||
| 26 | @@ -440,6 +440,33 @@ static const TestPlan plan_limit_by_well_known_name = | ||
| 27 | .iface = EXAMPLE_INTERFACE, | ||
| 28 | }, | ||
| 29 | }, | ||
| 30 | + { | ||
| 31 | + /* Attacker wants to trick subscriber into thinking that service | ||
| 32 | + * sent a signal */ | ||
| 33 | + .action = TEST_ACTION_EMIT_SIGNAL, | ||
| 34 | + .u.signal = { | ||
| 35 | + .sender = TEST_CONN_ATTACKER, | ||
| 36 | + .path = EXAMPLE_PATH, | ||
| 37 | + .iface = EXAMPLE_INTERFACE, | ||
| 38 | + .member = FOO_SIGNAL, | ||
| 39 | + .received_by_conn = 0, | ||
| 40 | + .received_by_proxy = 0 | ||
| 41 | + }, | ||
| 42 | + }, | ||
| 43 | + { | ||
| 44 | + /* Attacker tries harder, by sending a signal unicast directly to | ||
| 45 | + * the subscriber */ | ||
| 46 | + .action = TEST_ACTION_EMIT_SIGNAL, | ||
| 47 | + .u.signal = { | ||
| 48 | + .sender = TEST_CONN_ATTACKER, | ||
| 49 | + .unicast_to = TEST_CONN_SUBSCRIBER, | ||
| 50 | + .path = EXAMPLE_PATH, | ||
| 51 | + .iface = EXAMPLE_INTERFACE, | ||
| 52 | + .member = FOO_SIGNAL, | ||
| 53 | + .received_by_conn = 0, | ||
| 54 | + .received_by_proxy = 0 | ||
| 55 | + }, | ||
| 56 | + }, | ||
| 57 | { | ||
| 58 | /* When the service sends a signal with the name it already owns, | ||
| 59 | * it should get through */ | ||
| 60 | -- | ||
| 61 | 2.30.2 | ||
| 62 | |||
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2024-34397_17.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2024-34397_17.patch new file mode 100644 index 0000000000..7f5776d0c3 --- /dev/null +++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2024-34397_17.patch | |||
| @@ -0,0 +1,121 @@ | |||
| 1 | From ff467241a37a0119d3c6df53548bb61fe4d4fbf9 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Simon McVittie <smcv@collabora.com> | ||
| 3 | Date: Tue, 23 Apr 2024 21:39:43 +0100 | ||
| 4 | Subject: [PATCH 17/18] tests: Ensure that unsubscribing with GetNameOwner | ||
| 5 | in-flight doesn't crash | ||
| 6 | |||
| 7 | This was a bug that existed during development of this branch; make sure | ||
| 8 | it doesn't come back. | ||
| 9 | |||
| 10 | This test fails with a use-after-free and crash if we comment out the | ||
| 11 | part of name_watcher_unref_watched_name() that removes the name watcher | ||
| 12 | from `map_method_serial_to_name_watcher`. | ||
| 13 | |||
| 14 | It would also fail with an assertion failure if we asserted in | ||
| 15 | name_watcher_unref_watched_name() that get_name_owner_serial == 0 | ||
| 16 | (i.e. that GetNameOwner is not in-flight at destruction). | ||
| 17 | |||
| 18 | Signed-off-by: Simon McVittie <smcv@collabora.com> | ||
| 19 | |||
| 20 | CVE: CVE-2024-34397 | ||
| 21 | Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/glib/-/commit/ff467241a37a0119d3c6df53548bb61fe4d4fbf9] | ||
| 22 | Signed-off-by: Peter Marko <peter.marko@siemens.com> | ||
| 23 | --- | ||
| 24 | gio/tests/gdbus-subscribe.c | 52 ++++++++++++++++++++++++++++++++++++- | ||
| 25 | 1 file changed, 51 insertions(+), 1 deletion(-) | ||
| 26 | |||
| 27 | diff --git a/gio/tests/gdbus-subscribe.c b/gio/tests/gdbus-subscribe.c | ||
| 28 | index 5406ba7e2..4cba4f565 100644 | ||
| 29 | --- a/gio/tests/gdbus-subscribe.c | ||
| 30 | +++ b/gio/tests/gdbus-subscribe.c | ||
| 31 | @@ -116,6 +116,7 @@ typedef struct | ||
| 32 | const char *member; | ||
| 33 | const char *arg0; | ||
| 34 | GDBusSignalFlags flags; | ||
| 35 | + gboolean unsubscribe_immediately; | ||
| 36 | } TestSubscribe; | ||
| 37 | |||
| 38 | typedef struct | ||
| 39 | @@ -141,6 +142,7 @@ typedef struct | ||
| 40 | TestEmitSignal signal; | ||
| 41 | TestSubscribe subscribe; | ||
| 42 | TestOwnName own_name; | ||
| 43 | + guint unsubscribe_undo_step; | ||
| 44 | } u; | ||
| 45 | } TestStep; | ||
| 46 | |||
| 47 | @@ -505,6 +507,43 @@ static const TestPlan plan_limit_by_well_known_name = | ||
| 48 | }, | ||
| 49 | }; | ||
| 50 | |||
| 51 | +static const TestPlan plan_unsubscribe_immediately = | ||
| 52 | +{ | ||
| 53 | + .description = "Unsubscribing before GetNameOwner can return doesn't result in a crash", | ||
| 54 | + .steps = { | ||
| 55 | + { | ||
| 56 | + /* Service already owns one name */ | ||
| 57 | + .action = TEST_ACTION_OWN_NAME, | ||
| 58 | + .u.own_name = { | ||
| 59 | + .name = ALREADY_OWNED_NAME, | ||
| 60 | + .owner = TEST_CONN_SERVICE | ||
| 61 | + }, | ||
| 62 | + }, | ||
| 63 | + { | ||
| 64 | + .action = TEST_ACTION_SUBSCRIBE, | ||
| 65 | + .u.subscribe = { | ||
| 66 | + .string_sender = ALREADY_OWNED_NAME, | ||
| 67 | + .path = EXAMPLE_PATH, | ||
| 68 | + .iface = EXAMPLE_INTERFACE, | ||
| 69 | + .unsubscribe_immediately = TRUE | ||
| 70 | + }, | ||
| 71 | + }, | ||
| 72 | + { | ||
| 73 | + .action = TEST_ACTION_EMIT_SIGNAL, | ||
| 74 | + .u.signal = { | ||
| 75 | + .sender = TEST_CONN_SERVICE, | ||
| 76 | + .path = EXAMPLE_PATH, | ||
| 77 | + .iface = EXAMPLE_INTERFACE, | ||
| 78 | + .member = FOO_SIGNAL, | ||
| 79 | + .received_by_conn = 0, | ||
| 80 | + /* The proxy can't unsubscribe, except by destroying the proxy | ||
| 81 | + * completely, which we don't currently implement in this test */ | ||
| 82 | + .received_by_proxy = 1 | ||
| 83 | + }, | ||
| 84 | + }, | ||
| 85 | + }, | ||
| 86 | +}; | ||
| 87 | + | ||
| 88 | static const TestPlan plan_limit_to_message_bus = | ||
| 89 | { | ||
| 90 | .description = "A subscription to the message bus only accepts messages " | ||
| 91 | @@ -855,8 +894,18 @@ fixture_subscribe (Fixture *f, | ||
| 92 | subscribe->flags, | ||
| 93 | subscribed_signal_cb, | ||
| 94 | f, NULL); | ||
| 95 | + | ||
| 96 | g_assert_cmpuint (id, !=, 0); | ||
| 97 | - f->subscriptions[step_number] = id; | ||
| 98 | + | ||
| 99 | + if (subscribe->unsubscribe_immediately) | ||
| 100 | + { | ||
| 101 | + g_test_message ("\tImmediately unsubscribing"); | ||
| 102 | + g_dbus_connection_signal_unsubscribe (subscriber, id); | ||
| 103 | + } | ||
| 104 | + else | ||
| 105 | + { | ||
| 106 | + f->subscriptions[step_number] = id; | ||
| 107 | + } | ||
| 108 | } | ||
| 109 | |||
| 110 | if (f->mode != SUBSCRIPTION_MODE_CONN) | ||
| 111 | @@ -1287,6 +1336,7 @@ main (int argc, | ||
| 112 | ADD_SUBSCRIBE_TEST (nonexistent_unique_name); | ||
| 113 | ADD_SUBSCRIBE_TEST (limit_by_well_known_name); | ||
| 114 | ADD_SUBSCRIBE_TEST (limit_to_message_bus); | ||
| 115 | + ADD_SUBSCRIBE_TEST (unsubscribe_immediately); | ||
| 116 | |||
| 117 | return g_test_run(); | ||
| 118 | } | ||
| 119 | -- | ||
| 120 | 2.30.2 | ||
| 121 | |||
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2024-34397_18.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2024-34397_18.patch new file mode 100644 index 0000000000..a19ce24555 --- /dev/null +++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2024-34397_18.patch | |||
| @@ -0,0 +1,50 @@ | |||
| 1 | From fe11c6a513a1b16462442e361bab753246c8de2e Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Simon McVittie <smcv@debian.org> | ||
| 3 | Date: Mon, 6 May 2024 21:24:53 +0100 | ||
| 4 | Subject: [PATCH 18/18] gdbus-proxy test: Wait before asserting name owner has | ||
| 5 | gone away | ||
| 6 | |||
| 7 | GDBusConnection sends each signal to recipients in a separate idle | ||
| 8 | callback, and there's no particular guarantee about the order in which | ||
| 9 | they're scheduled or dispatched. For the NameOwnerChanged signal that | ||
| 10 | reports the name becoming unowned, it's possible that g_bus_watch_name() | ||
| 11 | gets its idle callback called before the GDBusProxy:g-name-owner | ||
| 12 | machinery has updated the name owner, in which case the assertion | ||
| 13 | will fail. | ||
| 14 | |||
| 15 | Fixing GNOME/glib#3268 introduced a new subscription to NameOwnerChanged | ||
| 16 | which can alter the order of delivery, particularly in the case where | ||
| 17 | G_DBUS_PROXY_FLAGS_NO_MATCH_RULE was used (as tested in | ||
| 18 | /gdbus/proxy/no-match-rule). The resulting test failure is intermittent, | ||
| 19 | but reliably appears within 100 repetitions of that test. | ||
| 20 | |||
| 21 | Fixes: 511c5f5b "tests: Wait for gdbus-testserver to die when killing it" | ||
| 22 | Signed-off-by: Simon McVittie <smcv@debian.org> | ||
| 23 | |||
| 24 | CVE: CVE-2024-34397 | ||
| 25 | Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/glib/-/commit/fe11c6a513a1b16462442e361bab753246c8de2e] | ||
| 26 | Signed-off-by: Peter Marko <peter.marko@siemens.com> | ||
| 27 | --- | ||
| 28 | gio/tests/gdbus-proxy.c | 6 ++++++ | ||
| 29 | 1 file changed, 6 insertions(+) | ||
| 30 | |||
| 31 | diff --git a/gio/tests/gdbus-proxy.c b/gio/tests/gdbus-proxy.c | ||
| 32 | index eed75acf4..9303d0088 100644 | ||
| 33 | --- a/gio/tests/gdbus-proxy.c | ||
| 34 | +++ b/gio/tests/gdbus-proxy.c | ||
| 35 | @@ -778,6 +778,12 @@ kill_test_service (GDBusConnection *connection) | ||
| 36 | while (!name_disappeared) | ||
| 37 | g_main_context_iteration (NULL, TRUE); | ||
| 38 | |||
| 39 | + /* GDBusConnection doesn't guarantee that different subscriptions to the | ||
| 40 | + * same signal will get their callbacks scheduled in any particular order, | ||
| 41 | + * so make sure they have all happened */ | ||
| 42 | + while (g_main_context_iteration (NULL, FALSE)) | ||
| 43 | + continue; | ||
| 44 | + | ||
| 45 | g_bus_unwatch_name (watch_id); | ||
| 46 | #else | ||
| 47 | g_warning ("Can't kill com.example.TestService"); | ||
| 48 | -- | ||
| 49 | 2.30.2 | ||
| 50 | |||
diff --git a/meta/recipes-core/glib-2.0/glib-2.0_2.72.3.bb b/meta/recipes-core/glib-2.0/glib-2.0_2.72.3.bb index 24c590a714..35b51a3ec9 100644 --- a/meta/recipes-core/glib-2.0/glib-2.0_2.72.3.bb +++ b/meta/recipes-core/glib-2.0/glib-2.0_2.72.3.bb | |||
| @@ -31,6 +31,24 @@ SRC_URI = "${GNOME_MIRROR}/glib/${SHRT_VER}/glib-${PV}.tar.xz \ | |||
| 31 | file://CVE-2023-32611-0002.patch \ | 31 | file://CVE-2023-32611-0002.patch \ |
| 32 | file://CVE-2023-32643.patch \ | 32 | file://CVE-2023-32643.patch \ |
| 33 | file://CVE-2023-32636.patch \ | 33 | file://CVE-2023-32636.patch \ |
| 34 | file://CVE-2024-34397_01.patch \ | ||
| 35 | file://CVE-2024-34397_02.patch \ | ||
| 36 | file://CVE-2024-34397_03.patch \ | ||
| 37 | file://CVE-2024-34397_04.patch \ | ||
| 38 | file://CVE-2024-34397_05.patch \ | ||
| 39 | file://CVE-2024-34397_06.patch \ | ||
| 40 | file://CVE-2024-34397_07.patch \ | ||
| 41 | file://CVE-2024-34397_08.patch \ | ||
| 42 | file://CVE-2024-34397_09.patch \ | ||
| 43 | file://CVE-2024-34397_10.patch \ | ||
| 44 | file://CVE-2024-34397_11.patch \ | ||
| 45 | file://CVE-2024-34397_12.patch \ | ||
| 46 | file://CVE-2024-34397_13.patch \ | ||
| 47 | file://CVE-2024-34397_14.patch \ | ||
| 48 | file://CVE-2024-34397_15.patch \ | ||
| 49 | file://CVE-2024-34397_16.patch \ | ||
| 50 | file://CVE-2024-34397_17.patch \ | ||
| 51 | file://CVE-2024-34397_18.patch \ | ||
| 34 | " | 52 | " |
| 35 | SRC_URI:append:class-native = " file://relocate-modules.patch" | 53 | SRC_URI:append:class-native = " file://relocate-modules.patch" |
| 36 | 54 | ||
