Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package xdg-dbus-proxy for openSUSE:Factory 
checked in at 2026-08-22 21:34:26
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/xdg-dbus-proxy (Old)
 and      /work/SRC/openSUSE:Factory/.xdg-dbus-proxy.new.1258 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "xdg-dbus-proxy"

Sat Aug 22 21:34:26 2026 rev:9 rq:1372904 version:0.1.8

Changes:
--------
--- /work/SRC/openSUSE:Factory/xdg-dbus-proxy/xdg-dbus-proxy.changes    
2026-04-26 21:12:42.204829108 +0200
+++ /work/SRC/openSUSE:Factory/.xdg-dbus-proxy.new.1258/xdg-dbus-proxy.changes  
2026-08-22 21:34:54.754564082 +0200
@@ -1,0 +2,15 @@
+Thu Aug 20 08:25:27 UTC 2026 - Dominique Leuenberger <[email protected]>
+
+- Update to version 0.1.8:
+  + Fix broadcast messages bypassing path/interface/member checks
+  + Improvements to the existing testing infrastructure
+  + Add tests for owning names, issuing method calls, receiving
+    messages
+
+-------------------------------------------------------------------
+Mon Aug 17 10:11:41 UTC 2026 - Zoltan Balogh <[email protected]>
+
+- Add xdg-dbus-proxy-tests subpackage with installed
+  tests for gnome-desktop-testing-runner
+
+-------------------------------------------------------------------
@@ -78 +92,0 @@
-

Old:
----
  xdg-dbus-proxy-0.1.7.tar.xz

New:
----
  xdg-dbus-proxy-0.1.8.tar.xz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ xdg-dbus-proxy.spec ++++++
--- /var/tmp/diff_new_pack.rAltVY/_old  2026-08-22 21:34:56.258617712 +0200
+++ /var/tmp/diff_new_pack.rAltVY/_new  2026-08-22 21:34:56.263617891 +0200
@@ -1,7 +1,7 @@
 #
 # spec file for package xdg-dbus-proxy
 #
-# Copyright (c) 2024 SUSE LLC
+# Copyright (c) 2026 SUSE LLC and contributors
 # Copyright (c) 2019 Bjørn Lie, Bryne, Norway.
 #
 # All modifications and additions to the file contributed by third parties
@@ -18,7 +18,7 @@
 
 
 Name:           xdg-dbus-proxy
-Version:        0.1.7
+Version:        0.1.8
 Release:        0
 Summary:        Filtering proxy for D-Bus connections
 License:        LGPL-2.1-or-later
@@ -49,6 +49,7 @@
 
 %build
 %meson \
+       -Dinstalled_tests=true \
        %{nil}
 %meson_build
 
@@ -64,3 +65,18 @@
 %{_bindir}/xdg-dbus-proxy
 %{_mandir}/man1/xdg-dbus-proxy.1%{ext_man}
 
+%package tests
+Summary:        Installed tests for %{name}
+Requires:       %{name} = %{version}
+Requires:       dbus-1
+Requires:       gnome-desktop-testing
+
+%description tests
+Installed tests for xdg-dbus-proxy, compatible with 
gnome-desktop-testing-runner.
+
+%files tests
+%dir %{_libexecdir}/installed-tests
+%{_libexecdir}/installed-tests/%{name}/
+%dir %{_datadir}/installed-tests
+%{_datadir}/installed-tests/%{name}/
+

++++++ _scmsync.obsinfo ++++++
--- /var/tmp/diff_new_pack.rAltVY/_old  2026-08-22 21:34:56.363621457 +0200
+++ /var/tmp/diff_new_pack.rAltVY/_new  2026-08-22 21:34:56.367621599 +0200
@@ -1,6 +1,6 @@
-mtime: 1776410437
-commit: 700fea6c729eaf8f4c6224bd1794cc39755db804dff571768942871bda8c3abd
+mtime: 1787214355
+commit: 3ce2c8449f3e5125299f57cce14b06e0b1ff1ab847c7748a3a3c082758f1e11d
 url: https://src.opensuse.org/GNOME/xdg-dbus-proxy
-revision: 700fea6c729eaf8f4c6224bd1794cc39755db804dff571768942871bda8c3abd
+revision: 3ce2c8449f3e5125299f57cce14b06e0b1ff1ab847c7748a3a3c082758f1e11d
 projectscmsync: https://src.opensuse.org/GNOME/_ObsPrj
 

++++++ build.specials.obscpio ++++++

++++++ build.specials.obscpio ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/.gitignore new/.gitignore
--- old/.gitignore      1970-01-01 01:00:00.000000000 +0100
+++ new/.gitignore      2026-08-20 10:25:55.000000000 +0200
@@ -0,0 +1,4 @@
+*.obscpio
+*.osc
+_build.*
+.pbuild

++++++ xdg-dbus-proxy-0.1.7.tar.xz -> xdg-dbus-proxy-0.1.8.tar.xz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xdg-dbus-proxy-0.1.7/NEWS 
new/xdg-dbus-proxy-0.1.8/NEWS
--- old/xdg-dbus-proxy-0.1.7/NEWS       2026-04-07 18:51:52.000000000 +0200
+++ new/xdg-dbus-proxy-0.1.8/NEWS       2026-08-11 14:05:09.000000000 +0200
@@ -1,3 +1,12 @@
+Changes in 0.1.8
+================
+
+Released 2026-08-11
+
+  * Fix broadcast messages bypassing path/interface/member checks
+  * Improvements to the existing testing infrastructure
+  * Add tests for owning names, issuing method calls, receiving messages
+
 Changes in 0.1.7
 ================
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xdg-dbus-proxy-0.1.7/flatpak-proxy.c 
new/xdg-dbus-proxy-0.1.8/flatpak-proxy.c
--- old/xdg-dbus-proxy-0.1.7/flatpak-proxy.c    2026-04-07 18:51:52.000000000 
+0200
+++ new/xdg-dbus-proxy-0.1.8/flatpak-proxy.c    2026-08-11 14:05:09.000000000 
+0200
@@ -2808,11 +2808,11 @@
           policy = flatpak_proxy_client_get_max_policy_and_matched (client, 
header->sender, &filters);
 
           if (policy == FLATPAK_POLICY_OWN ||
-              policy == FLATPAK_POLICY_TALK ||
-              any_filter_matches (filters, FILTER_TYPE_BROADCAST,
-                                  header->path,
-                                  header->interface,
-                                  header->member))
+              (policy == FLATPAK_POLICY_TALK &&
+               any_filter_matches (filters, FILTER_TYPE_BROADCAST,
+                                   header->path,
+                                   header->interface,
+                                   header->member)))
             filtered = FALSE;
 
           if (filtered)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xdg-dbus-proxy-0.1.7/meson.build 
new/xdg-dbus-proxy-0.1.8/meson.build
--- old/xdg-dbus-proxy-0.1.7/meson.build        2026-04-07 18:51:52.000000000 
+0200
+++ new/xdg-dbus-proxy-0.1.8/meson.build        2026-08-11 14:05:09.000000000 
+0200
@@ -1,7 +1,7 @@
 project(
   'xdg-dbus-proxy',
   'c',
-  version : '0.1.7',
+  version : '0.1.8',
   meson_version : '>=0.49.0',
   default_options : [
     'warning_level=2',
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xdg-dbus-proxy-0.1.7/tests/test-proxy.c 
new/xdg-dbus-proxy-0.1.8/tests/test-proxy.c
--- old/xdg-dbus-proxy-0.1.7/tests/test-proxy.c 2026-04-07 18:51:52.000000000 
+0200
+++ new/xdg-dbus-proxy-0.1.8/tests/test-proxy.c 2026-08-11 14:05:09.000000000 
+0200
@@ -33,11 +33,93 @@
 #define DBUS_SERVICE_DBUS "org.freedesktop.DBus"
 #define DBUS_PATH_DBUS "/org/freedesktop/DBus"
 #define DBUS_INTERFACE_DBUS "org.freedesktop.DBus"
+#define DBUS_INTERFACE_PEER "org.freedesktop.DBus.Peer"
+
+#define DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER 1
+#define DBUS_REQUEST_NAME_REPLY_IN_QUEUE 2
+#define DBUS_REQUEST_NAME_REPLY_EXISTS 3
+#define DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER 4
+
+#define CANNOT_ACCESS_NAME "com.example.CannotAccess"
+#define CAN_SEE_NAME "com.example.CanSee"
+#define CAN_TALK_NAME "com.example.CanTalk"
+#define CAN_OWN_NAME "com.example.CanOwn"
+#define CAN_CALL_ANYTHING_NAME "com.example.CanCallAny"
+#define CAN_CALL_SOME_NAME "com.example.CanCallSome"
+#define CAN_RECEIVE_ANYTHING_NAME "com.example.CanReceiveAny"
+#define CAN_RECEIVE_SOME_NAME "com.example.CanReceiveSome"
+
+#define EXAMPLE_IFACE "net.example.AnyInterface"
+#define EXAMPLE_METHOD "Echo"
+#define EXAMPLE_SIGNAL "Shouted"
+#define EXAMPLE_PATH "/path"
+#define CAN_CALL_SOME_IFACE "org.example.CanCallThis"
+#define CAN_CALL_SOME_METHOD "OnlyThisMethod"
+#define CAN_CALL_SOME_PATH "/only/this/path"
+#define CAN_RECEIVE_SOME_IFACE "org.example.CanReceiveThis"
+#define CAN_RECEIVE_SOME_SIGNAL "JustThisSignal"
+#define CAN_RECEIVE_SOME_PATH "/just/this/path"
+
+static void
+ready_cb (GObject *source_object,
+          GAsyncResult *result,
+          void *user_data)
+{
+  GAsyncResult **result_p = user_data;
+
+  g_assert_nonnull (result_p);
+  g_assert_null (*result_p);
+  *result_p = g_object_ref (result);
+}
+
+typedef struct
+{
+  GDBusConnection *conn;
+  const char *label;
+  const char *unique_name;
+  guint filter;
+  int n_method_calls;       /* atomic */
+  int n_unicast_signals;    /* atomic */
+  int n_broadcasts;         /* atomic */
+} Connection;
+
+static void
+connection_clear (Connection *self)
+{
+  if (self->conn != NULL)
+    {
+      g_autoptr(GError) error = NULL;
+
+      if (self->filter != 0)
+        {
+          g_dbus_connection_remove_filter (self->conn, self->filter);
+          self->filter = 0;
+        }
+
+      g_dbus_connection_close_sync (self->conn, NULL, &error);
+
+      if (error != NULL)
+        g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CLOSED);
+    }
+
+  self->unique_name = NULL;
+  g_clear_object (&self->conn);
+}
 
 typedef struct
 {
-  GDBusConnection *proxied_conn;
+  Connection proxied;
+  Connection cannot_access_conn;
+  Connection can_see_conn;
+  Connection can_talk_conn;
+  Connection can_own_conn;
+  Connection can_call_anything_conn;
+  Connection can_call_some_conn;
+  Connection can_receive_anything_conn;
+  Connection can_receive_some_conn;
+  GHashTable *connections_by_name;
   GSubprocess *dbus_daemon;
+  GSubprocess *monitor;
   GSubprocess *proxy;
   gchar *dbus_address;
   gchar *temp_directory;
@@ -52,6 +134,140 @@
   int dummy;
 } Config;
 
+static GDBusMessage *
+conn_filter_cb (GDBusConnection *conn,
+                GDBusMessage *message,
+                gboolean incoming,
+                void *user_data)
+{
+  Connection *conn_info = user_data;
+
+  g_assert (conn == conn_info->conn);
+
+  if (incoming)
+    {
+      GDBusMessageType type = g_dbus_message_get_message_type (message);
+      const char *sender = g_dbus_message_get_sender (message);
+      const char *dest = g_dbus_message_get_destination (message);
+      const char *path = g_dbus_message_get_path (message);
+      const char *iface = g_dbus_message_get_interface (message);
+      const char *member = g_dbus_message_get_member (message);
+
+      g_test_message ("%s got message type %u, from=%s, to=%s, path=%s, %s.%s",
+                      conn_info->label,
+                      type,
+                      sender ?: "(message bus)",
+                      dest ?: "(broadcast)",
+                      path ?: "(none)",
+                      iface ?: "(none)",
+                      member ?: "(none)");
+
+      switch (type)
+        {
+          case G_DBUS_MESSAGE_TYPE_METHOD_CALL:
+            g_test_message ("%s got method call", conn_info->label);
+            g_atomic_int_inc (&conn_info->n_method_calls);
+            break;
+
+          case G_DBUS_MESSAGE_TYPE_SIGNAL:
+            if (sender == NULL)
+              {
+                g_test_message ("%s got signal from message bus, ignoring", 
conn_info->label);
+              }
+            else if (dest != NULL && dest[0] != '\0')
+              {
+                g_test_message ("%s got unicast signal", conn_info->label);
+                g_atomic_int_inc (&conn_info->n_unicast_signals);
+              }
+            else
+              {
+                g_test_message ("%s got broadcast signal", conn_info->label);
+                g_atomic_int_inc (&conn_info->n_broadcasts);
+              }
+
+            break;
+
+          case G_DBUS_MESSAGE_TYPE_METHOD_RETURN:
+            g_test_message ("%s got method reply", conn_info->label);
+            break;
+
+          case G_DBUS_MESSAGE_TYPE_ERROR:
+            g_test_message ("%s got error reply", conn_info->label);
+            break;
+
+          case G_DBUS_MESSAGE_TYPE_INVALID:
+          default:
+            g_assert_not_reached ();
+        }
+    }
+
+  return message;
+}
+
+/*
+ * Open a direct connection to the bus
+ */
+static void
+fixture_connect (Fixture *f,
+                 Connection *conn,
+                 const char *name)
+{
+  g_autoptr(GError) error = NULL;
+
+  g_return_if_fail (conn != NULL);
+  g_return_if_fail (conn->conn == NULL);
+
+  if (name != NULL)
+    conn->label = name;
+  else
+    conn->label = "(unnamed connection)";
+
+  conn->conn = g_dbus_connection_new_for_address_sync (f->dbus_address,
+                                                       
(G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT
+                                                        | 
G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION),
+                                                       NULL,    /* observer */
+                                                       NULL,    /* cancellable 
*/
+                                                       &error);
+  g_assert_no_error (error);
+  g_assert_nonnull (conn->conn);
+  conn->unique_name = g_dbus_connection_get_unique_name (conn->conn);
+
+  if (name != NULL)
+    {
+      g_autoptr(GVariant) tuple = NULL;
+      guint32 result = 0;
+
+      tuple = g_dbus_connection_call_sync (conn->conn,
+                                           DBUS_SERVICE_DBUS,
+                                           DBUS_PATH_DBUS,
+                                           DBUS_INTERFACE_DBUS,
+                                           "RequestName",
+                                           g_variant_new ("(su)",
+                                                           name,
+                                                           
(G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT
+                                                           | 
G_BUS_NAME_OWNER_FLAGS_REPLACE
+                                                           | 
G_BUS_NAME_OWNER_FLAGS_DO_NOT_QUEUE)),
+                                           G_VARIANT_TYPE ("(u)"),
+                                           G_DBUS_CALL_FLAGS_NONE,
+                                           -1,
+                                           NULL,    /* cancellable */
+                                           &error);
+      g_assert_no_error (error);
+      g_assert_nonnull (tuple);
+      g_variant_get (tuple, "(u)", &result);
+      g_assert_cmpuint (result, ==, DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER);
+
+      g_hash_table_replace (f->connections_by_name,
+                            g_strdup (name),
+                            conn);
+    }
+
+  conn->filter = g_dbus_connection_add_filter (conn->conn,
+                                               conn_filter_cb,
+                                               conn,
+                                               NULL);
+}
+
 static void
 setup (Fixture *f,
        gconstpointer context G_GNUC_UNUSED)
@@ -102,6 +318,18 @@
   *newline = '\0';
   f->dbus_address = g_strdup (address_buffer);
 
+  if (g_getenv ("TEST_DBUS_MONITOR") != NULL)
+    {
+      g_autoptr(GSubprocessLauncher) monitor_launcher = NULL;
+
+      monitor_launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_NONE);
+      g_subprocess_launcher_take_stdout_fd (monitor_launcher, dup 
(STDERR_FILENO));
+      f->monitor = g_subprocess_launcher_spawn (monitor_launcher, NULL,
+                                                "dbus-monitor",
+                                                "--address", f->dbus_address,
+                                                NULL);
+    }
+
   f->proxy_path = g_getenv ("DBUS_PROXY");
 
   if (f->proxy_path == NULL)
@@ -112,6 +340,20 @@
   f->proxy_socket = g_build_filename (f->temp_directory, "proxy", NULL);
   escaped = g_dbus_address_escape_value (f->proxy_socket);
   f->proxy_address = g_strdup_printf ("unix:path=%s", escaped);
+
+  f->connections_by_name = g_hash_table_new_full (g_str_hash,
+                                                  g_str_equal,
+                                                  g_free,
+                                                  NULL);
+
+  fixture_connect (f, &f->cannot_access_conn, CANNOT_ACCESS_NAME);
+  fixture_connect (f, &f->can_see_conn, CAN_SEE_NAME);
+  fixture_connect (f, &f->can_talk_conn, CAN_TALK_NAME);
+  fixture_connect (f, &f->can_own_conn, CAN_OWN_NAME);
+  fixture_connect (f, &f->can_call_anything_conn, CAN_CALL_ANYTHING_NAME);
+  fixture_connect (f, &f->can_call_some_conn, CAN_CALL_SOME_NAME);
+  fixture_connect (f, &f->can_receive_anything_conn, 
CAN_RECEIVE_ANYTHING_NAME);
+  fixture_connect (f, &f->can_receive_some_conn, CAN_RECEIVE_SOME_NAME);
 }
 
 enum
@@ -122,27 +364,25 @@
 };
 
 static void
-test_basics (Fixture *f,
-             gconstpointer context G_GNUC_UNUSED)
+fixture_start_proxy (Fixture *f)
 {
   g_autoptr(GSubprocessLauncher) launcher = NULL;
   g_autoptr(GError) error = NULL;
   g_autoptr(GVariant) tuple = NULL;
-  g_auto(GStrv) strv = NULL;
-  const char *proxied_name;
   int sync_pipe[PIPE_FDS];
   char buf;
   ssize_t bytes_read;
-  gsize i;
-  gboolean found;
-
-  alarm (30);
 
+#if GLIB_CHECK_VERSION (2, 78, 0)
+  g_unix_open_pipe (sync_pipe, O_CLOEXEC, &error);
+#else
   g_unix_open_pipe (sync_pipe, FD_CLOEXEC, &error);
+#endif
   g_assert_no_error (error);
   f->sync_pipe = sync_pipe[READ_END];
 
-  launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_STDOUT_PIPE);
+  launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_NONE);
+  g_subprocess_launcher_take_fd (launcher, dup (STDERR_FILENO), STDOUT_FILENO);
   g_subprocess_launcher_take_fd (launcher, sync_pipe[WRITE_END], 3);
   sync_pipe[WRITE_END] = -1;
 
@@ -151,6 +391,15 @@
                                           "--fd=3",
                                           f->dbus_address,
                                           f->proxy_socket,
+                                          "--filter",
+                                          "--log",
+                                          "--see=" CAN_SEE_NAME,
+                                          "--talk=" CAN_TALK_NAME,
+                                          "--own=" CAN_OWN_NAME,
+                                          "--call=" CAN_CALL_ANYTHING_NAME 
"=*",
+                                          "--call=" CAN_CALL_SOME_NAME "=" 
CAN_CALL_SOME_IFACE "." CAN_CALL_SOME_METHOD "@" CAN_CALL_SOME_PATH,
+                                          "--broadcast=" 
CAN_RECEIVE_ANYTHING_NAME "=*",
+                                          "--broadcast=" CAN_RECEIVE_SOME_NAME 
"=" CAN_RECEIVE_SOME_IFACE "." CAN_RECEIVE_SOME_SIGNAL "@" 
CAN_RECEIVE_SOME_PATH,
                                           NULL);
   g_assert_no_error (error);
   g_assert_nonnull (f->proxy);
@@ -159,15 +408,49 @@
   bytes_read = read (sync_pipe[READ_END], &buf, 1);
   g_assert_cmpint (bytes_read, ==, 1);
 
-  f->proxied_conn = g_dbus_connection_new_for_address_sync (f->proxy_address,
-                                                            
G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT
-                                                            | 
G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION,
-                                                            NULL, NULL, 
&error);
+  f->proxied.label = "Sandboxed connection";
+  f->proxied.conn = g_dbus_connection_new_for_address_sync (f->proxy_address,
+                                                            
(G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT
+                                                             | 
G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION),
+                                                            NULL,    /* 
observer */
+                                                            NULL,    /* 
cancellable */
+                                                            &error);
+  g_assert_no_error (error);
+  g_assert_nonnull (f->proxied.conn);
+  f->proxied.unique_name = g_dbus_connection_get_unique_name (f->proxied.conn);
+  tuple = g_dbus_connection_call_sync (f->proxied.conn,
+                                       DBUS_SERVICE_DBUS,
+                                       DBUS_PATH_DBUS,
+                                       DBUS_INTERFACE_DBUS,
+                                       "AddMatch",
+                                       g_variant_new ("(s)", ""),
+                                       G_VARIANT_TYPE ("()"),
+                                       G_DBUS_CALL_FLAGS_NONE,
+                                       -1,
+                                       NULL,    /* cancellable */
+                                       &error);
   g_assert_no_error (error);
-  g_assert_nonnull (f->proxied_conn);
-  proxied_name = g_dbus_connection_get_unique_name (f->proxied_conn);
+  f->proxied.filter = g_dbus_connection_add_filter (f->proxied.conn,
+                                                    conn_filter_cb,
+                                                    &f->proxied,
+                                                    NULL);
+}
 
-  tuple = g_dbus_connection_call_sync (f->proxied_conn, DBUS_SERVICE_DBUS,
+static void
+test_basics (Fixture *f,
+             gconstpointer context G_GNUC_UNUSED)
+{
+  g_autoptr(GError) error = NULL;
+  g_autoptr(GVariant) tuple = NULL;
+  g_auto(GStrv) strv = NULL;
+  gsize i;
+  gboolean found;
+
+  alarm (30);
+
+  fixture_start_proxy (f);
+
+  tuple = g_dbus_connection_call_sync (f->proxied.conn, DBUS_SERVICE_DBUS,
                                        DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS,
                                        "ListNames", NULL,
                                        G_VARIANT_TYPE ("(as)"),
@@ -184,19 +467,376 @@
     {
       g_test_message ("ListNames(): %s", strv[i]);
 
-      if (g_strcmp0 (strv[i], proxied_name) == 0)
+      if (g_strcmp0 (strv[i], f->proxied.unique_name) == 0)
         found = TRUE;
     }
 
   g_assert_true (found);
 }
 
+typedef struct
+{
+  const char *name;
+  const char *path;
+  const char *iface;
+  const char *method;
+  gboolean can_call;
+  gboolean can_see;
+} CallTest;
+
+static const CallTest call_tests[] =
+{
+  { CANNOT_ACCESS_NAME, EXAMPLE_PATH, EXAMPLE_IFACE, EXAMPLE_METHOD,
+    .can_call = FALSE, .can_see = FALSE },
+  { CAN_SEE_NAME, EXAMPLE_PATH, EXAMPLE_IFACE, EXAMPLE_METHOD,
+    .can_call = FALSE, .can_see = TRUE },
+  { CAN_TALK_NAME, EXAMPLE_PATH, EXAMPLE_IFACE, EXAMPLE_METHOD,
+    .can_call = TRUE, .can_see = TRUE },
+  { CAN_OWN_NAME, EXAMPLE_PATH, EXAMPLE_IFACE, EXAMPLE_METHOD,
+    .can_call = TRUE, .can_see = TRUE },
+  { CAN_RECEIVE_ANYTHING_NAME, EXAMPLE_PATH, EXAMPLE_IFACE, EXAMPLE_METHOD,
+    .can_call = FALSE, .can_see = TRUE },
+  { CAN_RECEIVE_SOME_NAME, EXAMPLE_PATH, EXAMPLE_IFACE, EXAMPLE_METHOD,
+    .can_call = FALSE, .can_see = TRUE },
+
+  { CAN_CALL_ANYTHING_NAME, EXAMPLE_PATH, EXAMPLE_IFACE, EXAMPLE_METHOD,
+    .can_call = TRUE, .can_see = TRUE },
+
+  { CAN_CALL_SOME_NAME, EXAMPLE_PATH, EXAMPLE_IFACE, EXAMPLE_METHOD,
+    .can_call = FALSE, .can_see = TRUE },
+  { CAN_CALL_SOME_NAME, CAN_CALL_SOME_PATH, CAN_CALL_SOME_IFACE, 
CAN_CALL_SOME_METHOD,
+    .can_call = TRUE, .can_see = TRUE },
+  { CAN_CALL_SOME_NAME, EXAMPLE_PATH, CAN_CALL_SOME_IFACE, 
CAN_CALL_SOME_METHOD,
+    .can_call = FALSE, .can_see = TRUE },
+  { CAN_CALL_SOME_NAME, CAN_CALL_SOME_PATH, EXAMPLE_IFACE, 
CAN_CALL_SOME_METHOD,
+    .can_call = FALSE, .can_see = TRUE },
+  { CAN_CALL_SOME_NAME, CAN_CALL_SOME_PATH, CAN_CALL_SOME_IFACE, 
EXAMPLE_METHOD,
+    .can_call = FALSE, .can_see = TRUE },
+};
+
+static void
+test_call (Fixture *f,
+           gconstpointer context G_GNUC_UNUSED)
+{
+  alarm (30);
+  fixture_start_proxy (f);
+
+  for (size_t i = 0; i < G_N_ELEMENTS (call_tests); i++)
+    {
+      const CallTest *t = &call_tests[i];
+      g_autoptr(GAsyncResult) result = NULL;
+      g_autoptr(GError) error = NULL;
+      g_autoptr(GVariant) tuple = NULL;
+      const Connection *dest;
+      int n_calls_before;
+
+      g_test_message ("#%zu: sandboxed connection %s be allowed to call 
%s:%s.%s on %s",
+                      i,
+                      t->can_call ? "should" : "should not",
+                      t->path,
+                      t->iface,
+                      t->method,
+                      t->name);
+
+      dest = g_hash_table_lookup (f->connections_by_name, t->name);
+      g_assert_nonnull (dest);
+      n_calls_before = g_atomic_int_get (&dest->n_method_calls);
+
+      g_dbus_connection_call (f->proxied.conn,
+                              t->name,
+                              t->path,
+                              t->iface,
+                              t->method,
+                              NULL,
+                              G_VARIANT_TYPE ("()"),
+                              G_DBUS_CALL_FLAGS_NONE,
+                              -1,
+                              NULL,    /* cancellable */
+                              ready_cb,
+                              &result);
+
+      while (result == NULL)
+        g_main_context_iteration (NULL, TRUE);
+
+      tuple = g_dbus_connection_call_finish (f->proxied.conn, result, &error);
+      g_assert_nonnull (error);
+      g_assert_null (tuple);
+      g_test_message ("-> %s", error->message);
+
+      if (t->can_call)
+        {
+          /* If the method call was allowed, we just return an error,
+           * because for simplicity we didn't actually implement any
+           * method calls. */
+          g_assert_cmpstr (g_quark_to_string (error->domain),
+                           ==, g_quark_to_string (G_DBUS_ERROR));
+
+          switch (error->code)
+            {
+              case G_DBUS_ERROR_UNKNOWN_METHOD:
+              case G_DBUS_ERROR_UNKNOWN_INTERFACE:
+              case G_DBUS_ERROR_UNKNOWN_OBJECT:
+                /* OK */
+                break;
+
+              default:
+                g_assert_not_reached ();
+            }
+
+          g_assert_cmpint (g_atomic_int_get (&dest->n_method_calls), ==, 
n_calls_before + 1);
+        }
+      else if (t->can_see)
+        {
+          g_assert_error (error, G_DBUS_ERROR, G_DBUS_ERROR_ACCESS_DENIED);
+          g_assert_cmpint (g_atomic_int_get (&dest->n_method_calls), ==, 
n_calls_before);
+        }
+      else
+        {
+          g_assert_error (error, G_DBUS_ERROR, G_DBUS_ERROR_SERVICE_UNKNOWN);
+          g_assert_cmpint (g_atomic_int_get (&dest->n_method_calls), ==, 
n_calls_before);
+        }
+    }
+}
+
+typedef struct
+{
+  const char *name;
+  gboolean can_own;
+  gboolean can_see;
+} OwnTest;
+
+static const OwnTest own_tests[] =
+{
+  { CANNOT_ACCESS_NAME, .can_own = FALSE, .can_see = FALSE },
+  { CAN_SEE_NAME, .can_own = FALSE, .can_see = TRUE },
+  { CAN_TALK_NAME, .can_own = FALSE, .can_see = TRUE },
+  { CAN_OWN_NAME, .can_own = TRUE, .can_see = TRUE },
+  { CAN_CALL_ANYTHING_NAME, .can_own = FALSE, .can_see = TRUE },
+  { CAN_CALL_SOME_NAME, .can_own = FALSE, .can_see = TRUE },
+  { CAN_RECEIVE_ANYTHING_NAME, .can_own = FALSE, .can_see = TRUE },
+  { CAN_RECEIVE_SOME_NAME, .can_own = FALSE, .can_see = TRUE },
+};
+
+static void
+test_own (Fixture *f,
+          gconstpointer context G_GNUC_UNUSED)
+{
+  alarm (30);
+  fixture_start_proxy (f);
+
+  for (size_t i = 0; i < G_N_ELEMENTS (own_tests); i++)
+    {
+      const OwnTest *t = &own_tests[i];
+      g_autoptr(GError) error = NULL;
+      g_autoptr(GVariant) tuple = NULL;
+      const char *owner = NULL;
+
+      g_test_message ("#%zu: sandboxed connection %s be allowed to own %s",
+                      i, t->can_own ? "should" : "should not", t->name);
+
+      tuple = g_dbus_connection_call_sync (f->proxied.conn,
+                                           DBUS_SERVICE_DBUS,
+                                           DBUS_PATH_DBUS,
+                                           DBUS_INTERFACE_DBUS,
+                                           "RequestName",
+                                           g_variant_new ("(su)",
+                                                           t->name,
+                                                           
(G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT
+                                                           | 
G_BUS_NAME_OWNER_FLAGS_REPLACE
+                                                           | 
G_BUS_NAME_OWNER_FLAGS_DO_NOT_QUEUE)),
+                                           G_VARIANT_TYPE ("(u)"),
+                                           G_DBUS_CALL_FLAGS_NONE,
+                                           -1,
+                                           NULL,    /* cancellable */
+                                           &error);
+
+      if (tuple != NULL)
+        g_test_message ("-> Was allowed");
+      else
+        g_test_message ("-> Was not allowed: %s", error->message);
+
+      if (t->can_own)
+        {
+          guint32 result = 0;
+
+          g_assert_no_error (error);
+          g_assert_nonnull (tuple);
+          g_variant_get (tuple, "(u)", &result);
+          g_assert_cmpuint (result, ==, DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER);
+        }
+      else if (t->can_see)
+        {
+          g_assert_error (error, G_DBUS_ERROR, G_DBUS_ERROR_ACCESS_DENIED);
+        }
+      else
+        {
+          g_assert_error (error, G_DBUS_ERROR, G_DBUS_ERROR_SERVICE_UNKNOWN);
+        }
+
+      g_clear_error (&error);
+      g_clear_pointer (&tuple, g_variant_unref);
+
+      /* Use a different connection to check who actually owns the name */
+      tuple = g_dbus_connection_call_sync (f->cannot_access_conn.conn,
+                                           DBUS_SERVICE_DBUS,
+                                           DBUS_PATH_DBUS,
+                                           DBUS_INTERFACE_DBUS,
+                                           "GetNameOwner",
+                                           g_variant_new ("(s)", t->name),
+                                           G_VARIANT_TYPE ("(s)"),
+                                           G_DBUS_CALL_FLAGS_NONE,
+                                           -1,
+                                           NULL,    /* cancellable */
+                                           NULL);
+
+      if (tuple != NULL)
+        g_variant_get (tuple, "(&s)", &owner);
+      else
+        owner = "";
+
+      if (t->can_own)
+        g_assert_cmpstr (owner, ==, f->proxied.unique_name);
+      else
+        g_assert_cmpstr (owner, !=, f->proxied.unique_name);
+    }
+}
+
+typedef struct
+{
+  const char *name;
+  const char *path;
+  const char *iface;
+  const char *member;
+  gboolean can_receive_broadcast;
+} ReceiveTest;
+
+static const ReceiveTest receive_tests[] =
+{
+  { CANNOT_ACCESS_NAME, EXAMPLE_PATH, EXAMPLE_IFACE, EXAMPLE_SIGNAL, FALSE },
+  { CAN_SEE_NAME, EXAMPLE_PATH, EXAMPLE_IFACE, EXAMPLE_SIGNAL, FALSE },
+  { CAN_TALK_NAME, EXAMPLE_PATH, EXAMPLE_IFACE, EXAMPLE_SIGNAL, TRUE },
+  { CAN_OWN_NAME, EXAMPLE_PATH, EXAMPLE_IFACE, EXAMPLE_SIGNAL, TRUE },
+
+  /* Before GHSA-r7hp-698j-2h6c was fixed, both of these would receive the
+   * broadcast, but that was unintended */
+  { CAN_CALL_ANYTHING_NAME, EXAMPLE_PATH, EXAMPLE_IFACE, EXAMPLE_SIGNAL, FALSE 
},
+  { CAN_CALL_SOME_NAME, EXAMPLE_PATH, EXAMPLE_IFACE, EXAMPLE_SIGNAL, FALSE },
+
+  { CAN_RECEIVE_ANYTHING_NAME, EXAMPLE_PATH, EXAMPLE_IFACE, EXAMPLE_SIGNAL, 
TRUE },
+
+  { CAN_RECEIVE_SOME_NAME, CAN_RECEIVE_SOME_PATH, CAN_RECEIVE_SOME_IFACE, 
CAN_RECEIVE_SOME_SIGNAL, TRUE },
+
+  /* Before GHSA-r7hp-698j-2h6c was fixed, all of these would receive the 
broadcast,
+   * but that was unintended */
+  { CAN_RECEIVE_SOME_NAME, EXAMPLE_PATH, CAN_RECEIVE_SOME_IFACE, 
CAN_RECEIVE_SOME_SIGNAL, FALSE },
+  { CAN_RECEIVE_SOME_NAME, CAN_RECEIVE_SOME_PATH, EXAMPLE_IFACE, 
CAN_RECEIVE_SOME_SIGNAL, FALSE },
+  { CAN_RECEIVE_SOME_NAME, CAN_RECEIVE_SOME_PATH, CAN_RECEIVE_SOME_IFACE, 
EXAMPLE_SIGNAL, FALSE },
+  { CAN_RECEIVE_SOME_NAME, EXAMPLE_PATH, EXAMPLE_IFACE, EXAMPLE_SIGNAL, FALSE 
},
+};
+
+static void
+test_receive (Fixture *f,
+              gconstpointer context G_GNUC_UNUSED)
+{
+  alarm (30);
+  fixture_start_proxy (f);
+
+  for (size_t i = 0; i < G_N_ELEMENTS (receive_tests); i++)
+    {
+      g_autoptr(GAsyncResult) result = NULL;
+      g_autoptr(GVariant) tuple = NULL;
+      g_autoptr(GError) error = NULL;
+      const Connection *sender;
+      const ReceiveTest *t = &receive_tests[i];
+      int n_unicasts_before;
+      int n_broadcasts_before;
+      int n_calls_before;
+
+      g_test_message ("#%zu: sandboxed connection %s be allowed to receive 
broadcast from %s:%s.%s on %s",
+                      i,
+                      t->can_receive_broadcast ? "should" : "should not",
+                      t->path,
+                      t->iface,
+                      t->member,
+                      t->name);
+
+      sender = g_hash_table_lookup (f->connections_by_name, t->name);
+      g_assert_nonnull (sender);
+
+      n_calls_before = g_atomic_int_get (&f->proxied.n_method_calls);
+      n_unicasts_before = g_atomic_int_get (&f->proxied.n_unicast_signals);
+      n_broadcasts_before = g_atomic_int_get (&f->proxied.n_broadcasts);
+
+      /* The sandboxed recipient is only sometimes allowed to receive
+       * broadcasts. We do this first, because D-Bus preserves message
+       * order, therefore by the time we have received the unicast signal
+       * and/or the method call, it's guaranteed that this broadcast
+       * has been processed (and received, or not, as appropriate). */
+      g_dbus_connection_emit_signal (sender->conn,
+                                     NULL,
+                                     t->path,
+                                     t->iface,
+                                     t->member,
+                                     NULL,
+                                     &error);
+      g_assert_no_error (error);
+
+      /* The sandboxed recipient is always allowed to receive
+       * unicast signals. */
+      g_dbus_connection_emit_signal (sender->conn,
+                                     f->proxied.unique_name,
+                                     t->path,
+                                     t->iface,
+                                     t->member,
+                                     NULL,
+                                     &error);
+      g_assert_no_error (error);
+
+      /* The sandboxed recipient is always allowed to receive
+       * method calls. */
+      g_dbus_connection_call (sender->conn,
+                              f->proxied.unique_name,
+                              "/",
+                              DBUS_INTERFACE_PEER,
+                              "Ping",
+                              NULL,
+                              G_VARIANT_TYPE ("()"),
+                              G_DBUS_CALL_FLAGS_NONE,
+                              -1,
+                              NULL,    /* cancellable */
+                              ready_cb,
+                              &result);
+
+      while (result == NULL)
+        g_main_context_iteration (NULL, TRUE);
+
+      tuple = g_dbus_connection_call_finish (sender->conn, result, &error);
+      g_assert_no_error (error);
+      g_assert_nonnull (tuple);
+
+      g_assert_cmpint (g_atomic_int_get (&f->proxied.n_method_calls), ==, 
n_calls_before + 1);
+      g_assert_cmpint (g_atomic_int_get (&f->proxied.n_unicast_signals), ==, 
n_unicasts_before + 1);
+
+      if (t->can_receive_broadcast)
+        g_assert_cmpint (g_atomic_int_get (&f->proxied.n_broadcasts), ==, 
n_broadcasts_before + 1);
+      else
+        g_assert_cmpint (g_atomic_int_get (&f->proxied.n_broadcasts), ==, 
n_broadcasts_before);
+    }
+}
+
 static void
 teardown (Fixture *f,
           gconstpointer context G_GNUC_UNUSED)
 {
   g_autoptr(GError) error = NULL;
 
+  if (f->monitor != NULL)
+    {
+      g_subprocess_send_signal (f->monitor, SIGTERM);
+      g_subprocess_wait (f->monitor, NULL, &error);
+      g_assert_no_error (error);
+    }
+
   if (f->dbus_daemon != NULL)
     {
       g_subprocess_send_signal (f->dbus_daemon, SIGTERM);
@@ -218,16 +858,7 @@
       g_assert_no_error (error);
     }
 
-  if (f->proxied_conn != NULL)
-    {
-      g_dbus_connection_close_sync (f->proxied_conn, NULL, &error);
-
-      if (error != NULL)
-        {
-          g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CLOSED);
-          g_clear_error (&error);
-        }
-    }
+  connection_clear (&f->proxied);
 
   if (f->proxy_socket != NULL)
     {
@@ -245,7 +876,8 @@
       g_free (f->temp_directory);
     }
 
-  g_clear_object (&f->proxied_conn);
+  g_clear_pointer (&f->connections_by_name, g_hash_table_unref);
+  g_clear_object (&f->monitor);
   g_clear_object (&f->dbus_daemon);
   g_clear_object (&f->proxy);
   g_free (f->dbus_address);
@@ -260,6 +892,9 @@
   g_test_init (&argc, &argv, NULL);
 
   g_test_add ("/basics", Fixture, NULL, setup, test_basics, teardown);
+  g_test_add ("/call", Fixture, NULL, setup, test_call, teardown);
+  g_test_add ("/own", Fixture, NULL, setup, test_own, teardown);
+  g_test_add ("/receive", Fixture, NULL, setup, test_receive, teardown);
 
   return g_test_run ();
 }

Reply via email to