Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package dbus-broker for openSUSE:Factory checked in at 2021-03-25 14:52:16 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/dbus-broker (Old) and /work/SRC/openSUSE:Factory/.dbus-broker.new.2401 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "dbus-broker" Thu Mar 25 14:52:16 2021 rev:11 rq:881075 version:28 Changes: -------- --- /work/SRC/openSUSE:Factory/dbus-broker/dbus-broker.changes 2021-02-15 23:21:54.251897996 +0100 +++ /work/SRC/openSUSE:Factory/.dbus-broker.new.2401/dbus-broker.changes 2021-03-25 14:52:17.784483701 +0100 @@ -1,0 +2,10 @@ +Wed Mar 17 15:10:16 UTC 2021 - Jan Engelhardt <jeng...@inai.de> + +- Update to release 28 + * Further improvements to the service activation tracking. This + better tracks units in systemd and closes some races where a + repeated activation would incorrectly fail. + * Fix a crash where duplicate monitor matches would be + incorrectly installed in the broker. + +------------------------------------------------------------------- Old: ---- dbus-broker-27.tar.xz New: ---- dbus-broker-28.tar.xz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ dbus-broker.spec ++++++ --- /var/tmp/diff_new_pack.n7oYIb/_old 2021-03-25 14:52:18.348484275 +0100 +++ /var/tmp/diff_new_pack.n7oYIb/_new 2021-03-25 14:52:18.348484275 +0100 @@ -17,7 +17,7 @@ Name: dbus-broker -Version: 27 +Version: 28 Release: 0 Summary: XDG-conforming message bus implementation License: Apache-2.0 ++++++ dbus-broker-27.tar.xz -> dbus-broker-28.tar.xz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dbus-broker-27/.gitattributes new/dbus-broker-28/.gitattributes --- old/dbus-broker-27/.gitattributes 1970-01-01 01:00:00.000000000 +0100 +++ new/dbus-broker-28/.gitattributes 2021-03-17 13:48:38.251243800 +0100 @@ -0,0 +1 @@ +subprojects/*/subprojects export-ignore diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dbus-broker-27/NEWS.md new/dbus-broker-28/NEWS.md --- old/dbus-broker-27/NEWS.md 2021-02-15 10:25:22.568052000 +0100 +++ new/dbus-broker-28/NEWS.md 2021-03-17 15:50:54.115497000 +0100 @@ -1,5 +1,25 @@ # dbus-broker - Linux D-Bus Message Broker +## CHANGES WITH 28: + + Contributions from: David Rheinsberg + + * Further improvements to the service activation tracking. This better + tracks units in systemd and closes some races where a repeated + activation would incorrectly fail. + + * Fix a crash where duplicate monitor matches would be incorrectly + installed in the broker. + + * Clear the ambient capability set to harden against possible exploits. + + * A couple of bug-fixes in the utility libraries, and static + dependencies of the broker. + + Contributions from: David Rheinsberg + + - Du??lingen, 2021-03-17 + ## CHANGES WITH 27: * Fix several bugs with the new service-activation tracking, including diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dbus-broker-27/meson.build new/dbus-broker-28/meson.build --- old/dbus-broker-27/meson.build 2021-02-15 10:25:37.068088800 +0100 +++ new/dbus-broker-28/meson.build 2021-03-17 15:51:02.999106200 +0100 @@ -5,7 +5,7 @@ project( 'dbus-broker', 'c', - version: '27', + version: '28', license: 'Apache', default_options: [ 'c_std=c11', diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dbus-broker-27/src/broker/main.c new/dbus-broker-28/src/broker/main.c --- old/dbus-broker-27/src/broker/main.c 2021-02-04 15:01:53.763595800 +0100 +++ new/dbus-broker-28/src/broker/main.c 2021-03-17 15:47:25.715761700 +0100 @@ -6,6 +6,7 @@ #include <getopt.h> #include <limits.h> #include <stdlib.h> +#include <sys/prctl.h> #include <sys/socket.h> #include <sys/types.h> #include "broker/broker.h" @@ -233,6 +234,22 @@ return 0; } +static int setup(void) { + int r; + + /* + * We never spawn external applications from within the broker itself, + * so clear the ambient set, as it is never needed. This is meant as + * safety measure to guarantee our capabilities are not inherited by + * possible exploits. + */ + r = prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_CLEAR_ALL, 0, 0, 0); + if (r < 0) + return error_origin(-errno); + + return 0; +} + static int run(void) { _c_cleanup_(broker_freep) Broker *broker = NULL; int r; @@ -251,6 +268,10 @@ if (r) goto exit; + r = setup(); + if (r) + goto exit; + if (main_arg_audit) { r = util_audit_init_global(); if (r) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dbus-broker-27/src/bus/peer.c new/dbus-broker-28/src/bus/peer.c --- old/dbus-broker-27/src/bus/peer.c 2021-02-04 15:01:53.770262500 +0100 +++ new/dbus-broker-28/src/bus/peer.c 2021-03-17 13:48:38.277910700 +0100 @@ -656,6 +656,7 @@ int peer_become_monitor(Peer *peer, MatchOwner *owned_matches) { MatchRule *rule; + size_t i, n_user_refs; int r, poison = 0; c_assert(!peer->registered); @@ -666,12 +667,22 @@ match_owner_move(&peer->owned_matches, owned_matches); c_rbtree_for_each_entry(rule, &peer->owned_matches.rule_tree, owner_node) { - rule->owner = &peer->owned_matches; + n_user_refs = rule->n_user_refs; - r = peer_link_match(peer, rule, true); - if (r && !poison) - poison = error_trace(r); + /* + * Link once for each match instance, in case the user provided + * duplicate matches. No need to optimize this; treat it as + * individual matches and mirror `peer_add_match()`. We + * prefetch the user-refs to guarantee they are constant (in + * case `peer_link_match()` would ever want to acquire more + * user-refs, for whatever reason). + */ + for (i = 0; i < n_user_refs; ++i) { + r = peer_link_match(peer, rule, true); + if (r && !poison) + poison = error_trace(r); + } } if (poison) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dbus-broker-27/src/launch/nss-cache.c new/dbus-broker-28/src/launch/nss-cache.c --- old/dbus-broker-27/src/launch/nss-cache.c 2021-02-04 15:01:53.780262500 +0100 +++ new/dbus-broker-28/src/launch/nss-cache.c 2021-03-17 13:48:38.281244000 +0100 @@ -40,7 +40,10 @@ static int nss_cache_node_new(NSSCacheNode **nodep, const char *name, uint32_t id) { NSSCacheNode *node; - size_t n_name = name ? strlen(name) : 0; + size_t n_name; + + name = name ? : ""; + n_name = strlen(name); node = malloc(sizeof(*node) + n_name + 1); if (!node) @@ -148,7 +151,7 @@ &parent_by_id); if (!slot_by_id) { node_by_id = c_rbnode_entry(parent_by_id, NSSCacheNode, rb_by_id); - node = node_by_name; + node = node_by_id; } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dbus-broker-27/src/launch/service.c new/dbus-broker-28/src/launch/service.c --- old/dbus-broker-27/src/launch/service.c 2021-02-08 13:49:11.695880200 +0100 +++ new/dbus-broker-28/src/launch/service.c 2021-03-17 13:48:38.281244000 +0100 @@ -80,6 +80,7 @@ c_rbnode_unlink(&service->rb_by_name); c_rbnode_unlink(&service->rb); + free(service->job); free(service->user); for (size_t i = 0; i < service->argc; ++i) free(service->argv[i]); @@ -88,8 +89,8 @@ free(service->name); free(service->path); service->slot_start_unit = sd_bus_slot_unref(service->slot_start_unit); - service->slot_query_unit = sd_bus_slot_unref(service->slot_query_unit); service->slot_watch_unit = sd_bus_slot_unref(service->slot_watch_unit); + service->slot_watch_jobs = sd_bus_slot_unref(service->slot_watch_jobs); free(service); return NULL; @@ -181,9 +182,10 @@ } static void service_discard_activation(Service *service) { + service->job = c_free(service->job); service->slot_start_unit = sd_bus_slot_unref(service->slot_start_unit); - service->slot_query_unit = sd_bus_slot_unref(service->slot_query_unit); service->slot_watch_unit = sd_bus_slot_unref(service->slot_watch_unit); + service->slot_watch_jobs = sd_bus_slot_unref(service->slot_watch_jobs); } static int service_reset_activation(Service *service) { @@ -218,25 +220,46 @@ return 0; } -static int service_handle_active_state(Service *service, const char *value) { +static int service_watch_jobs_handler(sd_bus_message *message, void *userdata, sd_bus_error *errorp) { + Service *service = userdata; + const char *path = NULL, *unit = NULL, *result = NULL; + uint32_t id; int r; /* - * The possible values of "ActiveState" are: - * - * active, reloading, inactive, failed, activating, deactivating + * Whenever we have an activation job queued, we want to know when it + * is done. We get a `JobRemoved` signal from systemd, which includes + * the reason why the job is done. + * We get those signals for all jobs, since we cannot know a job-id to + * match for before we create job. This is quite unfortunate, but + * little we can do about it now. * - * We are never interested in positive results, because the broker - * already gets those by tracking the name to be acquired. Therefore, - * we only ever track negative results. This means we only ever react - * to "failed". - * We could also react to units entering "inactive", but we cannot know - * upfront whether the unit is just a oneshot unit and thus is expected - * to enter "inactive" when it finished. Hence, we simply require - * anything to explicitly fail if they want to reset the activation. + * We require this signal merely to know when systemd finished handling + * a job. For properly configured services, this should already tell us + * whether the startup was successful or failed. But for basic services + * that use no notify or dbus systemd-startup handling, we have to + * continue tracking their `ActiveState` to see whether they failed. */ - if (!strcmp(value, "failed")) { + r = sd_bus_message_read(message, "uoss", &id, &path, &unit, &result); + if (r < 0) + return error_origin(r); + + if (!service->job || strcmp(path, service->job)) + return 0; + + if (!strcmp(result, "done") || !strcmp(result, "skipped")) { + /* + * Our job completed successfully. Make sure to stop watching + * it so the `ActiveState` handling will take effect. + */ + service->job = c_free(service->job); + service->slot_watch_jobs = sd_bus_slot_unref(service->slot_watch_jobs); + } else { + /* + * Our job failed. Forward this information to the broker so it + * can fail pending activations. + */ r = service_reset_activation(service); if (r) return error_trace(r); @@ -245,44 +268,57 @@ return 0; } -static int service_query_unit_handler(sd_bus_message *message, void *userdata, sd_bus_error *errorp) { - Service *service = userdata; - const char *v; +static int service_watch_jobs(Service *service) { int r; - service->slot_query_unit = sd_bus_slot_unref(service->slot_query_unit); - - r = sd_bus_message_enter_container(message, 'v', "s"); - if (r < 0) - return error_origin(r); - - { - r = sd_bus_message_read(message, "s", &v); - if (r < 0) - return error_origin(r); - } + assert(!service->slot_watch_jobs); + assert(!service->job); - r = sd_bus_message_exit_container(message); + r = sd_bus_match_signal_async( + service->launcher->bus_regular, + &service->slot_watch_jobs, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "JobRemoved", + service_watch_jobs_handler, + NULL, + service + ); if (r < 0) return error_origin(r); - r = service_handle_active_state(service, v); - if (r) - return error_trace(r); - return 0; } static int service_watch_unit_handler(sd_bus_message *message, void *userdata, sd_bus_error *errorp) { Service *service = userdata; const char *interface = NULL, *property = NULL, *value = NULL; - bool invalidated = false; int r; /* + * If we still watch the job-signals it means systemd has not yet fully + * finished our job. In this case, any errors will be caught by the + * `JobRemoved` handler and we do not have to track the unit, yet. + * Moreover, we must not track the unit, since it might still return + * failures before our job was actually handled by systemd. + * + * Hence, simply ignore any PropertiesChanged signals until we got + * confirmation by systemd that our job finished. Bus ordering will + * guarantee that we catch unit-failures both before and after the job + * completion. + */ + if (service->slot_watch_jobs) + return 0; + + /* * The properties of the bus unit changed. We are only interested in * the "ActiveState" property. We check whether it is included in the - * payload. If not, we query it, in case it was invalidated. + * payload. If not, we ignore the signal. + * + * Note that we rely on systemd including it with value in the signal. + * We will not query it, if it was merely invalidated. This is a + * systemd API guarantee, and we rely on it. */ /* Parse: "s" */ @@ -339,54 +375,24 @@ return error_origin(r); } - /* Parse: "as" */ - { - r = sd_bus_message_enter_container(message, 'a', "s"); - if (r < 0) - return error_origin(r); - - while (!sd_bus_message_at_end(message, false)) { - r = sd_bus_message_read(message, "s", &property); - if (r < 0) - return error_origin(r); - - if (!strcmp(property, "ActiveState")) - invalidated = true; - } - - r = sd_bus_message_exit_container(message); - if (r < 0) - return error_origin(r); - } - - /* If the value neither changed or was invalidated, discard it. */ - if (!value && !invalidated) - return 0; - - service->slot_query_unit = sd_bus_slot_unref(service->slot_query_unit); - - if (value) { - /* We got a new property value, so handle it. */ - r = service_handle_active_state(service, value); + /* + * The possible values of "ActiveState" are: + * + * active, reloading, inactive, failed, activating, deactivating + * + * We are never interested in positive results, because the broker + * already gets those by tracking the name to be acquired. Therefore, + * we only ever track negative results. This means we only ever react + * to "failed". + * We could also react to units entering "inactive", but we cannot know + * upfront whether the unit is just a oneshot unit and thus is expected + * to enter "inactive" when it finished. Hence, we simply require + * anything to explicitly fail if they want to reset the activation. + */ + if (value && !strcmp(value, "failed")) { + r = service_reset_activation(service); if (r) return error_trace(r); - } else { - /* The property was invalidated, so query it. */ - r = sd_bus_call_method_async( - service->launcher->bus_regular, - &service->slot_query_unit, - "org.freedesktop.systemd1", - sd_bus_message_get_path(message), - "org.freedesktop.DBus.Properties", - "Get", - service_query_unit_handler, - service, - "ss", - "org.freedesktop.systemd1.Unit", - "ActiveState" - ); - if (r < 0) - return error_origin(r); } return 0; @@ -397,7 +403,6 @@ int r; assert(!service->slot_watch_unit); - assert(!service->slot_query_unit); r = sd_bus_path_encode( "/org/freedesktop/systemd1/unit", @@ -428,14 +433,31 @@ Service *service = userdata; Launcher *launcher = service->launcher; const sd_bus_error *error; + const char *job; int r; service->slot_start_unit = sd_bus_slot_unref(service->slot_start_unit); error = sd_bus_message_get_error(message); - if (!error) - /* unit queued successfully */ + if (!error) { + /* + * We successfully queued the job. Now remember the job path, + * so we can properly track when it finishes (via the + * JobRemoved signal). + */ + + assert(!service->job); + + r = sd_bus_message_read(message, "o", &job); + if (r < 0) + return error_origin(r); + + service->job = strdup(job); + if (!service->job) + return error_origin(-ENOMEM); + return 1; + } /* * We always forward activation failure to the broker, which then @@ -522,6 +544,10 @@ _c_cleanup_(sd_bus_message_unrefp) sd_bus_message *method_call = NULL; int r; + r = service_watch_jobs(service); + if (r) + return error_trace(r); + r = service_watch_unit(service, service->unit); if (r) return error_trace(r); @@ -552,6 +578,10 @@ const char *unique_name; int r; + r = service_watch_jobs(service); + if (r) + return error_trace(r); + r = sd_bus_get_unique_name(launcher->bus_regular, &unique_name); if (r < 0) return error_origin(r); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dbus-broker-27/src/launch/service.h new/dbus-broker-28/src/launch/service.h --- old/dbus-broker-27/src/launch/service.h 2021-02-08 13:49:11.695880200 +0100 +++ new/dbus-broker-28/src/launch/service.h 2021-03-17 13:48:38.281244000 +0100 @@ -17,8 +17,8 @@ bool not_found; bool running; bool reload_tag; + sd_bus_slot *slot_watch_jobs; sd_bus_slot *slot_watch_unit; - sd_bus_slot *slot_query_unit; sd_bus_slot *slot_start_unit; CRBNode rb; CRBNode rb_by_name; @@ -33,6 +33,7 @@ uint64_t n_missing_unit; uint64_t n_masked_unit; uint64_t last_serial; + char *job; char id[]; }; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dbus-broker-27/src/util/sockopt.c new/dbus-broker-28/src/util/sockopt.c --- old/dbus-broker-27/src/util/sockopt.c 2021-02-04 15:01:53.786929100 +0100 +++ new/dbus-broker-28/src/util/sockopt.c 2021-03-17 13:48:38.281244000 +0100 @@ -145,8 +145,10 @@ if (!warned) { warned = true; log_append_here(log, LOG_ERR, 0, DBUS_BROKER_CATALOG_NO_SOPEERGROUP); - log_commitf(log, "Falling back to racy auxiliary groups" - "resolution using nss.\n"); + r = log_commitf(log, "Falling back to racy auxiliary groups" + "resolution using nss.\n"); + if (r) + return error_fold(r); } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dbus-broker-27/subprojects/c-list/src/test-basic.c new/dbus-broker-28/subprojects/c-list/src/test-basic.c --- old/dbus-broker-27/subprojects/c-list/src/test-basic.c 2021-02-04 16:14:18.166463100 +0100 +++ new/dbus-broker-28/subprojects/c-list/src/test-basic.c 2021-03-17 12:22:49.962468100 +0100 @@ -176,10 +176,28 @@ assert(!c_list_is_linked(&e2)); } +static void test_macros(void) { + /* Verify `c_list_entry()` evaluates arguments only once. */ + { + struct TestList { + int a; + CList link; + int b; + } list = { .link = C_LIST_INIT(list.link) }; + CList *p[2] = { &list.link, NULL }; + unsigned int i = 0; + + assert(i == 0); + assert(c_list_entry(p[i++], struct TestList, link) == &list); + assert(i == 1); + } +} + int main(int argc, char **argv) { test_iterators(); test_swap(); test_splice(); test_flush(); + test_macros(); return 0; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dbus-broker-27/subprojects/c-shquote/src/test-api.c new/dbus-broker-28/subprojects/c-shquote/src/test-api.c --- old/dbus-broker-27/subprojects/c-shquote/src/test-api.c 2021-02-04 16:14:23.286444200 +0100 +++ new/dbus-broker-28/subprojects/c-shquote/src/test-api.c 2021-03-17 12:22:51.162492300 +0100 @@ -41,7 +41,7 @@ free(argv); } -int main(int argc, char **argv) { +int main(void) { test_api(); return 0; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dbus-broker-27/subprojects/c-shquote/src/test-basic.c new/dbus-broker-28/subprojects/c-shquote/src/test-basic.c --- old/dbus-broker-27/subprojects/c-shquote/src/test-basic.c 2021-02-04 16:14:23.286444200 +0100 +++ new/dbus-broker-28/subprojects/c-shquote/src/test-basic.c 2021-03-17 12:22:51.162492300 +0100 @@ -137,7 +137,7 @@ free(argv); } -int main(int argc, char *argv[]) { +int main(void) { test_quote(); test_unquote(); test_reverse(); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dbus-broker-27/subprojects/c-shquote/src/test-private.c new/dbus-broker-28/subprojects/c-shquote/src/test-private.c --- old/dbus-broker-27/subprojects/c-shquote/src/test-private.c 2021-02-04 16:14:23.286444200 +0100 +++ new/dbus-broker-28/subprojects/c-shquote/src/test-private.c 2021-03-17 12:22:51.162492300 +0100 @@ -380,7 +380,7 @@ c_assert(!memcmp(buf, "fo\"obar", strlen(string) - 3)); } -int main(int argc, char *argv[]) { +int main(void) { test_append_str(); test_append_char(); test_skip_str(); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dbus-broker-27/subprojects/c-shquote/src/test-reference.c new/dbus-broker-28/subprojects/c-shquote/src/test-reference.c --- old/dbus-broker-27/subprojects/c-shquote/src/test-reference.c 2021-02-04 16:14:23.286444200 +0100 +++ new/dbus-broker-28/subprojects/c-shquote/src/test-reference.c 2021-03-17 12:22:51.162492300 +0100 @@ -114,7 +114,7 @@ test_parse_one("/usr/libexec/at-spi-bus-launcher"); } -int main(int argc, char *argv[]) { +int main(void) { test_quote(); test_unquote(); test_parse(); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dbus-broker-27/subprojects/c-stdaux/src/test-api.c new/dbus-broker-28/subprojects/c-stdaux/src/test-api.c --- old/dbus-broker-27/subprojects/c-stdaux/src/test-api.c 2021-02-04 16:14:11.939819800 +0100 +++ new/dbus-broker-28/subprojects/c-stdaux/src/test-api.c 2021-03-17 12:22:51.732504000 +0100 @@ -12,14 +12,14 @@ static _c_const_ int const_fn(void) { return 0; } static _c_deprecated_ _c_unused_ int deprecated_fn(void) { return 0; } _c_hidden_ int c_internal_hidden_fn(void) { return 0; } -static _c_printf_(1, 2) int printf_fn(const char *f, ...) { return 0; } +static _c_printf_(1, 2) int printf_fn(const _c_unused_ char *f, ...) { return 0; } _c_public_ int c_internal_public_fn(void) { return 0; } static _c_pure_ int pure_fn(void) { return 0; } -static _c_sentinel_ int sentinel_fn(const char *f, ...) { return 0; } +static _c_sentinel_ int sentinel_fn(const _c_unused_ char *f, ...) { return 0; } static _c_unused_ int unused_fn(void) { return 0; } -static void cleanup_fn(int p) {} -static void direct_cleanup_fn(int p) {} +static void cleanup_fn(_c_unused_ int p) {} +static void direct_cleanup_fn(_c_unused_ int p) {} C_DEFINE_CLEANUP(int, cleanup_fn); C_DEFINE_DIRECT_CLEANUP(int, direct_cleanup_fn); @@ -202,7 +202,7 @@ c_assert(!!fns[i]); } -int main(int argc, char **argv) { +int main(void) { test_api_macros(); test_api_functions(); return 0; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dbus-broker-27/subprojects/c-stdaux/src/test-basic.c new/dbus-broker-28/subprojects/c-stdaux/src/test-basic.c --- old/dbus-broker-27/subprojects/c-stdaux/src/test-basic.c 2021-02-04 16:14:11.939819800 +0100 +++ new/dbus-broker-28/subprojects/c-stdaux/src/test-basic.c 2021-03-17 12:22:51.732504000 +0100 @@ -425,7 +425,7 @@ } } -int main(int argc, char **argv) { +int main(int argc, _c_unused_ char **argv) { test_misc(argc); test_destructors(); return 0; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dbus-broker-27/test/dbus/test-driver.c new/dbus-broker-28/test/dbus/test-driver.c --- old/dbus-broker-27/test/dbus/test-driver.c 2021-02-04 15:01:53.790262500 +0100 +++ new/dbus-broker-28/test/dbus/test-driver.c 2021-03-17 13:48:38.284577400 +0100 @@ -2195,6 +2195,20 @@ c_assert(r == -ECONNRESET); } + /* become monitor with a match duplicate */ + { + _c_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + + util_broker_connect(broker, &bus); + + r = sd_bus_call_method(bus, "org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus.Monitoring", + "BecomeMonitor", NULL, NULL, + "asu", + 2, "sender=com.example.test", "sender=com.example.test", + 0); + c_assert(r >= 0); + } + util_broker_terminate(broker); }