gdbusconnection: Don't deliver signals if the sender doesn't match

Otherwise a malicious connection on a shared bus, especially the system
bus, could trick GDBus clients into processing signals sent by the
malicious connection as though they had come from the real owner of a
well-known service name.

Resolves: https://gitlab.gnome.org/GNOME/glib/-/issues/3268
Signed-off-by: Simon McVittie <smcv@collabora.com>
This commit is contained in:
Simon McVittie 2024-03-14 20:42:41 +00:00
parent d6c2a2f12e
commit ad8e763f73

View File

@ -4300,6 +4300,46 @@ schedule_callbacks (GDBusConnection *connection,
if (signal_data->object_path != NULL && g_strcmp0 (signal_data->object_path, path) != 0)
continue;
if (signal_data->shared_name_watcher != NULL)
{
/* We want signals from a specified well-known name, which means
* the signal's sender needs to be the unique name that currently
* owns that well-known name, and we will have found this
* SignalData in
* connection->map_sender_unique_name_to_signal_data_array[""]. */
const WatchedName *watched_name;
const char *current_owner;
g_assert (signal_data->sender != NULL);
/* Invariant: We never need to watch for the owner of a unique
* name, or for the owner of DBUS_SERVICE_DBUS, either of which
* is always its own owner */
g_assert (!g_dbus_is_unique_name (signal_data->sender));
g_assert (g_strcmp0 (signal_data->sender, DBUS_SERVICE_DBUS) != 0);
watched_name = signal_data->shared_name_watcher->watched_name;
g_assert (watched_name != NULL);
current_owner = watched_name->owner;
/* Skip the signal if the actual sender is not known to own
* the required name */
if (current_owner == NULL || g_strcmp0 (current_owner, sender) != 0)
continue;
}
else if (signal_data->sender != NULL)
{
/* We want signals from a unique name or o.fd.DBus... */
g_assert (g_dbus_is_unique_name (signal_data->sender)
|| g_str_equal (signal_data->sender, DBUS_SERVICE_DBUS));
/* ... which means we must have found this SignalData in
* connection->map_sender_unique_name_to_signal_data_array[signal_data->sender],
* therefore we would only have found it if the signal's
* actual sender matches the required signal_data->sender */
g_assert (g_strcmp0 (signal_data->sender, sender) == 0);
}
/* else the sender is unspecified and we will accept anything */
if (signal_data->arg0 != NULL)
{
if (signal_data->flags & G_DBUS_SIGNAL_FLAGS_MATCH_ARG0_NAMESPACE)