From 5377b4d9061b73bb47af85cc99253a18dc58e83e Mon Sep 17 00:00:00 2001
From: Simon McVittie <smcv@collabora.com>
Date: Tue, 23 Apr 2024 20:39:05 +0100
Subject: [PATCH 12/18] gdbusconnection: Stop storing sender_unique_name in
 SignalData

This will become confusing when we start tracking the owner of a
well-known-name sender, and it's redundant anyway. Instead, track the
1 bit of data that we actually need: whether it's a well-known name.

Strictly speaking this too is redundant, because it's syntactically
derivable from the sender, but only via extra string operations.
A subsequent commit will add a data structure to keep track of the
owner of a well-known-name sender, at which point this boolean will
be replaced by the presence or absence of that data structure.

Signed-off-by: Simon McVittie <smcv@collabora.com>

CVE: CVE-2024-34397
Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/glib/-/commit/5377b4d9061b73bb47af85cc99253a18dc58e83e]
Signed-off-by: Peter Marko <peter.marko@siemens.com>
---
 gio/gdbusconnection.c | 36 ++++++++++++++++++++++++------------
 1 file changed, 24 insertions(+), 12 deletions(-)

diff --git a/gio/gdbusconnection.c b/gio/gdbusconnection.c
index 114cdde29..8c1d77b62 100644
--- a/gio/gdbusconnection.c
+++ b/gio/gdbusconnection.c
@@ -323,19 +323,19 @@ typedef struct
 {
   gchar *rule;
   gchar *sender;
-  gchar *sender_unique_name; /* if sender is unique or org.freedesktop.DBus, then that name... otherwise blank */
   gchar *interface_name;
   gchar *member;
   gchar *object_path;
   gchar *arg0;
   GDBusSignalFlags flags;
   GPtrArray *subscribers;  /* (owned) (element-type SignalSubscriber) */
+  gboolean sender_is_its_own_owner;
 } SignalData;
 
 static SignalData *
 signal_data_new_take (gchar *rule,
                       gchar *sender,
-                      gchar *sender_unique_name,
+                      gboolean sender_is_its_own_owner,
                       gchar *interface_name,
                       gchar *member,
                       gchar *object_path,
@@ -346,7 +346,7 @@ signal_data_new_take (gchar *rule,
 
   signal_data->rule = rule;
   signal_data->sender = sender;
-  signal_data->sender_unique_name = sender_unique_name;
+  signal_data->sender_is_its_own_owner = sender_is_its_own_owner;
   signal_data->interface_name = interface_name;
   signal_data->member = member;
   signal_data->object_path = object_path;
@@ -361,7 +361,6 @@ signal_data_free (SignalData *signal_data)
 {
   g_free (signal_data->rule);
   g_free (signal_data->sender);
-  g_free (signal_data->sender_unique_name);
   g_free (signal_data->interface_name);
   g_free (signal_data->member);
   g_free (signal_data->object_path);
@@ -3438,7 +3437,7 @@ remove_match_rule (GDBusConnection *connection,
 static gboolean
 is_signal_data_for_name_lost_or_acquired (SignalData *signal_data)
 {
-  return g_strcmp0 (signal_data->sender_unique_name, "org.freedesktop.DBus") == 0 &&
+  return g_strcmp0 (signal_data->sender, "org.freedesktop.DBus") == 0 &&
          g_strcmp0 (signal_data->interface_name, "org.freedesktop.DBus") == 0 &&
          g_strcmp0 (signal_data->object_path, "/org/freedesktop/DBus") == 0 &&
          (g_strcmp0 (signal_data->member, "NameLost") == 0 ||
@@ -3450,7 +3449,8 @@ is_signal_data_for_name_lost_or_acquired (SignalData *signal_data)
 /* called in any thread, connection lock is held */
 static void
 add_signal_data (GDBusConnection *connection,
-                 SignalData      *signal_data)
+                 SignalData      *signal_data,
+                 const char      *sender_unique_name)
 {
   GPtrArray *signal_data_array;
 
@@ -3470,12 +3470,12 @@ add_signal_data (GDBusConnection *connection,
     }
 
   signal_data_array = g_hash_table_lookup (connection->map_sender_unique_name_to_signal_data_array,
-                                           signal_data->sender_unique_name);
+                                           sender_unique_name);
   if (signal_data_array == NULL)
     {
       signal_data_array = g_ptr_array_new ();
       g_hash_table_insert (connection->map_sender_unique_name_to_signal_data_array,
-                           g_strdup (signal_data->sender_unique_name),
+                           g_strdup (sender_unique_name),
                            signal_data_array);
     }
   g_ptr_array_add (signal_data_array, signal_data);
@@ -3572,6 +3572,7 @@ g_dbus_connection_signal_subscribe (GDBusConnection     *connection,
   gchar *rule;
   SignalData *signal_data;
   SignalSubscriber *subscriber;
+  gboolean sender_is_its_own_owner;
   const gchar *sender_unique_name;
 
   /* Right now we abort if AddMatch() fails since it can only fail with the bus being in
@@ -3607,6 +3608,11 @@ g_dbus_connection_signal_subscribe (GDBusConnection     *connection,
   rule = args_to_rule (sender, interface_name, member, object_path, arg0, flags);
 
   if (sender != NULL && (g_dbus_is_unique_name (sender) || g_strcmp0 (sender, "org.freedesktop.DBus") == 0))
+    sender_is_its_own_owner = TRUE;
+  else
+    sender_is_its_own_owner = FALSE;
+
+  if (sender_is_its_own_owner)
     sender_unique_name = sender;
   else
     sender_unique_name = "";
@@ -3630,14 +3636,14 @@ g_dbus_connection_signal_subscribe (GDBusConnection     *connection,
 
   signal_data = signal_data_new_take (g_steal_pointer (&rule),
                                       g_strdup (sender),
-                                      g_strdup (sender_unique_name),
+                                      sender_is_its_own_owner,
                                       g_strdup (interface_name),
                                       g_strdup (member),
                                       g_strdup (object_path),
                                       g_strdup (arg0),
                                       flags);
   g_ptr_array_add (signal_data->subscribers, subscriber);
-  add_signal_data (connection, signal_data);
+  add_signal_data (connection, signal_data, sender_unique_name);
 
  out:
   g_hash_table_insert (connection->map_id_to_signal_data,
@@ -3661,22 +3667,28 @@ static void
 remove_signal_data_if_unused (GDBusConnection *connection,
                               SignalData *signal_data)
 {
+  const gchar *sender_unique_name;
   GPtrArray *signal_data_array;
 
   if (signal_data->subscribers->len != 0)
     return;
 
+  if (signal_data->sender_is_its_own_owner)
+    sender_unique_name = signal_data->sender;
+  else
+    sender_unique_name = "";
+
   g_warn_if_fail (g_hash_table_remove (connection->map_rule_to_signal_data, signal_data->rule));
 
   signal_data_array = g_hash_table_lookup (connection->map_sender_unique_name_to_signal_data_array,
-                                           signal_data->sender_unique_name);
+                                           sender_unique_name);
   g_warn_if_fail (signal_data_array != NULL);
   g_warn_if_fail (g_ptr_array_remove (signal_data_array, signal_data));
 
   if (signal_data_array->len == 0)
     {
       g_warn_if_fail (g_hash_table_remove (connection->map_sender_unique_name_to_signal_data_array,
-                                           signal_data->sender_unique_name));
+                                           sender_unique_name));
     }
 
   /* remove the match rule from the bus unless NameLost or NameAcquired (see subscribe()) */
-- 
2.30.2

