diff --git a/libink/match.c b/libink/match.c index add721b4..eaaa87f5 100644 --- a/libink/match.c +++ b/libink/match.c @@ -7,6 +7,14 @@ * keys cause the whole rule to be rejected so a peer learns its * filter didn't take, rather than silently receiving everything. * + * The exceptions are sender, destination, and eavesdrop, which are + * accepted and then ignored. Clients send them as a matter of + * course, and refusing the rule leaves such a peer with no signals at + * all, which serves it far worse than a filter wider than it asked + * for. Widening is safe here: Finit is the only sender on this bus, + * and everything it emits through the match table is state any peer + * that reached the bus may already read. + * * Copyright (c) 2026 Joachim Wiberg * SPDX-License-Identifier: MIT */ @@ -103,7 +111,18 @@ struct link_match *__match_parse(const char *rule) else if (!strcmp(key, "interface")) slot = &m->interface; else if (!strcmp(key, "member")) slot = &m->member; else if (!strcmp(key, "path")) slot = &m->path; - else { + else if (!strcmp(key, "sender") || + !strcmp(key, "destination") || + !strcmp(key, "eavesdrop")) { + /* Understood well enough to accept, see above. */ + free(key); + free(value); + continue; + } else { + /* XXX: argN and argNpath land here, so a rule + * using them takes nothing rather than too + * much. They narrow on body contents, which + * means parsing the body to honour them. */ free(key); free(value); goto bad; diff --git a/test/dbus-bus.sh b/test/dbus-bus.sh index 7bd53704..57a21da8 100755 --- a/test/dbus-bus.sh +++ b/test/dbus-bus.sh @@ -54,6 +54,26 @@ case "$(cat /tmp/dbus-match.out)" in *) fail "Unexpected reply: $(cat /tmp/dbus-match.out)" ;; esac +# A client that sends these must still get its signals: refusing the +# rule would leave it with none at all. The sender here is deliberately +# wrong, so a delivered signal proves the key was ignored and not +# quietly honoured. +say "AddMatch accepts, and ignores, sender/destination/eavesdrop" +rm -f /tmp/dbus-ignored.out +( texec "$CLIENT" monitor-signal "$BUS" \ + "type='signal',sender='org.freedesktop.DBus',destination=':1.99',eavesdrop='false',interface='org.finit.Cond1',member='ConditionChanged'" \ + 5000 > /tmp/dbus-ignored.out 2>&1 ) & +ign_pid=$! +sleep 0.5 +texec "$CLIENT" call-s "$BUS" /org/finit/cond \ + org.finit.Cond1 Set "dbus-ignored-keys" >/dev/null \ + || fail "Cond1.Set returned non-zero" +set +e +wait "$ign_pid" +ign_rc=$? +set -e +assert "Signal still delivered through the wider rule (rc=$ign_rc)" "$ign_rc" -eq 0 + say "Unknown method on a Finit interface gets an org.freedesktop.DBus.Error.* reply" set +e texec "$CLIENT" unknown "$BUS"