Package: release.debian.org Severity: normal Control: affects -1 + src:dbus-broker User: release.debian.org@packages.debian.org Usertags: unblock Dear RT, [ Reason ] There is a new bugfix release of dbus-broker, that fixes several issues. It will likely be the last version before some major overhauls, so I'd like to have it in trixie. I am not really sure why dbus-broker is marked as a 'key package', as it's a completely optional, non-default, alternative implementation. [ Impact ] Small, it's a non-default, alternative implementation. No packaging changes besides dropping a backported patch that is included upstream. [ Tests ] Works and boots, and there is large code coverage thanks to the systemd debci job. [ Risks ] Low, as it's a non-default, alternative implementation, and there's lots of test coverage. [ Checklist ] [x] all changes are documented in the d/changelog [x] I reviewed all changes and I approve them [x] attach debdiff against the package in testing unblock dbus-broker/37-1 Thanks!
diff -Nru dbus-broker-36/AUTHORS dbus-broker-37/AUTHORS --- dbus-broker-36/AUTHORS 2024-04-12 15:07:35.000000000 +0100 +++ dbus-broker-37/AUTHORS 2025-06-16 13:26:27.000000000 +0100 @@ -18,11 +18,14 @@ AUTHORS: (ordered alphabetically) Allison Karlitskaya <allison.karlitskaya@redhat.com> + Attila Lakatos <alakatos@redhat.com> + Barnabás Pőcze <pobrn@protonmail.com> Camron Carter <reefoe@proton.me> Chris Paulson-Ellis <chris.paulson-ellis@motorolasolutions.com> Chris PeBenito <chpebeni@linux.microsoft.com> Daniel Rusek <mail@asciiwolf.com> Daniele Nicolodi <daniele@grinta.net> + darkblaze69 David Rheinsberg <david.rheinsberg@gmail.com> Evgeny Vereshchagin <evvers@ya.ru> Frantisek Sumsal <frantisek@sumsal.cz> @@ -30,8 +33,9 @@ Hugo Osvaldo Barrera <hugo@barrera.io> Jacob Alzén <jacob.alzen@gmail.com> Jake Dane - Lily Danzig <ldenardo@dealerinspire.com> + Jeffrey Bosboom <jbosboom@jeffreybosboom.com> Khem Raj <raj.khem@gmail.com> + Lily Danzig <ldenardo@dealerinspire.com> Laurent Bigonville <bigon@bigon.be> Luca Boccassi <luca.boccassi@microsoft.com> Marc-Antoine Perennou <Marc-Antoine@Perennou.com> @@ -40,9 +44,12 @@ Michal Schmidt <mschmidt@redhat.com> Mike Gilbert <floppym@gentoo.org> msizanoen1 <msizanoen@qtmlabs.xyz> + Ryan Wilson <ryantimwilson@gmail.com> + seaeunlee <seaeunlee@microsoft.com> Stefan Agner <stefan@agner.ch> Thomas Mühlbacher <tmuehlbacher@posteo.net> Tim Gates <tim.gates@iress.com> Tom Gundersen <teg@jklm.no> + Tomas Korbar <tkorbar@redhat.com> Yanko Kaneti <yaneti@declera.com> Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> diff -Nru dbus-broker-36/debian/changelog dbus-broker-37/debian/changelog --- dbus-broker-36/debian/changelog 2025-04-25 19:30:26.000000000 +0100 +++ dbus-broker-37/debian/changelog 2025-06-16 14:58:24.000000000 +0100 @@ -1,3 +1,12 @@ +dbus-broker (37-1) unstable; urgency=medium + + * Update upstream source from tag 'upstream/37' + For a full list of changes, see: + https://github.com/bus1/dbus-broker/releases/tag/v37 + * Drop util-sockopt-also-check-for-ESRCH.patch + + -- Luca Boccassi <bluca@debian.org> Mon, 16 Jun 2025 14:58:24 +0100 + dbus-broker (36-2) unstable; urgency=medium * Drop libaudit/libselinux compat patch, not needed since bookworm diff -Nru dbus-broker-36/debian/patches/series dbus-broker-37/debian/patches/series --- dbus-broker-36/debian/patches/series 2025-04-25 19:23:03.000000000 +0100 +++ dbus-broker-37/debian/patches/series 2025-06-16 14:58:00.000000000 +0100 @@ -1,2 +1 @@ -util-sockopt-also-check-for-ESRCH.patch github_apparmor_support.patch diff -Nru dbus-broker-36/debian/patches/util-sockopt-also-check-for-ESRCH.patch dbus-broker-37/debian/patches/util-sockopt-also-check-for-ESRCH.patch --- dbus-broker-36/debian/patches/util-sockopt-also-check-for-ESRCH.patch 2025-04-25 19:24:32.000000000 +0100 +++ dbus-broker-37/debian/patches/util-sockopt-also-check-for-ESRCH.patch 1970-01-01 01:00:00.000000000 +0100 @@ -1,15 +0,0 @@ -Author: Luca Boccassi <bluca@debian.org> -Forwarded: https://github.com/bus1/dbus-broker/pull/389 -Origin: commit:4b1d9da51dc2703b7596243cb555a689bb27b4c1 -Description: util/sockopt: also check for ESRCH when the process has exited ---- a/src/util/sockopt.c -+++ b/src/util/sockopt.c -@@ -238,7 +238,7 @@ - return SOCKOPT_E_UNSUPPORTED; - if (errno == ENODATA) - return SOCKOPT_E_UNAVAILABLE; -- if (errno == EINVAL) -+ if (errno == EINVAL || errno == ESRCH) - return SOCKOPT_E_REAPED; - - return error_origin(-errno); diff -Nru dbus-broker-36/.github/workflows/codeql.yml dbus-broker-37/.github/workflows/codeql.yml --- dbus-broker-36/.github/workflows/codeql.yml 2024-04-12 15:07:35.000000000 +0100 +++ dbus-broker-37/.github/workflows/codeql.yml 2025-06-16 13:26:27.000000000 +0100 @@ -32,7 +32,7 @@ sudo apt -y install dbus expat libaudit-dev libselinux-dev libsystemd-dev python3-pip sudo pip3 install meson ninja - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Initialize CodeQL uses: github/codeql-action/init@v2 with: diff -Nru dbus-broker-36/.github/workflows/fuzz.yml dbus-broker-37/.github/workflows/fuzz.yml --- dbus-broker-36/.github/workflows/fuzz.yml 2024-04-12 15:07:35.000000000 +0100 +++ dbus-broker-37/.github/workflows/fuzz.yml 2025-06-16 13:26:27.000000000 +0100 @@ -46,7 +46,7 @@ sanitizer: ${{ matrix.sanitizer }} - name: Upload Crash if: failure() && steps.build.outcome == 'success' - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: ${{ matrix.sanitizer }}-${{ matrix.architecture }}-artifacts path: ./out/artifacts diff -Nru dbus-broker-36/.github/workflows/meson-tests.yml dbus-broker-37/.github/workflows/meson-tests.yml --- dbus-broker-36/.github/workflows/meson-tests.yml 2024-04-12 15:07:35.000000000 +0100 +++ dbus-broker-37/.github/workflows/meson-tests.yml 2025-06-16 13:26:27.000000000 +0100 @@ -36,29 +36,29 @@ # since it clashes with sd-bus used by the launcher. This test also # builds documentation and related resources. - id: "release" - name: "RELEASE @ CLANG-X86_64 @ +TEST -VALGRIND @ -APPARMOR +AUDIT +DOCS +LAUNCHER +SELINUX" + name: "RELEASE @ CLANG-X86_64 @ +TEST -VALGRIND @ -APPARMOR +AUDIT +DOCS +LAUNCHER -SELINUX" # Explicitly set all options here to document them. buildtype: "debugoptimized" cc: "clang" cflags: "-Werror" - image: "ghcr.io/bus1/dbrk-ci-fedora:latest" - m32: "no" - setupargs: "-Daudit=true -Ddocs=true -Dlauncher=true -Dselinux=true" + image: "ghcr.io/readaheadeu/rae-ci-archlinux:latest" + rustflags: "" + setupargs: "-Daudit=true -Ddocs=true -Dlauncher=true" test: "yes" valgrind: "no" warnlevel: "2" - # A release build with `-m32` to test on 32-bit. + # A release build with `--cross-file lib32` to test on 32-bit. - id: "32bit" - name: "RELEASE @ CLANG-I686 @ +TEST -VALGRIND @ -APPARMOR +AUDIT -DOCS +LAUNCHER -SELINUX" + name: "RELEASE @ CLANG-I686 @ +TEST -VALGRIND @ -APPARMOR -AUDIT -DOCS +LAUNCHER -SELINUX" buildtype: "debugoptimized" cc: "clang" - cflags: "-m32 -Werror" - image: "ghcr.io/bus1/dbrk-ci-fedora:latest" - m32: "yes" - setupargs: "-Daudit=true -Dlauncher=true" + cflags: "-Werror" + image: "ghcr.io/readaheadeu/rae-ci-archlinux:latest" + rustflags: "--target i686-unknown-linux-gnu" + setupargs: "-Dlauncher=true --cross-file lib32" test: "yes" warnlevel: "2" @@ -71,7 +71,7 @@ buildtype: "debugoptimized" cc: "clang" cflags: "-Werror" - image: "ghcr.io/bus1/dbrk-ci-fedora:latest" + image: "ghcr.io/readaheadeu/rae-ci-archlinux:latest" setupargs: "-Daudit=true -Dlauncher=false" test: "yes" valgrind: "yes" @@ -80,26 +80,26 @@ # A reduced build with `-O0` to verify we do not rely on dead-code # elimination. - id: "O0-PLAIN" - name: "PLAIN @ GCC-X86_64 @ +TEST -VALGRIND @ -APPARMOR +AUDIT -DOCS +LAUNCHER +SELINUX" + name: "PLAIN @ GCC-X86_64 @ +TEST -VALGRIND @ -APPARMOR +AUDIT -DOCS +LAUNCHER -SELINUX" buildtype: "plain" cc: "gcc" cflags: "-O0 -Werror" - image: "ghcr.io/bus1/dbrk-ci-fedora:latest" - setupargs: "-Daudit=true -Dlauncher=true -Dselinux=true" + image: "ghcr.io/readaheadeu/rae-ci-archlinux:latest" + setupargs: "-Daudit=true -Dlauncher=true" test: "yes" warnlevel: "2" # An aggressive -O3 -DNDEBUG build that verfies that we properly # follow strict aliasing rules and do not rely on debug builds. - id: "O3-NDEBUG" - name: "OPTIMIZED @ GCC-X86_64 @ +TEST -VALGRIND @ -APPARMOR +AUDIT -DOCS +LAUNCHER +SELINUX" + name: "OPTIMIZED @ GCC-X86_64 @ +TEST -VALGRIND @ -APPARMOR +AUDIT -DOCS +LAUNCHER -SELINUX" buildtype: "release" cc: "gcc" cflags: "-O3 -Werror -DNDEBUG" - image: "ghcr.io/bus1/dbrk-ci-fedora:latest" - setupargs: "-Daudit=true -Dlauncher=true -Dselinux=true" + image: "ghcr.io/readaheadeu/rae-ci-archlinux:latest" + setupargs: "-Daudit=true -Dlauncher=true" test: "yes" warnlevel: "2" @@ -111,11 +111,12 @@ buildtype: "debugoptimized" cc: "clang" cflags: "-Werror" - image: "ghcr.io/bus1/dbrk-ci-fedora:latest" + image: "ghcr.io/readaheadeu/rae-ci-archlinux:latest" setupargs: "-Dlauncher=false" test: "yes" warnlevel: "2" + # Run on Ubuntu to test the AppArmor integration. - id: "ubuntu" name: "RELEASE @ CLANG-X86_64 @ +TEST -VALGRIND @ +APPARMOR +AUDIT -DOCS +LAUNCHER -SELINUX" @@ -129,6 +130,7 @@ container: image: ${{ matrix.image }} + options: --user root env: CC: ${{ matrix.cc }} @@ -138,14 +140,7 @@ steps: - name: "Fetch Sources" - uses: actions/checkout@v3 - - - name: "Setup 32-bit Environment" - if: matrix.m32 == 'yes' - run: | - echo \ - "PKG_CONFIG_LIBDIR=/usr/lib/pkgconfig:/usr/share/pkgconfig" \ - >> $GITHUB_ENV + uses: actions/checkout@v4 - name: "Setup Meson" run: | diff -Nru dbus-broker-36/.github/workflows/publish.yml dbus-broker-37/.github/workflows/publish.yml --- dbus-broker-36/.github/workflows/publish.yml 1970-01-01 01:00:00.000000000 +0100 +++ dbus-broker-37/.github/workflows/publish.yml 2025-06-16 13:26:27.000000000 +0100 @@ -0,0 +1,53 @@ +# +# Publish Releases +# +# This workflow can be manually triggered and will then publish the +# specified release to the configured release channels. +# + +name: "Publish Releases" + +on: + workflow_dispatch: + inputs: + tag: + description: "Git-Tag to Publish" + default: "" + required: true + +concurrency: + cancel-in-progress: false + group: "publish" + +defaults: + run: + shell: "bash" + +jobs: + publish: + name: "Publish GitHub" + + env: + CTX_GITHUB_EVENT_INPUTS_TAG: ${{ github.event.inputs.tag }} + permissions: + contents: write + runs-on: "ubuntu-latest" + + steps: + - name: "Verify Input" + run: | + if [[ -z "${CTX_GITHUB_EVENT_INPUTS_TAG}" ]] ; then + echo "error: empty git-tag specified as input" + exit 1 + fi + + - name: "Clone Repository" + uses: actions/checkout@v4 + with: + ref: ${{ github.event.inputs.tag }} + + - name: "Publish GitHub" + uses: readaheadeu/rae-actions/publish-github@v1 + with: + ghtoken: ${{ secrets.GITHUB_TOKEN }} + tag: ${{ github.event.inputs.tag }} diff -Nru dbus-broker-36/Makefile dbus-broker-37/Makefile --- dbus-broker-36/Makefile 2024-04-12 15:07:35.000000000 +0100 +++ dbus-broker-37/Makefile 2025-06-16 13:26:27.000000000 +0100 @@ -69,7 +69,6 @@ --buildtype "debugoptimized" \ --reconfigure \ --warnlevel "2" \ - -D "audit=true" \ -D "docs=true" \ -D "launcher=true" \ -- \ @@ -89,6 +88,13 @@ meson-setup: | $(BUILDDIR)/ $(MESON_SETUP) +.PHONY: meson-setup +meson-setup-32: | $(BUILDDIR)/ + CFLAGS="-m32" \ + PKG_CONFIG_LIBDIR="/usr/lib32/pkgconfig:/usr/share/pkgconfig" \ + RUSTFLAGS="--target i686-unknown-linux" \ + $(MESON_SETUP) + .PHONY: meson-test meson-test: $(BUILDDIR)/meson/ meson \ diff -Nru dbus-broker-36/meson.build dbus-broker-37/meson.build --- dbus-broker-36/meson.build 2024-04-12 15:07:35.000000000 +0100 +++ dbus-broker-37/meson.build 2025-06-16 13:26:27.000000000 +0100 @@ -4,15 +4,16 @@ project( 'dbus-broker', - 'c', default_options: [ 'c_std=c11', ], - license: 'Apache', + license: 'Apache-2.0', meson_version: '>=0.60.0', - version: '36', + version: '37', ) +add_languages('c', native: false) + cc = meson.get_compiler('c') conf = configuration_data() mod_pkgconfig = import('pkgconfig') diff -Nru dbus-broker-36/NEWS.md dbus-broker-37/NEWS.md --- dbus-broker-36/NEWS.md 2024-04-12 15:07:35.000000000 +0100 +++ dbus-broker-37/NEWS.md 2025-06-16 13:26:27.000000000 +0100 @@ -1,5 +1,30 @@ # dbus-broker - Linux D-Bus Message Broker +## CHANGES WITH 37: + + * Add `/etc` and `/run` to the search-paths for system services. This + change is aligned with recent changes to the reference + implementation. + + * Support systemd's `notify-reload` to trigger a reload operation. + This replaces the old `busctl call ...ReloadConfig` operation. + + * Extend `org.freedesktop.DBus.Debug.Stats.GetStats` with all the + fields defined by the specification. + + * Fix a bug in match-rule processing which caused argument processing + to fail for any but the first message argument. + + * Fix a memory leak in configuration processing when parsing invalid + user or group IDs. + + Contributions from: Attila Lakatos, Barnabás Pőcze, darkblaze69, David + Rheinsberg, Evgeny Vereshchagin, Frantisek Sumsal, + Jeffrey Bosboom, Luca Boccassi, Ryan Wilson, + seaeunlee, Tomas Korbar + + - Dußlingen, 2025-06-16 + ## CHANGES WITH 36: * Fix possible file-descriptor use-after-close, which can lead to diff -Nru dbus-broker-36/packit.yml dbus-broker-37/packit.yml --- dbus-broker-36/packit.yml 2024-04-12 15:07:35.000000000 +0100 +++ dbus-broker-37/packit.yml 2025-06-16 13:26:27.000000000 +0100 @@ -1,3 +1,4 @@ +create_sync_note: false downstream_package_name: "dbus-broker" upstream_package_name: "dbus-broker" upstream_tag_template: "v{version}" diff -Nru dbus-broker-36/src/broker/broker.c dbus-broker-37/src/broker/broker.c --- dbus-broker-36/src/broker/broker.c 2024-04-12 15:07:35.000000000 +0100 +++ dbus-broker-37/src/broker/broker.c 2025-06-16 13:26:27.000000000 +0100 @@ -40,19 +40,12 @@ return DISPATCH_E_EXIT; } -int broker_new(Broker **brokerp, const char *machine_id, int log_fd, int controller_fd, uint64_t max_bytes, uint64_t max_fds, uint64_t max_matches, uint64_t max_objects) { +int broker_new(Broker **brokerp, Log *log, const char *machine_id, int controller_fd, uint64_t max_bytes, uint64_t max_fds, uint64_t max_matches, uint64_t max_objects) { _c_cleanup_(broker_freep) Broker *broker = NULL; struct ucred ucred; socklen_t z; sigset_t sigmask; - int r, log_type; - - if (log_fd >= 0) { - z = sizeof(log_type); - r = getsockopt(log_fd, SOL_SOCKET, SO_TYPE, &log_type, &z); - if (r < 0) - return error_origin(-errno); - } + int r; z = sizeof(ucred); r = getsockopt(controller_fd, SOL_SOCKET, SO_PEERCRED, &ucred, &z); @@ -63,26 +56,14 @@ if (!broker) return error_origin(-ENOMEM); - broker->log = (Log)LOG_NULL; + broker->log = log; broker->bus = (Bus)BUS_NULL(broker->bus); broker->dispatcher = (DispatchContext)DISPATCH_CONTEXT_NULL(broker->dispatcher); broker->signals_fd = -1; broker->signals_file = (DispatchFile)DISPATCH_FILE_NULL(broker->signals_file); broker->controller = (Controller)CONTROLLER_NULL(broker->controller); - if (log_fd < 0) - log_init(&broker->log); - else if (log_type == SOCK_STREAM) - log_init_stderr(&broker->log, log_fd); - else if (log_type == SOCK_DGRAM) - log_init_journal(&broker->log, log_fd); - else - return error_origin(-ENOTRECOVERABLE); - - /* XXX: make this run-time optional */ - log_set_lossy(&broker->log, true); - - r = bus_init(&broker->bus, &broker->log, machine_id, max_bytes, max_fds, max_matches, max_objects); + r = bus_init(&broker->bus, broker->log, machine_id, max_bytes, max_fds, max_matches, max_objects); if (r) return error_fold(r); @@ -104,7 +85,7 @@ return error_fold(r); r = sockopt_get_peergroups(controller_fd, - &broker->log, + broker->log, ucred.uid, ucred.gid, &broker->bus.gids, @@ -168,7 +149,6 @@ c_close(broker->signals_fd); dispatch_context_deinit(&broker->dispatcher); bus_deinit(&broker->bus); - log_deinit(&broker->log); free(broker); return NULL; diff -Nru dbus-broker-36/src/broker/broker.h dbus-broker-37/src/broker/broker.h --- dbus-broker-36/src/broker/broker.h 2024-04-12 15:07:35.000000000 +0100 +++ dbus-broker-37/src/broker/broker.h 2025-06-16 13:26:27.000000000 +0100 @@ -21,7 +21,7 @@ typedef struct User User; struct Broker { - Log log; + Log *log; Bus bus; DispatchContext dispatcher; @@ -33,7 +33,7 @@ /* broker */ -int broker_new(Broker **brokerp, const char *machine_id, int log_fd, int controller_fd, uint64_t max_bytes, uint64_t max_fds, uint64_t max_matches, uint64_t max_objects); +int broker_new(Broker **brokerp, Log *log, const char *machine_id, int controller_fd, uint64_t max_bytes, uint64_t max_fds, uint64_t max_matches, uint64_t max_objects); Broker *broker_free(Broker *broker); int broker_run(Broker *broker); diff -Nru dbus-broker-36/src/broker/main.c dbus-broker-37/src/broker/main.c --- dbus-broker-36/src/broker/main.c 2024-04-12 15:07:35.000000000 +0100 +++ dbus-broker-37/src/broker/main.c 2025-06-16 13:26:27.000000000 +0100 @@ -13,6 +13,7 @@ #include "broker/main.h" #include "util/audit.h" #include "util/error.h" +#include "util/log.h" #include "util/selinux.h" #include "util/string.h" @@ -234,8 +235,9 @@ return 0; } -static int setup(void) { - int r; +static int setup(Log *logp) { + socklen_t z; + int r, log_type; /* * We never spawn external applications from within the broker itself, @@ -247,14 +249,33 @@ if (r < 0) return error_origin(-errno); + if (main_arg_log >= 0) { + z = sizeof(log_type); + r = getsockopt(main_arg_log, SOL_SOCKET, SO_TYPE, &log_type, &z); + if (r < 0) + return error_origin(-errno); + } + + if (main_arg_log < 0) + log_init(logp); + else if (log_type == SOCK_STREAM) + log_init_stderr(logp, main_arg_log); + else if (log_type == SOCK_DGRAM) + log_init_journal(logp, main_arg_log); + else + return error_origin(-ENOTRECOVERABLE); + + /* XXX: make this run-time optional */ + log_set_lossy(logp, true); + return 0; } -static int run(void) { +static int run(Log *log) { _c_cleanup_(broker_freep) Broker *broker = NULL; int r; - r = broker_new(&broker, main_arg_machine_id, main_arg_log, main_arg_controller, main_arg_max_bytes, main_arg_max_fds, main_arg_max_matches, main_arg_max_objects); + r = broker_new(&broker, log, main_arg_machine_id, main_arg_controller, main_arg_max_bytes, main_arg_max_fds, main_arg_max_matches, main_arg_max_objects); if (!r) r = broker_run(broker); @@ -262,13 +283,14 @@ } int main(int argc, char **argv) { + Log log = LOG_NULL; int r; r = parse_argv(argc, argv); if (r) goto exit; - r = setup(); + r = setup(&log); if (r) goto exit; @@ -280,17 +302,18 @@ } } - r = bus_selinux_init_global(); + r = bus_selinux_init_global(&log); if (r) { r = error_fold(r); goto exit; } - r = run(); + r = run(&log); exit: bus_selinux_deinit_global(); util_audit_deinit_global(); + log_deinit(&log); r = error_trace(r); return (r == 0 || r == MAIN_EXIT) ? 0 : 1; diff -Nru dbus-broker-36/src/bus/bus.h dbus-broker-37/src/bus/bus.h --- dbus-broker-36/src/bus/bus.h 2024-04-12 15:07:35.000000000 +0100 +++ dbus-broker-37/src/bus/bus.h 2025-06-16 13:26:27.000000000 +0100 @@ -46,6 +46,7 @@ UserRegistry users; NameRegistry names; + MatchCounters match_counters; MatchRegistry wildcard_matches; MatchRegistry sender_matches; PeerRegistry peers; @@ -53,6 +54,7 @@ uint64_t n_monitors; uint64_t listener_ids; uint64_t activation_ids; + uint64_t stats_ids; Metrics metrics; }; @@ -61,6 +63,7 @@ .pid_fd = -1, \ .users = USER_REGISTRY_NULL, \ .names = NAME_REGISTRY_INIT, \ + .match_counters = MATCH_COUNTERS_INIT, \ .wildcard_matches = MATCH_REGISTRY_INIT((_x).wildcard_matches), \ .sender_matches = MATCH_REGISTRY_INIT((_x).sender_matches), \ .peers = PEER_REGISTRY_INIT, \ diff -Nru dbus-broker-36/src/bus/driver.c dbus-broker-37/src/bus/driver.c --- dbus-broker-36/src/bus/driver.c 2024-04-12 15:07:35.000000000 +0100 +++ dbus-broker-37/src/bus/driver.c 2025-06-16 13:26:27.000000000 +0100 @@ -21,6 +21,7 @@ #include "dbus/socket.h" #include "util/apparmor.h" #include "util/error.h" +#include "util/misc.h" #include "util/selinux.h" #include "util/string.h" @@ -2274,6 +2275,7 @@ } static int driver_method_get_stats(Peer *peer, const char *path, CDVar *in_v, uint32_t serial, CDVar *out_v) { + Bus *bus = peer->bus; int r; c_dvar_read(in_v, "()"); @@ -2282,16 +2284,40 @@ if (r) return error_trace(r); - /* - * Append all supported statistics. So far, none of the dbus-daemon - * statistics are appended, since they are very specific to how the bus - * is implemented. We do, however, add our own (namespaced) statistics. - */ c_dvar_write(out_v, "([{s", "org.bus1.DBus.Debug.Stats.PeerAccounting"); driver_append_peer_accounting(out_v, peer->bus); c_dvar_write(out_v, "}{s", "org.bus1.DBus.Debug.Stats.UserAccounting"); driver_append_user_accounting(out_v, peer->bus); - c_dvar_write(out_v, "}])"); + c_dvar_write(out_v, "}" + "{s<u>}" + "{s<u>}" + "{s<u>}" + "{s<u>}" + "{s<u>}" + "{s<u>}" + "{s<u>}" + "{s<u>}" + "{s<u>}" + "])", + "Serial", c_dvar_type_u, + util_t2u_saturating(++peer->bus->stats_ids), + "ActiveConnections", c_dvar_type_u, + util_z2u_saturating(bus->peers.n_registered), + "IncompleteConnections", c_dvar_type_u, + util_z2u_saturating(bus->peers.n_peers - bus->peers.n_registered), + "BusNames", c_dvar_type_u, + util_z2u_saturating(bus->names.n_primaries), + "PeakBusNames", c_dvar_type_u, + util_z2u_saturating(bus->names.n_primaries_peak), + "PeakBusNamesPerConnection", c_dvar_type_u, + util_z2u_saturating(bus->names.n_owner_primaries_peak), + "MatchRules", c_dvar_type_u, + util_z2u_saturating(bus->match_counters.n_subscriptions), + "PeakMatchRules", c_dvar_type_u, + util_z2u_saturating(bus->match_counters.n_subscriptions_peak), + "PeakMatchRulesPerConnection", c_dvar_type_u, + util_z2u_saturating(bus->match_counters.n_owner_subscriptions_peak) + ); r = driver_send_reply(peer, out_v, serial); if (r) @@ -2777,7 +2803,7 @@ r = driver_send_error(peer, message_read_serial(message), "org.freedesktop.DBus.Error.UnknownMethod", driver_error_to_string(r)); break; case DRIVER_E_UNEXPECTED_PROPERTY: - r = driver_send_error(peer, message_read_serial(message), "org.freedesktop.DBus.Error.UnkonwnProperty", driver_error_to_string(r)); + r = driver_send_error(peer, message_read_serial(message), "org.freedesktop.DBus.Error.UnknownProperty", driver_error_to_string(r)); break; case DRIVER_E_READONLY_PROPERTY: r = driver_send_error(peer, message_read_serial(message), "org.freedesktop.DBus.Error.PropertyReadOnly", driver_error_to_string(r)); diff -Nru dbus-broker-36/src/bus/match.c dbus-broker-37/src/bus/match.c --- dbus-broker-36/src/bus/match.c 2024-04-12 15:07:35.000000000 +0100 +++ dbus-broker-37/src/bus/match.c 2025-06-16 13:26:27.000000000 +0100 @@ -11,6 +11,7 @@ #include "dbus/message.h" #include "dbus/protocol.h" #include "util/error.h" +#include "util/misc.h" #include "util/string.h" static bool match_key_equal(const char *key1, const char *key2, size_t n_key2) { @@ -422,12 +423,12 @@ return false; for (unsigned int i = 0; i < keys->filter.n_args || i < keys->filter.n_argpaths; i ++) { - if (keys->filter.args[i] && !(metadata->args[0].element == 's' && string_equal(keys->filter.args[i], metadata->args[i].value))) + if (keys->filter.args[i] && !(metadata->args[i].element == 's' && string_equal(keys->filter.args[i], metadata->args[i].value))) return false; if (keys->filter.argpaths[i]) { if (!match_string_prefix(metadata->args[i].value, keys->filter.argpaths[i], '/', true) && - !match_string_prefix(keys->filter.argpaths[i], metadata->args[0].value, '/', true)) + !match_string_prefix(keys->filter.argpaths[i], metadata->args[i].value, '/', true)) return false; } } @@ -871,7 +872,7 @@ /** * match_rule_link() - XXX */ -int match_rule_link(MatchRule *rule, MatchRegistry *registry, bool monitor) { +int match_rule_link(MatchRule *rule, MatchCounters *counters, MatchRegistry *registry, bool monitor) { _c_cleanup_(match_registry_by_path_unrefp) MatchRegistryByPath *registry_by_path = NULL; CRBTree *tree; CRBNode **slot, *parent; @@ -880,6 +881,7 @@ if (rule->registry) { c_assert(registry == rule->registry); c_assert(c_list_is_linked(&rule->registry_link)); + c_assert(counters == rule->counters); return 0; } @@ -903,7 +905,16 @@ r = match_rule_link_by_path(rule, registry_by_path); if (r) return error_trace(r); + rule->registry = registry; + rule->counters = counters; + + if (counters) { + ++counters->n_subscriptions; + ++rule->owner->n_owner_subscriptions; + util_peak_update(&counters->n_subscriptions_peak, counters->n_subscriptions); + util_peak_update(&counters->n_owner_subscriptions_peak, rule->owner->n_owner_subscriptions); + } return 0; } @@ -913,8 +924,14 @@ */ void match_rule_unlink(MatchRule *rule) { if (rule->registry) { + if (rule->counters) { + --rule->owner->n_owner_subscriptions; + --rule->counters->n_subscriptions; + } + c_list_unlink(&rule->registry_link); rule->registry_by_keys = match_registry_by_keys_unref(rule->registry_by_keys); + rule->counters = NULL; rule->registry = NULL; } } diff -Nru dbus-broker-36/src/bus/match.h dbus-broker-37/src/bus/match.h --- dbus-broker-36/src/bus/match.h 2024-04-12 15:07:35.000000000 +0100 +++ dbus-broker-37/src/bus/match.h 2025-06-16 13:26:27.000000000 +0100 @@ -11,6 +11,7 @@ #include "dbus/address.h" #include "util/user.h" +typedef struct MatchCounters MatchCounters; typedef struct MatchFilter MatchFilter; typedef struct MatchKeys MatchKeys; typedef struct MatchOwner MatchOwner; @@ -71,6 +72,7 @@ MatchRegistry *registry; MatchOwner *owner; CRBNode owner_node; + MatchCounters *counters; UserCharge charge[2]; MatchKeys keys; @@ -85,6 +87,7 @@ } struct MatchOwner { + size_t n_owner_subscriptions; CRBTree rule_tree; CList destinations_link; }; @@ -161,12 +164,20 @@ .monitor_tree = C_RBTREE_INIT, \ } +struct MatchCounters { + size_t n_subscriptions; + size_t n_subscriptions_peak; + size_t n_owner_subscriptions_peak; +}; + +#define MATCH_COUNTERS_INIT {} + /* rules */ MatchRule *match_rule_user_ref(MatchRule *rule); MatchRule *match_rule_user_unref(MatchRule *rule); -int match_rule_link(MatchRule *rule, MatchRegistry *registry, bool monitor); +int match_rule_link(MatchRule *rule, MatchCounters *counters, MatchRegistry *registry, bool monitor); void match_rule_unlink(MatchRule *rule); C_DEFINE_CLEANUP(MatchRule *, match_rule_user_unref); diff -Nru dbus-broker-36/src/bus/name.c dbus-broker-37/src/bus/name.c --- dbus-broker-36/src/bus/name.c 2024-04-12 15:07:35.000000000 +0100 +++ dbus-broker-37/src/bus/name.c 2025-06-16 13:26:27.000000000 +0100 @@ -11,6 +11,7 @@ #include "dbus/protocol.h" #include "dbus/socket.h" #include "util/error.h" +#include "util/misc.h" #include "util/user.h" /** @@ -115,20 +116,31 @@ */ void name_ownership_release(NameOwnership *ownership, NameChange *change) { NameOwnership *primary; + Name *name = ownership->name; c_assert(!change->name); c_assert(!change->old_owner); c_assert(!change->new_owner); - primary = name_primary(ownership->name); + primary = name_primary(name); c_list_unlink(&ownership->name_link); if (ownership == primary) { - primary = name_primary(ownership->name); + --ownership->owner->n_owner_primaries; + --name->registry->n_primaries; - change->name = name_ref(ownership->name); + primary = name_primary(name); + + change->name = name_ref(name); change->old_owner = ownership->owner; change->new_owner = primary ? primary->owner : NULL; + + if (primary) { + // skip `n_primaries_peak` as `n_primaries` did not change + ++name->registry->n_primaries; + ++primary->owner->n_owner_primaries; + util_peak_update(&name->registry->n_owner_primaries_peak, primary->owner->n_owner_primaries); + } } name_ownership_free(ownership); @@ -156,6 +168,12 @@ c_assert(!c_list_is_linked(&ownership->name_link)); c_list_link_front(&name->ownership_list, &ownership->name_link); + + ++name->registry->n_primaries; + ++ownership->owner->n_owner_primaries; + util_peak_update(&name->registry->n_primaries_peak, name->registry->n_primaries); + util_peak_update(&name->registry->n_owner_primaries_peak, ownership->owner->n_owner_primaries); + r = 0; } else if (primary == ownership) { /* we are already the primary owner */ @@ -170,6 +188,11 @@ c_list_unlink(&ownership->name_link); c_list_link_front(&name->ownership_list, &ownership->name_link); + // skip `n_primaries_peak` as `n_primaries` did not change + --primary->owner->n_owner_primaries; + ++ownership->owner->n_owner_primaries; + util_peak_update(&name->registry->n_owner_primaries_peak, ownership->owner->n_owner_primaries); + /* drop previous primary owner, if queuing is not requested */ if (primary->flags & DBUS_NAME_FLAG_DO_NOT_QUEUE) { c_list_unlink(&primary->name_link); diff -Nru dbus-broker-36/src/bus/name.h dbus-broker-37/src/bus/name.h --- dbus-broker-36/src/bus/name.h 2024-04-12 15:07:35.000000000 +0100 +++ dbus-broker-37/src/bus/name.h 2025-06-16 13:26:27.000000000 +0100 @@ -76,6 +76,7 @@ } struct NameOwner { + size_t n_owner_primaries; CRBTree ownership_tree; }; @@ -84,6 +85,9 @@ } struct NameRegistry { + size_t n_primaries; + size_t n_primaries_peak; + size_t n_owner_primaries_peak; CRBTree name_tree; }; diff -Nru dbus-broker-36/src/bus/peer.c dbus-broker-37/src/bus/peer.c --- dbus-broker-36/src/bus/peer.c 2024-04-12 15:07:35.000000000 +0100 +++ dbus-broker-37/src/bus/peer.c 2025-06-16 13:26:27.000000000 +0100 @@ -298,6 +298,7 @@ *peer = (Peer)PEER_INIT(*peer); peer->bus = bus; + ++peer->bus->peers.n_peers; peer->user = user; user = NULL; peer->pid = ucred.pid; @@ -378,6 +379,7 @@ free(peer->seclabel); free(peer->gids); user_unref(peer->user); + --peer->bus->peers.n_peers; free(peer); close(fd); @@ -394,12 +396,14 @@ c_assert(!peer->monitor); peer->registered = true; + ++peer->bus->peers.n_registered; } void peer_unregister(Peer *peer) { c_assert(peer->registered); c_assert(!peer->monitor); + --peer->bus->peers.n_registered; peer->registered = false; } @@ -477,12 +481,16 @@ } static int peer_link_match(Peer *peer, MatchRule *rule, bool monitor) { + MatchCounters *counters = NULL; Address addr; Peer *sender, *owner; int r; + if (!monitor) + counters = &peer->bus->match_counters; + if (!rule->keys.sender) { - r = match_rule_link(rule, &peer->bus->wildcard_matches, monitor); + r = match_rule_link(rule, counters, &peer->bus->wildcard_matches, monitor); if (r) return error_fold(r); } else if (strcmp(rule->keys.sender, "org.freedesktop.DBus") == 0) { @@ -499,7 +507,7 @@ case ADDRESS_TYPE_ID: { owner = peer_registry_find_peer(&peer->bus->peers, addr.id); if (owner) { - r = match_rule_link(rule, &owner->name_owner_changed_matches, monitor); + r = match_rule_link(rule, counters, &owner->name_owner_changed_matches, monitor); if (r) return error_fold(r); } else if (addr.id >= peer->bus->peers.ids) { @@ -513,7 +521,7 @@ * forthcoming peer, so this is most likely * a bug in a client. */ - r = match_rule_link(rule, &peer->bus->sender_matches, monitor); + r = match_rule_link(rule, counters, &peer->bus->sender_matches, monitor); if (r) return error_fold(r); } else { @@ -537,7 +545,7 @@ if (r) return error_fold(r); - r = match_rule_link(rule, &name->name_owner_changed_matches, monitor); + r = match_rule_link(rule, counters, &name->name_owner_changed_matches, monitor); if (r) return error_fold(r); name_ref(name); /* this reference must be explicitly released */ @@ -552,7 +560,7 @@ * install other (unexpected) matches here, they will always be false negatives * but for the sake of simplicity we do not attempt to optimize them away. */ - r = match_rule_link(rule, &peer->bus->sender_matches, monitor); + r = match_rule_link(rule, counters, &peer->bus->sender_matches, monitor); if (r) return error_fold(r); } @@ -562,7 +570,7 @@ case ADDRESS_TYPE_ID: { sender = peer_registry_find_peer(&peer->bus->peers, addr.id); if (sender) { - r = match_rule_link(rule, &sender->sender_matches, monitor); + r = match_rule_link(rule, counters, &sender->sender_matches, monitor); if (r) return error_fold(r); } else if (addr.id >= peer->bus->peers.ids) { @@ -571,7 +579,7 @@ * reasoning as above, keep it as a wildcard * match. */ - r = match_rule_link(rule, &peer->bus->wildcard_matches, monitor); + r = match_rule_link(rule, counters, &peer->bus->wildcard_matches, monitor); if (r) return error_fold(r); } else { @@ -591,7 +599,7 @@ if (r) return error_fold(r); - r = match_rule_link(rule, &name->sender_matches, monitor); + r = match_rule_link(rule, counters, &name->sender_matches, monitor); if (r) return error_fold(r); name_ref(name); /* this reference must be explicitly released */ diff -Nru dbus-broker-36/src/bus/peer.h dbus-broker-37/src/bus/peer.h --- dbus-broker-36/src/bus/peer.h 2024-04-12 15:07:35.000000000 +0100 +++ dbus-broker-37/src/bus/peer.h 2025-06-16 13:26:27.000000000 +0100 @@ -96,6 +96,8 @@ struct PeerRegistry { CRBTree peer_tree; uint64_t ids; + size_t n_peers; + size_t n_registered; }; #define PEER_REGISTRY_INIT {} diff -Nru dbus-broker-36/src/bus/test-match.c dbus-broker-37/src/bus/test-match.c --- dbus-broker-36/src/bus/test-match.c 2024-04-12 15:07:35.000000000 +0100 +++ dbus-broker-37/src/bus/test-match.c 2025-06-16 13:26:27.000000000 +0100 @@ -161,7 +161,7 @@ r = match_owner_ref_rule(&owner, &rule, NULL, match_string, false); c_assert(!r); - r = match_rule_link(rule, ®istry, false); + r = match_rule_link(rule, NULL, ®istry, false); c_assert(!r); match_registry_get_subscribers(®istry, &subscribers, metadata); @@ -254,6 +254,33 @@ c_assert(!test_match("arg0=com.example.foobar", &metadata)); c_assert(!test_match("arg0=com.example", &metadata)); + /* arg1 */ + metadata = (MessageMetadata)MESSAGE_METADATA_INIT; + c_assert(!test_match("arg1=/com/example/foo/", &metadata)); + metadata.args[0].value = "unrelated string"; + metadata.args[0].element = 's'; + metadata.args[1].value = "/com/example/foo/"; + metadata.args[1].element = 's'; + metadata.n_args = 2; + c_assert(test_match("arg1=/com/example/foo/", &metadata)); + c_assert(!test_match("arg1=/com/example/foo/bar", &metadata)); + c_assert(!test_match("arg1=/com/example/foobar", &metadata)); + c_assert(!test_match("arg1=/com/example/", &metadata)); + c_assert(!test_match("arg1=/com/example", &metadata)); + metadata.args[1].value = "/com/example/foo"; + metadata.args[1].element = 's'; + c_assert(test_match("arg1=/com/example/foo", &metadata)); + c_assert(!test_match("arg1=/com/example/foo/bar", &metadata)); + c_assert(!test_match("arg1=/com/example/foobar", &metadata)); + c_assert(!test_match("arg1=/com/example/", &metadata)); + c_assert(!test_match("arg1=/com/example", &metadata)); + metadata.args[1].value = "com.example.foo"; + metadata.args[1].element = 's'; + c_assert(test_match("arg1=com.example.foo", &metadata)); + c_assert(!test_match("arg1=com.example.foo.bar", &metadata)); + c_assert(!test_match("arg1=com.example.foobar", &metadata)); + c_assert(!test_match("arg1=com.example", &metadata)); + /* arg0path - parent */ metadata = (MessageMetadata)MESSAGE_METADATA_INIT; c_assert(!test_match("arg0path=/com/example/foo/", &metadata)); @@ -278,6 +305,34 @@ c_assert(test_match("arg0path=/com/example/", &metadata)); c_assert(!test_match("arg0path=/com/example", &metadata)); + /* arg1path - parent */ + metadata = (MessageMetadata)MESSAGE_METADATA_INIT; + c_assert(!test_match("arg1path=/com/example/foo/", &metadata)); + metadata.args[0].value = "unrelated string"; + metadata.args[0].element = 's'; + metadata.args[1].value = "/com/example/foo/"; + metadata.args[1].element = 'o'; + metadata.n_args = 2; + c_assert(test_match("arg1path=/com/example/foo/", &metadata)); + c_assert(test_match("arg1path=/com/example/foo/bar", &metadata)); + c_assert(!test_match("arg1path=/com/example/foobar", &metadata)); + c_assert(test_match("arg1path=/com/example/", &metadata)); + c_assert(!test_match("arg1path=/com/example", &metadata)); + + /* arg1path - child */ + metadata = (MessageMetadata)MESSAGE_METADATA_INIT; + c_assert(!test_match("arg1path=/com/example/foo", &metadata)); + metadata.args[0].value = "unrelated string"; + metadata.args[0].element = 's'; + metadata.args[1].value = "/com/example/foo"; + metadata.args[1].element = 'o'; + metadata.n_args = 2; + c_assert(test_match("arg1path=/com/example/foo", &metadata)); + c_assert(!test_match("arg1path=/com/example/foo/bar", &metadata)); + c_assert(!test_match("arg1path=/com/example/foobar", &metadata)); + c_assert(test_match("arg1path=/com/example/", &metadata)); + c_assert(!test_match("arg1path=/com/example", &metadata)); + /* arg0namespace */ metadata = (MessageMetadata)MESSAGE_METADATA_INIT; c_assert(!test_match("arg0namespace=com.example.foo", &metadata)); @@ -306,25 +361,25 @@ r = match_owner_ref_rule(&owner1, &rule1, NULL, "", false); c_assert(!r); - r = match_rule_link(rule1, ®istry, false); + r = match_rule_link(rule1, NULL, ®istry, false); c_assert(!r); r = match_owner_ref_rule(&owner1, &rule2, NULL, "", false); c_assert(!r); - r = match_rule_link(rule2, ®istry, false); + r = match_rule_link(rule2, NULL, ®istry, false); c_assert(!r); r = match_owner_ref_rule(&owner2, &rule3, NULL, "", false); c_assert(!r); - r = match_rule_link(rule3, ®istry, false); + r = match_rule_link(rule3, NULL, ®istry, false); c_assert(!r); r = match_owner_ref_rule(&owner2, &rule4, NULL, "", false); c_assert(!r); - r = match_rule_link(rule4, ®istry, false); + r = match_rule_link(rule4, NULL, ®istry, false); c_assert(!r); match_registry_get_subscribers(®istry, &subscribers, &metadata); @@ -344,7 +399,94 @@ match_owner_deinit(&owner2); match_owner_deinit(&owner1); match_registry_deinit(®istry); +} + +static void test_counters(void) { + MatchCounters counters = MATCH_COUNTERS_INIT; + MatchRegistry registry = MATCH_REGISTRY_INIT(registry); + MatchOwner owner1, owner2; + MatchRule *rule1, *rule2, *rule3, *rule4; + int r; + + match_owner_init(&owner1); + match_owner_init(&owner2); + + c_assert(owner1.n_owner_subscriptions == 0); + c_assert(owner2.n_owner_subscriptions == 0); + c_assert(counters.n_subscriptions == 0); + c_assert(counters.n_subscriptions_peak == 0); + c_assert(counters.n_owner_subscriptions_peak == 0); + + /* owner1: install a new match */ + + r = match_owner_ref_rule(&owner1, &rule1, NULL, "path=/a", false); + c_assert(!r); + + r = match_rule_link(rule1, &counters, ®istry, false); + c_assert(!r); + + c_assert(owner1.n_owner_subscriptions == 1); + c_assert(owner2.n_owner_subscriptions == 0); + c_assert(counters.n_subscriptions == 1); + c_assert(counters.n_subscriptions_peak == 1); + c_assert(counters.n_owner_subscriptions_peak == 1); + + /* owner1: install the same match again */ + + r = match_owner_ref_rule(&owner1, &rule2, NULL, "path=/a", false); + c_assert(!r); + + r = match_rule_link(rule2, &counters, ®istry, false); + c_assert(!r); + + c_assert(owner1.n_owner_subscriptions == 1); + c_assert(owner2.n_owner_subscriptions == 0); + c_assert(counters.n_subscriptions == 1); + c_assert(counters.n_subscriptions_peak == 1); + c_assert(counters.n_owner_subscriptions_peak == 1); + + /* owner2: install a new match */ + + r = match_owner_ref_rule(&owner2, &rule3, NULL, "path=/a", false); + c_assert(!r); + + r = match_rule_link(rule3, &counters, ®istry, false); + c_assert(!r); + + c_assert(owner1.n_owner_subscriptions == 1); + c_assert(owner2.n_owner_subscriptions == 1); + c_assert(counters.n_subscriptions == 2); + c_assert(counters.n_subscriptions_peak == 2); + c_assert(counters.n_owner_subscriptions_peak == 1); + + /* owner2: install another match */ + + r = match_owner_ref_rule(&owner2, &rule4, NULL, "path=/b", false); + c_assert(!r); + r = match_rule_link(rule4, &counters, ®istry, false); + c_assert(!r); + + c_assert(owner1.n_owner_subscriptions == 1); + c_assert(owner2.n_owner_subscriptions == 2); + c_assert(counters.n_subscriptions == 3); + c_assert(counters.n_subscriptions_peak == 3); + c_assert(counters.n_owner_subscriptions_peak == 2); + + match_rule_user_unref(rule4); + match_rule_user_unref(rule3); + match_rule_user_unref(rule2); + match_rule_user_unref(rule1); + + c_assert(owner1.n_owner_subscriptions == 0); + c_assert(owner2.n_owner_subscriptions == 0); + c_assert(counters.n_subscriptions == 0); + c_assert(counters.n_subscriptions_peak == 3); + c_assert(counters.n_owner_subscriptions_peak == 2); + + match_owner_deinit(&owner2); + match_owner_deinit(&owner1); + match_registry_deinit(®istry); } int main(int argc, char **argv) { @@ -358,8 +500,8 @@ test_eavesdrop(&owner); test_individual_matches(); - test_iterator(); + test_counters(); match_owner_deinit(&owner); return 0; diff -Nru dbus-broker-36/src/bus/test-name.c dbus-broker-37/src/bus/test-name.c --- dbus-broker-36/src/bus/test-name.c 2024-04-12 15:07:35.000000000 +0100 +++ dbus-broker-37/src/bus/test-name.c 2025-06-16 13:26:27.000000000 +0100 @@ -220,9 +220,219 @@ name_registry_deinit(®istry); } +static void test_queue_counters(void) { + NameRegistry registry; + NameOwner owner1, owner2; + NameChange change; + int r; + + /* + * Verify that primary counters are adjusted correctly on queue updates + * and replacements. They should only count primary ownerships, not any + * secondary name queuing. + */ + + name_registry_init(®istry); + name_owner_init(&owner1); + name_owner_init(&owner2); + name_change_init(&change); + + c_assert(owner1.n_owner_primaries == 0); + c_assert(owner2.n_owner_primaries == 0); + c_assert(registry.n_primaries == 0); + c_assert(registry.n_primaries_peak == 0); + c_assert(registry.n_owner_primaries_peak == 0); + + /* owner1: foobar */ + r = name_registry_request_name(®istry, &owner1, NULL, "foobar", 0, &change); + c_assert(!r); + name_change_deinit(&change); + + c_assert(owner1.n_owner_primaries == 1); + c_assert(owner2.n_owner_primaries == 0); + c_assert(registry.n_primaries == 1); + c_assert(registry.n_primaries_peak == 1); + c_assert(registry.n_owner_primaries_peak == 1); + + /* re-request and queuing should not affect counters */ + r = name_registry_request_name(®istry, &owner1, NULL, "foobar", 0, &change); + c_assert(r == NAME_E_ALREADY_OWNER); + r = name_registry_request_name(®istry, &owner2, NULL, "foobar", DBUS_NAME_FLAG_DO_NOT_QUEUE, &change); + c_assert(r == NAME_E_EXISTS); + r = name_registry_request_name(®istry, &owner2, NULL, "foobar", DBUS_NAME_FLAG_DO_NOT_QUEUE | DBUS_NAME_FLAG_REPLACE_EXISTING, &change); + c_assert(r == NAME_E_EXISTS); + r = name_registry_request_name(®istry, &owner2, NULL, "foobar", 0, &change); + c_assert(r == NAME_E_IN_QUEUE); + + c_assert(owner1.n_owner_primaries == 1); + c_assert(owner2.n_owner_primaries == 0); + c_assert(registry.n_primaries == 1); + c_assert(registry.n_primaries_peak == 1); + c_assert(registry.n_owner_primaries_peak == 1); + + /* dequeue again */ + r = name_registry_release_name(®istry, &owner2, "foobar", &change); + c_assert(r == 0); + + c_assert(owner1.n_owner_primaries == 1); + c_assert(owner2.n_owner_primaries == 0); + c_assert(registry.n_primaries == 1); + c_assert(registry.n_primaries_peak == 1); + c_assert(registry.n_owner_primaries_peak == 1); + + /* queue owner2 then allow replacement (takes effect on next request) */ + r = name_registry_request_name(®istry, &owner2, NULL, "foobar", DBUS_NAME_FLAG_REPLACE_EXISTING, &change); + c_assert(r == NAME_E_IN_QUEUE); + r = name_registry_request_name(®istry, &owner1, NULL, "foobar", DBUS_NAME_FLAG_ALLOW_REPLACEMENT, &change); + c_assert(r == NAME_E_ALREADY_OWNER); + r = name_registry_request_name(®istry, &owner2, NULL, "foobar", 0, &change); + c_assert(r == NAME_E_IN_QUEUE); + + c_assert(owner1.n_owner_primaries == 1); + c_assert(owner2.n_owner_primaries == 0); + c_assert(registry.n_primaries == 1); + c_assert(registry.n_primaries_peak == 1); + c_assert(registry.n_owner_primaries_peak == 1); + + /* now overtake the primary */ + r = name_registry_request_name(®istry, &owner2, NULL, "foobar", + DBUS_NAME_FLAG_REPLACE_EXISTING | + DBUS_NAME_FLAG_ALLOW_REPLACEMENT | + DBUS_NAME_FLAG_DO_NOT_QUEUE, + &change); + c_assert(!r); + name_change_deinit(&change); + + c_assert(owner1.n_owner_primaries == 0); + c_assert(owner2.n_owner_primaries == 1); + c_assert(registry.n_primaries == 1); + c_assert(registry.n_primaries_peak == 1); + c_assert(registry.n_owner_primaries_peak == 1); + + /* overtake again */ + r = name_registry_request_name(®istry, &owner1, NULL, "foobar", DBUS_NAME_FLAG_REPLACE_EXISTING, &change); + c_assert(!r); + name_change_deinit(&change); + + c_assert(owner1.n_owner_primaries == 1); + c_assert(owner2.n_owner_primaries == 0); + c_assert(registry.n_primaries == 1); + c_assert(registry.n_primaries_peak == 1); + c_assert(registry.n_owner_primaries_peak == 1); + + /* release names */ + r = name_registry_release_name(®istry, &owner1, "foobar", &change); + c_assert(r == 0); + name_change_deinit(&change); + + name_owner_deinit(&owner2); + name_owner_deinit(&owner1); + name_registry_deinit(®istry); +} + +static void test_peak_counters(void) { + NameRegistry registry; + NameOwner owner1, owner2; + NameChange change; + int r; + + /* + * Verify that primary peak-counters are adjusted correctly when peers + * acquire primary names. + */ + + name_registry_init(®istry); + name_owner_init(&owner1); + name_owner_init(&owner2); + name_change_init(&change); + + c_assert(owner1.n_owner_primaries == 0); + c_assert(owner2.n_owner_primaries == 0); + c_assert(registry.n_primaries == 0); + c_assert(registry.n_primaries_peak == 0); + c_assert(registry.n_owner_primaries_peak == 0); + + /* owner1: foobar0 */ + r = name_registry_request_name(®istry, &owner1, NULL, "foobar0", 0, &change); + c_assert(!r); + name_change_deinit(&change); + + c_assert(owner1.n_owner_primaries == 1); + c_assert(owner2.n_owner_primaries == 0); + c_assert(registry.n_primaries == 1); + c_assert(registry.n_primaries_peak == 1); + c_assert(registry.n_owner_primaries_peak == 1); + + /* owner1: foobar1 */ + r = name_registry_request_name(®istry, &owner1, NULL, "foobar1", 0, &change); + c_assert(!r); + name_change_deinit(&change); + + c_assert(owner1.n_owner_primaries == 2); + c_assert(owner2.n_owner_primaries == 0); + c_assert(registry.n_primaries == 2); + c_assert(registry.n_primaries_peak == 2); + c_assert(registry.n_owner_primaries_peak == 2); + + /* owner2: foobar2 */ + r = name_registry_request_name(®istry, &owner2, NULL, "foobar2", 0, &change); + c_assert(!r); + name_change_deinit(&change); + + c_assert(owner1.n_owner_primaries == 2); + c_assert(owner2.n_owner_primaries == 1); + c_assert(registry.n_primaries == 3); + c_assert(registry.n_primaries_peak == 3); + c_assert(registry.n_owner_primaries_peak == 2); + + /* owner2: foobar3 */ + r = name_registry_request_name(®istry, &owner2, NULL, "foobar3", 0, &change); + c_assert(!r); + name_change_deinit(&change); + + c_assert(owner1.n_owner_primaries == 2); + c_assert(owner2.n_owner_primaries == 2); + c_assert(registry.n_primaries == 4); + c_assert(registry.n_primaries_peak == 4); + c_assert(registry.n_owner_primaries_peak == 2); + + /* release names */ + r = name_registry_release_name(®istry, &owner2, "foobar3", &change); + c_assert(r == 0); + name_change_deinit(&change); + r = name_registry_release_name(®istry, &owner2, "foobar2", &change); + c_assert(r == 0); + name_change_deinit(&change); + + c_assert(owner1.n_owner_primaries == 2); + c_assert(owner2.n_owner_primaries == 0); + c_assert(registry.n_primaries == 2); + c_assert(registry.n_primaries_peak == 4); + c_assert(registry.n_owner_primaries_peak == 2); + + r = name_registry_release_name(®istry, &owner1, "foobar1", &change); + c_assert(r == 0); + name_change_deinit(&change); + r = name_registry_release_name(®istry, &owner1, "foobar0", &change); + c_assert(r == 0); + name_change_deinit(&change); + + c_assert(owner1.n_owner_primaries == 0); + c_assert(owner2.n_owner_primaries == 0); + c_assert(registry.n_primaries == 0); + c_assert(registry.n_primaries_peak == 4); + c_assert(registry.n_owner_primaries_peak == 2); + + name_owner_deinit(&owner2); + name_owner_deinit(&owner1); + name_registry_deinit(®istry); +} + int main(int argc, char **argv) { test_setup(); test_release(); test_queue(); + test_queue_counters(); + test_peak_counters(); return 0; } diff -Nru dbus-broker-36/src/dbus/protocol.h dbus-broker-37/src/dbus/protocol.h --- dbus-broker-36/src/dbus/protocol.h 2024-04-12 15:07:35.000000000 +0100 +++ dbus-broker-37/src/dbus/protocol.h 2025-06-16 13:26:27.000000000 +0100 @@ -63,5 +63,5 @@ bool dbus_validate_name(const char *name, size_t n_name); bool dbus_validate_namespace(const char *namespace, size_t n_namespace); bool dbus_validate_interface(const char *interface, size_t n_interface); -bool dbus_validate_member(const char *memebr, size_t n_member); +bool dbus_validate_member(const char *member, size_t n_member); bool dbus_validate_error_name(const char *name, size_t n_name); diff -Nru dbus-broker-36/src/dbus/socket.c dbus-broker-37/src/dbus/socket.c --- dbus-broker-36/src/dbus/socket.c 2024-04-12 15:07:35.000000000 +0100 +++ dbus-broker-37/src/dbus/socket.c 2025-06-16 13:26:27.000000000 +0100 @@ -173,9 +173,13 @@ for ( ; !socket_buffer_is_consumed(buffer); ++buffer->writer) { t = c_min(buffer->writer->iov_len, n); - buffer->writer->iov_len -= t; - buffer->writer->iov_base += t; - n -= t; + // IOVs can be empty/NULL. Ensure we do not calculate + // `NULL + 0`, as this is, unfortunately, UB. + if (t) { + buffer->writer->iov_len -= t; + buffer->writer->iov_base += t; + n -= t; + } if (buffer->writer->iov_len) break; } diff -Nru dbus-broker-36/src/launch/launcher.c dbus-broker-37/src/launch/launcher.c --- dbus-broker-36/src/launch/launcher.c 2024-04-12 15:07:35.000000000 +0100 +++ dbus-broker-37/src/launch/launcher.c 2025-06-16 13:26:27.000000000 +0100 @@ -29,6 +29,7 @@ #include "util/fs.h" #include "util/log.h" #include "util/misc.h" +#include "util/nsec.h" #include "util/string.h" /* @@ -159,7 +160,7 @@ return 1; } -static int launcher_open_log(Launcher *launcher) { +static int launcher_open_journal(int *fdp) { _c_cleanup_(c_closep) int fd = -1; struct sockaddr_un address = { .sun_family = AF_UNIX, @@ -167,8 +168,6 @@ }; int r; - c_assert(log_get_fd(&launcher->log) < 0); - fd = socket(PF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0); if (fd < 0) return error_origin(-errno); @@ -179,8 +178,21 @@ if (r < 0) return error_origin(-errno); - log_init_journal_consume(&launcher->log, fd); + *fdp = fd; fd = -1; + return 0; +} + +static int launcher_open_log(Launcher *launcher) { + int r, fd; + + c_assert(log_get_fd(&launcher->log) < 0); + + r = launcher_open_journal(&fd); + if (r) + return error_fold(r); + + log_init_journal_consume(&launcher->log, fd); /* XXX: make this run-time optional */ log_set_lossy(&launcher->log, true); @@ -258,7 +270,7 @@ return NULL; } -static noreturn void launcher_run_child(Launcher *launcher, int fd_log, int fd_controller) { +static noreturn void launcher_run_child(Launcher *launcher, int fd_controller) { sd_id128_t machine_id; char str_log[C_DECIMAL_MAX(int) + 1], str_controller[C_DECIMAL_MAX(int) + 1], @@ -283,7 +295,7 @@ launcher->audit ? "--audit" : NULL, /* note that this needs to be the last argument to work */ NULL, }; - int r; + int r, fd_journal; if (launcher->uid != (uint32_t)-1) { r = util_audit_drop_permissions(launcher->uid, launcher->gid); @@ -297,13 +309,19 @@ goto exit; } - r = fcntl(fd_log, F_GETFD); + r = launcher_open_journal(&fd_journal); + if (r) { + r = error_trace(r); + goto exit; + } + + r = fcntl(fd_journal, F_GETFD); if (r < 0) { r = error_origin(-errno); goto exit; } - r = fcntl(fd_log, F_SETFD, r & ~FD_CLOEXEC); + r = fcntl(fd_journal, F_SETFD, r & ~FD_CLOEXEC); if (r < 0) { r = error_origin(-errno); goto exit; @@ -329,7 +347,7 @@ sd_id128_to_string(machine_id, str_machine_id); - r = snprintf(str_log, sizeof(str_log), "%d", fd_log); + r = snprintf(str_log, sizeof(str_log), "%d", fd_journal); c_assert(r < (ssize_t)sizeof(str_log)); r = snprintf(str_controller, sizeof(str_controller), "%d", fd_controller); @@ -375,7 +393,7 @@ return error_origin(-errno); if (!pid) - launcher_run_child(launcher, log_get_fd(&launcher->log), fd_controller); + launcher_run_child(launcher, fd_controller); r = sd_event_add_child(launcher->event, NULL, pid, WEXITED, launcher_on_child_exit, launcher); if (r < 0) @@ -925,6 +943,8 @@ static int launcher_load_standard_system_services(Launcher *launcher, NSSCache *nss_cache) { static const char *default_data_dirs[] = { + "/etc", + "/run", "/usr/local/share", "/usr/share", "/lib", @@ -1165,7 +1185,10 @@ Service *service; int r, res; - r = sd_notify(false, "RELOADING=1"); + r = sd_notifyf(/* unset_environment = */ false, + "RELOADING=1\n" + "MONOTONIC_USEC=%" NSEC_PRI, + nsec_to_usec(nsec_now(CLOCK_MONOTONIC))); if (r < 0) return error_origin(r); diff -Nru dbus-broker-36/src/launch/nss-cache.c dbus-broker-37/src/launch/nss-cache.c --- dbus-broker-36/src/launch/nss-cache.c 2024-04-12 15:07:35.000000000 +0100 +++ dbus-broker-37/src/launch/nss-cache.c 2025-06-16 13:26:27.000000000 +0100 @@ -491,9 +491,13 @@ return 0; } -int nss_cache_resolve_system_console_users(NSSCache *nss_cache, uint32_t **uidsp, size_t *n_uidsp) { - static const char * const usernames[] = { SYSTEM_CONSOLE_USERS }; - static const size_t n_usernames = C_ARRAY_SIZE(usernames); +static int nss_cache_resolve_names( + NSSCache *nss_cache, + uint32_t **uidsp, + size_t *n_uidsp, + const char * const *usernames, + size_t n_usernames +) { _c_cleanup_(c_freep) uint32_t *uids = NULL; size_t i, n_uids = 0; uid_t uid; @@ -526,3 +530,14 @@ uids = NULL; return 0; } + +int nss_cache_resolve_system_console_users(NSSCache *nss_cache, uint32_t **uidsp, size_t *n_uidsp) { + static const char * const usernames[] = { SYSTEM_CONSOLE_USERS }; + static const size_t n_usernames = C_ARRAY_SIZE(usernames); + + // We avoid inlining `nss_cache_resolve_names()` here, as GCC will start + // complaining about use of `usernames` if it is empty, even though the + // function bails out early if it is empty. + + return nss_cache_resolve_names(nss_cache, uidsp, n_uidsp, usernames, n_usernames); +} diff -Nru dbus-broker-36/src/launch/policy.c dbus-broker-37/src/launch/policy.c --- dbus-broker-36/src/launch/policy.c 2024-04-12 15:07:35.000000000 +0100 +++ dbus-broker-37/src/launch/policy.c 2025-06-16 13:26:27.000000000 +0100 @@ -396,16 +396,19 @@ } else if (cnode->parent->policy.context == CONFIG_POLICY_AT_CONSOLE) { c_list_link_tail(&policy->at_console_entries.own_list, &record->link); } else if (cnode->parent->policy.context == CONFIG_POLICY_GROUP) { - r = policy_at_gid(policy, &node, cnode->parent->policy.id); - if (r) - return error_trace(r); + if (cnode->parent->policy.id != (uint32_t)-1) { + r = policy_at_gid(policy, &node, cnode->parent->policy.id); + if (r) + return error_trace(r); - c_list_link_tail(&node->entries.own_list, &record->link); + c_list_link_tail(&node->entries.own_list, &record->link); + } } else { c_list_link_tail(&policy->default_entries.own_list, &record->link); } - record = NULL; + if (c_list_is_linked(&record->link)) + record = NULL; return 0; } @@ -497,7 +500,8 @@ c_list_link_tail(&policy->default_entries.send_list, &record->link); } - record = NULL; + if (c_list_is_linked(&record->link)) + record = NULL; return 0; } @@ -589,7 +593,8 @@ c_list_link_tail(&policy->default_entries.recv_list, &record->link); } - record = NULL; + if (c_list_is_linked(&record->link)) + record = NULL; return 0; } diff -Nru dbus-broker-36/src/meson.build dbus-broker-37/src/meson.build --- dbus-broker-36/src/meson.build 2024-04-12 15:07:35.000000000 +0100 +++ dbus-broker-37/src/meson.build 2025-06-16 13:26:27.000000000 +0100 @@ -40,6 +40,7 @@ 'util/log.c', 'util/metrics.c', 'util/misc.c', + 'util/nsec.c', 'util/proc.c', 'util/sockopt.c', 'util/string.c', @@ -55,6 +56,8 @@ dep_math, ] +incs_bus = include_directories('.') + if use_apparmor sources_bus += [ 'util/apparmor.c', @@ -119,7 +122,7 @@ ) dep_bus = declare_dependency( - include_directories: include_directories('.'), + include_directories: incs_bus, link_with: static_bus, dependencies: deps_bus, version: meson.project_version(), @@ -217,6 +220,9 @@ test_name = executable('test-name', sources: ['bus/test-name.c'], kwargs: test_kwargs) test('Name Registry', test_name, suite: 'unit') +test_nsec = executable('test-nsec', sources: ['util/test-nsec.c'], kwargs: test_kwargs) +test('Nanosecond Time', test_nsec, suite: 'unit') + if use_launcher test_nss_cache = executable('test-nss-cache', sources: ['launch/test-nss-cache.c'], kwargs: test_kwargs) test('NSS Cache', test_nss_cache, suite: 'unit') diff -Nru dbus-broker-36/src/units/system/dbus-broker.service.in dbus-broker-37/src/units/system/dbus-broker.service.in --- dbus-broker-36/src/units/system/dbus-broker.service.in 2024-04-12 15:07:35.000000000 +0100 +++ dbus-broker-37/src/units/system/dbus-broker.service.in 2025-06-16 13:26:27.000000000 +0100 @@ -8,7 +8,7 @@ Conflicts=shutdown.target [Service] -Type=notify +Type=notify-reload Sockets=dbus.socket OOMScoreAdjust=-900 LimitNOFILE=16384 @@ -16,7 +16,6 @@ PrivateTmp=true PrivateDevices=true ExecStart=@bindir@/dbus-broker-launch --scope system --audit -ExecReload=@bindir@/busctl call org.freedesktop.DBus /org/freedesktop/DBus org.freedesktop.DBus ReloadConfig [Install] Alias=dbus.service diff -Nru dbus-broker-36/src/units/user/dbus-broker.service.in dbus-broker-37/src/units/user/dbus-broker.service.in --- dbus-broker-36/src/units/user/dbus-broker.service.in 2024-04-12 15:07:35.000000000 +0100 +++ dbus-broker-37/src/units/user/dbus-broker.service.in 2025-06-16 13:26:27.000000000 +0100 @@ -8,10 +8,9 @@ Conflicts=shutdown.target [Service] -Type=notify +Type=notify-reload Sockets=dbus.socket ExecStart=@bindir@/dbus-broker-launch --scope user -ExecReload=@bindir@/busctl --user call org.freedesktop.DBus /org/freedesktop/DBus org.freedesktop.DBus ReloadConfig Slice=session.slice [Install] diff -Nru dbus-broker-36/src/util/apparmor.c dbus-broker-37/src/util/apparmor.c --- dbus-broker-36/src/util/apparmor.c 2024-04-12 15:07:35.000000000 +0100 +++ dbus-broker-37/src/util/apparmor.c 2025-06-16 13:26:27.000000000 +0100 @@ -179,7 +179,7 @@ * the right UID to use, follow dbus-daemon(1) and use our * own. */ r = util_audit_log(UTIL_AUDIT_TYPE_AVC, message, getuid()); - if (r) + if (r != UTIL_AUDIT_E_UNAVAILABLE) // XXX: use a log fallback return error_fold(r); return 0; diff -Nru dbus-broker-36/src/util/audit.c dbus-broker-37/src/util/audit.c --- dbus-broker-36/src/util/audit.c 2024-04-12 15:07:35.000000000 +0100 +++ dbus-broker-37/src/util/audit.c 2025-06-16 13:26:27.000000000 +0100 @@ -96,39 +96,58 @@ * @message: the message to be logged * @uid: the UID of the user causing the message to be logged * - * Log the message to the audit subsystem. If audit is disabled, log to - * stderr instead. + * Log the message to the audit subsystem. If audit is disabled, return + * UTIL_AUDIT_E_UNAVAILABLE instead. * - * Return: 0 on success, or a negative error code on failure. + * Return: 0 on success, UTIL_AUDIT_E_UNAVAILABLE if audit is not + * available, or a negative error code on failure. */ int util_audit_log(int type, const char *message, uid_t uid) { - int r, audit_type; + int r; - switch(type) { + if (audit_fd < 0) + return UTIL_AUDIT_E_UNAVAILABLE; + + switch (type) { case UTIL_AUDIT_TYPE_AVC: - audit_type = AUDIT_USER_AVC; + r = audit_log_user_avc_message( + audit_fd, + AUDIT_USER_AVC, + message, + NULL, + NULL, + NULL, + uid + ); break; case UTIL_AUDIT_TYPE_POLICYLOAD: - audit_type = AUDIT_USER_MAC_POLICY_LOAD; + r = audit_log_user_message( + audit_fd, + AUDIT_USER_MAC_POLICY_LOAD, + message, + NULL, + NULL, + NULL, + 1 + ); break; case UTIL_AUDIT_TYPE_MAC_STATUS: - audit_type = AUDIT_USER_MAC_STATUS; + r = audit_log_user_message( + audit_fd, + AUDIT_USER_MAC_STATUS, + message, + NULL, + NULL, + NULL, + 1 + ); break; - case UTIL_AUDIT_TYPE_NOAUDIT: default: - audit_type = 0; - break; + return error_origin(-ENOTRECOVERABLE); } - if (audit_fd >= 0 && type != UTIL_AUDIT_TYPE_NOAUDIT) { - r = audit_log_user_avc_message(audit_fd, audit_type, message, NULL, NULL, NULL, uid); - if (r <= 0) - return error_origin(-errno); - } else { - r = fprintf(stderr, "%s\n", message); - if (r < 0) - return error_origin(r); - } + if (r <= 0) + return error_origin(-errno); return 0; } diff -Nru dbus-broker-36/src/util/audit-fallback.c dbus-broker-37/src/util/audit-fallback.c --- dbus-broker-36/src/util/audit-fallback.c 2024-04-12 15:07:35.000000000 +0100 +++ dbus-broker-37/src/util/audit-fallback.c 2025-06-16 13:26:27.000000000 +0100 @@ -22,13 +22,7 @@ } int util_audit_log(int type, const char *message, uid_t uid) { - int r; - - r = fprintf(stderr, "%s\n", message); - if (r < 0) - return error_origin(r); - - return 0; + return UTIL_AUDIT_E_UNAVAILABLE; } int util_audit_init_global(void) { diff -Nru dbus-broker-36/src/util/audit.h dbus-broker-37/src/util/audit.h --- dbus-broker-36/src/util/audit.h 2024-04-12 15:07:35.000000000 +0100 +++ dbus-broker-37/src/util/audit.h 2025-06-16 13:26:27.000000000 +0100 @@ -8,7 +8,12 @@ #include <stdlib.h> enum { - UTIL_AUDIT_TYPE_NOAUDIT, + _UTIL_AUDIT_E_SUCCESS, + + UTIL_AUDIT_E_UNAVAILABLE, +}; + +enum { UTIL_AUDIT_TYPE_AVC, UTIL_AUDIT_TYPE_POLICYLOAD, UTIL_AUDIT_TYPE_MAC_STATUS, diff -Nru dbus-broker-36/src/util/misc.c dbus-broker-37/src/util/misc.c --- dbus-broker-36/src/util/misc.c 2024-04-12 15:07:35.000000000 +0100 +++ dbus-broker-37/src/util/misc.c 2025-06-16 13:26:27.000000000 +0100 @@ -49,7 +49,7 @@ * Throw in `MFD_CLOEXEC` or `F_SEAL_SEAL` as required. * * * If `MFD_NOEXEC_SEAL` is used without `MFD_ALLOW_SEALING`, sealing will - * be disabled (even though the kernel implicitly enables it). + * be disabled (even though some kernel versions implicitly enable it). * * * An initial set of seals is applied to the memfd, if specified in * @seals. Note that this is not allowed if sealing was not enabled. @@ -60,6 +60,7 @@ _c_cleanup_(c_closep) int fd = -1; unsigned int flags = uflags; unsigned int seals = useals; + unsigned int kseals; struct stat st; int r; @@ -111,11 +112,11 @@ } /* - * If we ended up passing `MFG_NOEXEC_SEAL` to the kernel, the kernel - * will implicitly enable sealing. This is very unfortunate, so we - * revert this if the caller did not explicitly allow it. To disable - * sealing, simply set `F_SEAL_SEAL`, which is also what the kernel - * does. + * If we ended up passing `MFG_NOEXEC_SEAL` to the kernel, some kernel + * versions will implicitly enable sealing. This is very unfortunate, + * so we revert this if the caller did not explicitly allow it. To + * disable sealing, simply set `F_SEAL_SEAL`, which is also what the + * kernel does. */ if ((flags & MISC_MFD_NOEXEC_SEAL) && !(flags & MISC_MFD_ALLOW_SEALING)) seals |= MISC_F_SEAL_SEAL; @@ -126,9 +127,15 @@ * into the kernel again. */ if (seals) { - r = misc_memfd_add_seals(fd, seals); + r = misc_memfd_get_seals(fd, &kseals); if (r) return error_fold(r); + + if (seals & ~kseals) { + r = misc_memfd_add_seals(fd, seals); + if (r) + return error_fold(r); + } } r = fd; @@ -167,20 +174,24 @@ /** * misc_memfd_get_seals() - query seals of a memfd * @fd: memfd to operate on + * @sealsp: output argument to store retrieved seals * * Query the seals of the memfd. If the FD does not refer to a memfd (or other * file that supports sealing), an error will be returned. * - * Return: Seal mask of the memfd is returned, negative error code on failure. + * On success, the seals are written to @sealsp. + * + * Return: 0 on success, negative error code on failure. */ -int misc_memfd_get_seals(int fd) { +int misc_memfd_get_seals(int fd, unsigned int *sealsp) { int seals; seals = fcntl(fd, MISC_F_GET_SEALS); if (seals < 0) return error_origin(-errno); - return seals; + *sealsp = seals; + return 0; } /** @@ -202,6 +213,44 @@ return res; } +/** + * util_z2u_saturating() - saturating cast of size_t to unsigned int + * @v: value to cast + * + * This will cast a value of `size_t` to `unsigned int`, saturating the + * value at `UINT_MAX` in case of overflow. + * + * Return: The casted, saturated value is returned. + */ +unsigned int util_z2u_saturating(size_t v) { + unsigned int cast; + + cast = (unsigned int)v; + if ((size_t)cast != v) + return UINT_MAX; + else + return cast; +} + +/** + * util_t2u_saturating() - saturating cast of uint64_t to unsigned int + * @v: value to cast + * + * This will cast a value of `uint64_t` to `unsigned int`, saturating the + * value at `UINT_MAX` in case of overflow. + * + * Return: The casted, saturated value is returned. + */ +unsigned int util_t2u_saturating(uint64_t v) { + unsigned int cast; + + cast = (unsigned int)v; + if ((uint64_t)cast != v) + return UINT_MAX; + else + return cast; +} + int util_drop_permissions(uint32_t uid, uint32_t gid) { int r; @@ -218,3 +267,8 @@ return 0; } + +void util_peak_update(size_t *peak, size_t update) { + if (update > *peak) + *peak = update; +} diff -Nru dbus-broker-36/src/util/misc.h dbus-broker-37/src/util/misc.h --- dbus-broker-36/src/util/misc.h 2024-04-12 15:07:35.000000000 +0100 +++ dbus-broker-37/src/util/misc.h 2025-06-16 13:26:27.000000000 +0100 @@ -22,7 +22,11 @@ int misc_memfd(const char *name, unsigned int uflags, unsigned int useals); int misc_memfd_add_seals(int fd, unsigned int seals); -int misc_memfd_get_seals(int fd); +int misc_memfd_get_seals(int fd, unsigned int *sealsp); uint64_t util_umul64_saturating(uint64_t a, uint64_t b); +unsigned int util_z2u_saturating(size_t v); +unsigned int util_t2u_saturating(uint64_t v); int util_drop_permissions(uint32_t uid, uint32_t gid); + +void util_peak_update(size_t *peak, size_t update); diff -Nru dbus-broker-36/src/util/nsec.c dbus-broker-37/src/util/nsec.c --- dbus-broker-36/src/util/nsec.c 1970-01-01 01:00:00.000000000 +0100 +++ dbus-broker-37/src/util/nsec.c 2025-06-16 13:26:27.000000000 +0100 @@ -0,0 +1,85 @@ +/* + * Nanosecond Time Management + * + * This module provides time management utilities around the `nsec_t` type, + * which carries time information encoded as nano-seconds since a + * clock-specific EPOCH. The clock source is not encoded at all but must be + * transferred via other means, if necessary. + * + * A 64-bit unsigned integer is used as backing data type. This can store + * seconds up to: + * + * 2^64 / 1_000_000_000 = 18,446,744,073.7 + * + * or years up to: + * + * 2^64 / 1_000_000_000 / 60 / 60 / 24 / 365 ~= 584 + * + * This is a suitable range for time-keeping in most situations. If any + * calendar, or other date-related functionality is needed, this type might not + * be suitable. + */ + +#include <c-stdaux.h> +#include <stdlib.h> +#include <sys/time.h> +#include <time.h> +#include "util/nsec.h" + +#define NSEC_PER_SEC UINT64_C(1000000000) + +/* Similar to `intprops.h`: provides `_MAX` for signed types without it. */ +#define NSEC_TIME_T_MAX \ + ((time_t)( \ + (UINTMAX_C(1) << ((sizeof(time_t) << 3) - 1)) - 1) \ + ) + +/** + * nsec_now() - get the current time in nanoseconds + * @clock: clock to query + * + * Read the current time and return it in nanoseconds. The clock must be + * specified by the caller. Only non-fallible clocks can be used with this + * function. + * + * Return: the timestamp in nano seconds. + */ +nsec_t nsec_now(clockid_t clock) { + struct timespec ts; + int r; + + r = clock_gettime(clock, &ts); + c_assert(r >= 0); + + return (uint64_t)ts.tv_sec * NSEC_PER_SEC + (uint64_t)ts.tv_nsec; +} + +/** + * nsec_sleep() - pause execution + * @clock: clock to use for time keeping + * @until: absolute timeout of the pause + * + * Pause exeuction until the absolute timeout specified by `until` is reached. + * The timeout must be relative to the clock specified by `clock`. + * + * The operation is automatically repeated, if it is interrupted by a signal. + */ +void nsec_sleep(clockid_t clock, nsec_t until) { + struct timespec ts; + uint64_t tv_sec, tv_nsec; + int r; + + tv_sec = until / NSEC_PER_SEC; + tv_nsec = until % NSEC_PER_SEC; + + c_assert(tv_sec <= NSEC_TIME_T_MAX); + + ts.tv_sec = (time_t)tv_sec; + ts.tv_nsec = (long)tv_nsec; + + do { + /* Note that `clock_nanosleep()` does not use `errno`! */ + r = clock_nanosleep(clock, TIMER_ABSTIME, &ts, NULL); + c_assert(r == 0 || r == EINTR); + } while (r == EINTR); +} diff -Nru dbus-broker-36/src/util/nsec.h dbus-broker-37/src/util/nsec.h --- dbus-broker-36/src/util/nsec.h 1970-01-01 01:00:00.000000000 +0100 +++ dbus-broker-37/src/util/nsec.h 2025-06-16 13:26:27.000000000 +0100 @@ -0,0 +1,25 @@ +#pragma once + +/* + * Nanosecond Time Management + */ + +#include <c-stdaux.h> +#include <stdlib.h> +#include <sys/time.h> +#include <time.h> + +typedef uint64_t nsec_t; + +#define NSEC_PRI PRIu64 + +/* nsec */ + +nsec_t nsec_now(clockid_t clock); +void nsec_sleep(clockid_t clock, nsec_t until); + +/* inline helpers */ + +static inline uint64_t nsec_to_usec(nsec_t t) { + return t / 1000; +} diff -Nru dbus-broker-36/src/util/selinux.c dbus-broker-37/src/util/selinux.c --- dbus-broker-36/src/util/selinux.c 2024-04-12 15:07:35.000000000 +0100 +++ dbus-broker-37/src/util/selinux.c 2025-06-16 13:26:27.000000000 +0100 @@ -9,6 +9,7 @@ #include <stdlib.h> #include "util/audit.h" #include "util/error.h" +#include "util/log.h" #include "util/ref.h" #include "util/selinux.h" @@ -26,6 +27,7 @@ typedef struct BusSELinuxName BusSELinuxName; +static Log *bus_selinux_log = NULL; static bool bus_selinux_avc_open; static bool bus_selinux_status_open; @@ -303,10 +305,11 @@ return 0; } -static int bus_selinux_log(int type, const char *fmt, ...) { +static int bus_selinux_log_fn(int type, const char *fmt, ...) { _c_cleanup_(c_freep) char *message = NULL; + const char *loghdr = NULL; va_list ap; - int r, audit_type; + int r, loglvl = 0; va_start(ap, fmt); r = vasprintf(&message, fmt, ap); @@ -314,50 +317,91 @@ if (r < 0) return r; - switch(type) { + switch (type) { case SELINUX_AVC: - audit_type = UTIL_AUDIT_TYPE_AVC; + /* XXX: we don't have access to any context, so can't find + * the right UID to use, follow dbus-daemon(1) and use our + * own. */ + r = util_audit_log(UTIL_AUDIT_TYPE_AVC, message, getuid()); + if (r == UTIL_AUDIT_E_UNAVAILABLE) { + loghdr = "selinux/avc"; + loglvl = LOG_INFO; + } else if (r) { + return error_fold(r); + } + break; case SELINUX_POLICYLOAD: - audit_type = UTIL_AUDIT_TYPE_POLICYLOAD; + r = util_audit_log(UTIL_AUDIT_TYPE_POLICYLOAD, message, getuid()); + if (r == UTIL_AUDIT_E_UNAVAILABLE) { + loghdr = "selinux/policyload"; + loglvl = LOG_INFO; + } else if (r) { + return error_fold(r); + } + break; case SELINUX_SETENFORCE: - audit_type = UTIL_AUDIT_TYPE_MAC_STATUS; + r = util_audit_log(UTIL_AUDIT_TYPE_MAC_STATUS, message, getuid()); + if (r == UTIL_AUDIT_E_UNAVAILABLE) { + loghdr = "selinux/macstatus"; + loglvl = LOG_INFO; + } else if (r) { + return error_fold(r); + } + + break; + case SELINUX_ERROR: + loghdr = "selinux/error"; + loglvl = LOG_ERR; + break; + case SELINUX_WARNING: + loghdr = "selinux/warning"; + loglvl = LOG_WARNING; + break; + case SELINUX_INFO: + loghdr = "selinux/info"; + loglvl = LOG_INFO; break; default: - /* not an auditable message. */ - audit_type = UTIL_AUDIT_TYPE_NOAUDIT; + loghdr = "selinux/unknown"; + loglvl = LOG_WARNING; break; } - /* XXX: we don't have access to any context, so can't find - * the right UID to use, follow dbus-daemon(1) and use our - * own. */ - r = util_audit_log(audit_type, message, getuid()); - if (r) - return error_fold(r); + if (loghdr && bus_selinux_log) { + log_append_here(bus_selinux_log, loglvl, 0, NULL); + r = log_commitf(bus_selinux_log, "%s: %s", loghdr, message); + if (r) + return error_fold(r); + } return 0; } /** * bus_selinux_init_global() - initialize the global SELinux context + * @log: log object to use * * Initialize the global SELinux context. This must be called before any * other SELinux function. * * Return: 0 on success, or a negative error code on failure. */ -int bus_selinux_init_global(void) { +int bus_selinux_init_global(Log *log) { int r; if (!is_selinux_enabled()) return 0; + bus_selinux_log = log; + if (!bus_selinux_avc_open) { r = avc_open(NULL, 0); - if (r) - return error_origin(-errno); + if (r) { + r = error_origin(-errno); + goto error; + } bus_selinux_avc_open = true; } @@ -385,11 +429,15 @@ } } - selinux_set_callback(SELINUX_CB_LOG, (union selinux_callback)bus_selinux_log); + selinux_set_callback(SELINUX_CB_LOG, (union selinux_callback)bus_selinux_log_fn); /* XXX: set audit callback to get more metadata in the audit log? */ return 0; + +error: + bus_selinux_log = NULL; + return error_trace(r); } /** @@ -412,4 +460,6 @@ avc_destroy(); bus_selinux_avc_open = false; } + + bus_selinux_log = NULL; } diff -Nru dbus-broker-36/src/util/selinux-fallback.c dbus-broker-37/src/util/selinux-fallback.c --- dbus-broker-36/src/util/selinux-fallback.c 2024-04-12 15:07:35.000000000 +0100 +++ dbus-broker-37/src/util/selinux-fallback.c 2025-06-16 13:26:27.000000000 +0100 @@ -53,7 +53,7 @@ return 0; } -int bus_selinux_init_global(void) { +int bus_selinux_init_global(Log *log) { return 0; } diff -Nru dbus-broker-36/src/util/selinux.h dbus-broker-37/src/util/selinux.h --- dbus-broker-36/src/util/selinux.h 2024-04-12 15:07:35.000000000 +0100 +++ dbus-broker-37/src/util/selinux.h 2025-06-16 13:26:27.000000000 +0100 @@ -8,6 +8,7 @@ #include <stdlib.h> typedef struct BusSELinuxRegistry BusSELinuxRegistry; +typedef struct Log Log; enum { _SELINUX_E_SUCCESS, @@ -34,5 +35,5 @@ const char *context_sender, const char *context_receiver); -int bus_selinux_init_global(void); +int bus_selinux_init_global(Log *log); void bus_selinux_deinit_global(void); diff -Nru dbus-broker-36/src/util/sockopt.c dbus-broker-37/src/util/sockopt.c --- dbus-broker-36/src/util/sockopt.c 2024-04-12 15:07:35.000000000 +0100 +++ dbus-broker-37/src/util/sockopt.c 2025-06-16 13:26:27.000000000 +0100 @@ -238,7 +238,7 @@ return SOCKOPT_E_UNSUPPORTED; if (errno == ENODATA) return SOCKOPT_E_UNAVAILABLE; - if (errno == EINVAL) + if (errno == EINVAL || errno == ESRCH) return SOCKOPT_E_REAPED; return error_origin(-errno); diff -Nru dbus-broker-36/src/util/string.h dbus-broker-37/src/util/string.h --- dbus-broker-36/src/util/string.h 2024-04-12 15:07:35.000000000 +0100 +++ dbus-broker-37/src/util/string.h 2025-06-16 13:26:27.000000000 +0100 @@ -78,7 +78,8 @@ * destination buffer must be at least twice as big as the source. */ static inline void string_to_hex(const char *str, size_t n, char *hex) { - static const char table[16] = "0123456789abcdef"; + // Include terminating NUL to silence warnings about truncated strings. + static const char table[17] = "0123456789abcdef"; size_t i; for (i = 0; i < n; ++i) { diff -Nru dbus-broker-36/src/util/systemd.c dbus-broker-37/src/util/systemd.c --- dbus-broker-36/src/util/systemd.c 2024-04-12 15:07:35.000000000 +0100 +++ dbus-broker-37/src/util/systemd.c 2025-06-16 13:26:27.000000000 +0100 @@ -15,7 +15,8 @@ } static char *escape_char(char *t, char c) { - static const char table[16] = "0123456789abcdef"; + // Include terminating NUL to silence warnings about truncated strings. + static const char table[17] = "0123456789abcdef"; *t++ = '\\'; *t++ = 'x'; diff -Nru dbus-broker-36/src/util/test-misc.c dbus-broker-37/src/util/test-misc.c --- dbus-broker-36/src/util/test-misc.c 2024-04-12 15:07:35.000000000 +0100 +++ dbus-broker-37/src/util/test-misc.c 2025-06-16 13:26:27.000000000 +0100 @@ -87,10 +87,10 @@ .out_fmode = 0666, }, }; - unsigned int seal_mask; + unsigned int seals, seal_mask; struct stat st; size_t i; - int r, fd, seals; + int r, fd; seal_mask = memfd_seals(); @@ -104,8 +104,8 @@ } c_assert(!v[i].out_error); - seals = misc_memfd_get_seals(fd); - c_assert(seals >= 0); + r = misc_memfd_get_seals(fd, &seals); + c_assert(r >= 0); c_assert((seals & seal_mask) == (v[i].out_seals & seal_mask)); r = fstat(fd, &st); @@ -144,8 +144,53 @@ } } +static void test_casts(void) { + static const struct { + size_t from; + unsigned int to; + } casts_z2u_sat[] = { + { 0, 0 }, + { 32, 32 }, + { 256, 256 }, + { SIZE_MAX, UINT_MAX }, +#if SIZE_MAX > UINT_MAX + { (size_t)UINT_MAX, UINT_MAX }, + { (size_t)UINT_MAX + 1, UINT_MAX }, + { (size_t)UINT_MAX * 2, UINT_MAX }, +#endif + }; + static const struct { + uint64_t from; + unsigned int to; + } casts_t2u_sat[] = { + { 0, 0 }, + { 32, 32 }, + { 256, 256 }, + { (uint64_t)UINT_MAX, UINT_MAX }, + { (uint64_t)UINT_MAX + 1, UINT_MAX }, + { (uint64_t)UINT_MAX * 2, UINT_MAX }, + { UINT64_MAX, UINT_MAX }, + }; + size_t i; + + for (i = 0; i < C_ARRAY_SIZE(casts_z2u_sat); ++i) { + unsigned int r; + + r = util_z2u_saturating(casts_z2u_sat[i].from); + c_assert(r == casts_z2u_sat[i].to); + } + + for (i = 0; i < C_ARRAY_SIZE(casts_t2u_sat); ++i) { + unsigned int r; + + r = util_t2u_saturating(casts_t2u_sat[i].from); + c_assert(r == casts_t2u_sat[i].to); + } +} + int main(int argc, char **argv) { test_memfd(); test_umul_saturating(); + test_casts(); return 0; } diff -Nru dbus-broker-36/src/util/test-nsec.c dbus-broker-37/src/util/test-nsec.c --- dbus-broker-36/src/util/test-nsec.c 1970-01-01 01:00:00.000000000 +0100 +++ dbus-broker-37/src/util/test-nsec.c 2025-06-16 13:26:27.000000000 +0100 @@ -0,0 +1,28 @@ +/* + * Test nanosecond time management + */ + +#undef NDEBUG +#include <c-stdaux.h> +#include <stdlib.h> +#include "util/nsec.h" + +static void test_nsec(void) { + nsec_t n0, n1, n2; + + n0 = nsec_now(CLOCK_MONOTONIC); + c_assert(n0 > 0); + + n1 = n0 + 8000; + nsec_sleep(CLOCK_MONOTONIC, n1); + + n2 = nsec_now(CLOCK_MONOTONIC); + c_assert(n2 > 0); + c_assert(n2 > n0); + c_assert(n2 - n0 >= 8000); +} + +int main(int argc, char **argv) { + test_nsec(); + return 0; +} diff -Nru dbus-broker-36/subprojects/libcdvar-1/meson.build dbus-broker-37/subprojects/libcdvar-1/meson.build --- dbus-broker-36/subprojects/libcdvar-1/meson.build 2023-12-18 12:17:27.000000000 +0000 +++ dbus-broker-37/subprojects/libcdvar-1/meson.build 2025-06-16 10:15:36.000000000 +0100 @@ -6,7 +6,7 @@ ], license: 'Apache', meson_version: '>=0.60.0', - version: '1.1.0', + version: '1.2.0', ) major = meson.project_version().split('.')[0] project_description = 'D-Bus Variant Type-System' diff -Nru dbus-broker-36/subprojects/libcdvar-1/NEWS.md dbus-broker-37/subprojects/libcdvar-1/NEWS.md --- dbus-broker-36/subprojects/libcdvar-1/NEWS.md 2023-12-18 12:17:27.000000000 +0000 +++ dbus-broker-37/subprojects/libcdvar-1/NEWS.md 2025-06-16 10:15:36.000000000 +0100 @@ -1,5 +1,14 @@ # c-dvar - D-Bus Variant Type-System +## CHANGES WITH 1.2.0: + + * Fix the variant-reader to use aliasing-safe accessors. This allows + parallel use of the variant-buffers with possibly aliasing pointers. + + Contributions from: David Rheinsberg, Kostadin Shishmanov + + - Dußlingen, 2025-06-16 + ## CHANGES WITH 1.1.0: * Update the c-stdaux dependency to provide the new build variables diff -Nru dbus-broker-36/subprojects/libclist-3/.github/workflows/ci.yml dbus-broker-37/subprojects/libclist-3/.github/workflows/ci.yml --- dbus-broker-36/subprojects/libclist-3/.github/workflows/ci.yml 2022-06-22 11:05:20.000000000 +0100 +++ dbus-broker-37/subprojects/libclist-3/.github/workflows/ci.yml 2022-07-07 13:07:43.000000000 +0100 @@ -7,38 +7,26 @@ - cron: '0 0 * * *' jobs: - ci: - name: CI with Default Configuration + ci-linux: + name: Linux CI uses: bus1/cabuild/.github/workflows/ci-c-util.yml@v1 with: cabuild_ref: "v1" + linux: true m32: true matrixmode: true valgrind: true - - ci-msvc: - name: CI with MSVC - runs-on: ${{ matrix.os }} - strategy: - matrix: - os: [windows-2019, windows-latest] - - steps: - - name: Fetch Sources - uses: actions/checkout@v2 - - name: Setup Python - uses: actions/setup-python@v2 - with: - python-version: '3.x' - - name: Install Python Dependencies - run: pip install meson ninja - - name: Prepare MSVC - uses: bus1/cabuild/action/msdevshell@v1 - with: - architecture: x64 - - name: Prepare Build - run: meson setup build - - name: Run Build - run: meson compile -v -C build - - name: Run Test Suite - run: meson test -v -C build + ci-macos: + name: MacOS CI + uses: bus1/cabuild/.github/workflows/ci-c-util.yml@v1 + with: + cabuild_ref: "v1" + linux: false + macos: true + ci-windows: + name: Windows CI + uses: bus1/cabuild/.github/workflows/ci-c-util.yml@v1 + with: + cabuild_ref: "v1" + linux: false + windows: true diff -Nru dbus-broker-36/subprojects/libcstdaux-1/meson.build dbus-broker-37/subprojects/libcstdaux-1/meson.build --- dbus-broker-36/subprojects/libcstdaux-1/meson.build 2024-01-10 12:46:38.000000000 +0000 +++ dbus-broker-37/subprojects/libcstdaux-1/meson.build 2025-06-16 10:09:11.000000000 +0100 @@ -10,7 +10,7 @@ ], license: 'Apache', meson_version: '>=0.60.0', - version: '1.5.0', + version: '1.6.0', ) major = meson.project_version().split('.')[0] project_description = 'Auxiliary macros and functions for the C standard library' diff -Nru dbus-broker-36/subprojects/libcstdaux-1/NEWS.md dbus-broker-37/subprojects/libcstdaux-1/NEWS.md --- dbus-broker-36/subprojects/libcstdaux-1/NEWS.md 2024-01-10 12:46:38.000000000 +0000 +++ dbus-broker-37/subprojects/libcstdaux-1/NEWS.md 2025-06-16 10:09:11.000000000 +0100 @@ -1,5 +1,14 @@ # c-stdaux - Auxiliary macros and functions for the C standard library +## CHANGES WITH 1.6.0: + + * Multiple fixes to the test-suite, which fix differences in the + optimizations performed by GCC and clang. + + Contributions from: David Rheinsberg, ms178, Nikita Popov + + - Dußlingen, 2025-06-16 + ## CHANGES WITH 1.5.0: * Change the meson variable exports to avoid dashes in variable names, diff -Nru dbus-broker-36/subprojects/libcstdaux-1/src/test-basic.c dbus-broker-37/subprojects/libcstdaux-1/src/test-basic.c --- dbus-broker-36/subprojects/libcstdaux-1/src/test-basic.c 2024-01-10 12:46:38.000000000 +0000 +++ dbus-broker-37/subprojects/libcstdaux-1/src/test-basic.c 2025-06-16 10:09:11.000000000 +0100 @@ -503,7 +503,7 @@ c_assert(foo == 11); c_assert(__builtin_constant_p(c_div_round_up(1, 5))); - c_assert(!__builtin_constant_p(c_div_round_up(1, non_constant_expr))); + c_assert(!__builtin_constant_p(c_div_round_up(8, 1 + !non_constant_expr))); /* alternative calculation is [(x + y - 1) / y], but it may overflow */ for (i = 0; i <= 0xffff; ++i) { diff -Nru dbus-broker-36/test/dbus/test-driver.c dbus-broker-37/test/dbus/test-driver.c --- dbus-broker-36/test/dbus/test-driver.c 2024-04-12 15:07:35.000000000 +0100 +++ dbus-broker-37/test/dbus/test-driver.c 2025-06-16 13:26:27.000000000 +0100 @@ -2581,6 +2581,23 @@ r = sd_bus_message_exit_container(reply); c_assert(r >= 0); + } else if (strcmp(stat, "Serial") == 0 || + strcmp(stat, "ActiveConnections") == 0 || + strcmp(stat, "IncompleteConnections") == 0 || + strcmp(stat, "BusNames") == 0 || + strcmp(stat, "PeakBusNames") == 0 || + strcmp(stat, "PeakBusNamesPerConnection") == 0 || + strcmp(stat, "MatchRules") == 0 || + strcmp(stat, "PeakMatchRules") == 0 || + strcmp(stat, "PeakMatchRulesPerConnection") == 0) { + r = sd_bus_message_enter_container(reply, 'v', "u"); + c_assert(r >= 0); + + r = sd_bus_message_skip(reply, "u"); + c_assert(r >= 0); + + r = sd_bus_message_exit_container(reply); + c_assert(r >= 0); } else { r = sd_bus_message_skip(reply, "v"); c_assert(r >= 0); diff -Nru dbus-broker-36/test/dbus/test-matches.c dbus-broker-37/test/dbus/test-matches.c --- dbus-broker-36/test/dbus/test-matches.c 2024-04-12 15:07:35.000000000 +0100 +++ dbus-broker-37/test/dbus/test-matches.c 2025-06-16 13:26:27.000000000 +0100 @@ -258,6 +258,154 @@ util_broker_terminate(broker); } +static void test_arg(void) { + _c_cleanup_(util_broker_freep) Broker *broker = NULL; + _c_cleanup_(sd_bus_flush_close_unrefp) sd_bus *sender = NULL; + _c_cleanup_(sd_bus_flush_close_unrefp) sd_bus *receiver = NULL; + int r; + + util_broker_new(&broker); + util_broker_spawn(broker); + + util_broker_connect(broker, &sender); + util_broker_connect(broker, &receiver); + + r = sd_bus_call_method(receiver, "org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus", + "AddMatch", NULL, NULL, + "s", "arg3='done'"); + c_assert(r >= 0); + + /* does not match: not a string */ + r = sd_bus_emit_signal(sender, "/org/example", "org.example", "DoesNotMatch", "iiii", 0, 0, 0, 0); + c_assert(r >= 0); + + /* does not match: wrong value */ + r = sd_bus_emit_signal(sender, "/org/example", "org.example", "DoesNotMatch", "iiis", 0, 0, 0, "failed"); + c_assert(r >= 0); + + /* does not match: correct value in the wrong arguments */ + r = sd_bus_emit_signal(sender, "/org/example", "org.example", "DoesNotMatch", "sssss", + "done", "done", "done", "failed", "done"); + c_assert(r >= 0); + + r = sd_bus_emit_signal(sender, "/org/example", "org.example", "Matches", "iiis", 0, 0, 0, "done"); + c_assert(r >= 0); + + util_broker_consume_signal(receiver, "org.example", "Matches"); + + util_broker_terminate(broker); +} + +static void test_args(void) { + _c_cleanup_(util_broker_freep) Broker *broker = NULL; + _c_cleanup_(sd_bus_flush_close_unrefp) sd_bus *sender = NULL; + _c_cleanup_(sd_bus_flush_close_unrefp) sd_bus *receiver = NULL; + int r; + + util_broker_new(&broker); + util_broker_spawn(broker); + + util_broker_connect(broker, &sender); + util_broker_connect(broker, &receiver); + + r = sd_bus_call_method(receiver, "org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus", + "AddMatch", NULL, NULL, + "s", "arg0='zero',arg1='one'"); + c_assert(r >= 0); + + /* does not match: too few arguments */ + r = sd_bus_emit_signal(sender, "/org/example", "org.example", "DoesNotMatch", "s", "zero"); + c_assert(r >= 0); + + /* does not match: one arg not a string */ + r = sd_bus_emit_signal(sender, "/org/example", "org.example", "DoesNotMatch", "si", "zero", 0); + c_assert(r >= 0); + r = sd_bus_emit_signal(sender, "/org/example", "org.example", "DoesNotMatch", "is", 0, "one"); + c_assert(r >= 0); + + /* does not match: incorrect value for one argument */ + r = sd_bus_emit_signal(sender, "/org/example", "org.example", "DoesNotMatch", "ss", "zero", "wrong"); + c_assert(r >= 0); + r = sd_bus_emit_signal(sender, "/org/example", "org.example", "DoesNotMatch", "ss", "wrong", "one"); + c_assert(r >= 0); + + /* does not match: correct values in the wrong arguments */ + r = sd_bus_emit_signal(sender, "/org/example", "org.example", "DoesNotMatch", "ss", "one", "zero"); + c_assert(r >= 0); + + r = sd_bus_emit_signal(sender, "/org/example", "org.example", "Matches", "ss", "zero", "one"); + c_assert(r >= 0); + + util_broker_consume_signal(receiver, "org.example", "Matches"); + + util_broker_terminate(broker); +} + +static void test_argpath(void) { + _c_cleanup_(util_broker_freep) Broker *broker = NULL; + _c_cleanup_(sd_bus_flush_close_unrefp) sd_bus *sender = NULL; + _c_cleanup_(sd_bus_flush_close_unrefp) sd_bus *receiver = NULL; + int r; + + util_broker_new(&broker); + util_broker_spawn(broker); + + util_broker_connect(broker, &sender); + util_broker_connect(broker, &receiver); + + /* example match rule, matches and nonmatches from D-Bus specification */ + r = sd_bus_call_method(receiver, "org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus", + "AddMatch", NULL, NULL, + "s", "arg1path='/aa/bb/'"); + c_assert(r >= 0); + + /* does not match: arg not a string or object path */ + r = sd_bus_emit_signal(sender, "/org/example", "org.example", "DoesNotMatch", "si", "foo", 0); + c_assert(r >= 0); + + /* does not match: incorrect value */ + r = sd_bus_emit_signal(sender, "/org/example", "org.example", "DoesNotMatch", "ss", "foo", "/aa/b"); + c_assert(r >= 0); + r = sd_bus_emit_signal(sender, "/org/example", "org.example", "DoesNotMatch", "ss", "foo", "/aa"); + c_assert(r >= 0); + r = sd_bus_emit_signal(sender, "/org/example", "org.example", "DoesNotMatch", "ss", "foo", "/aa/bb"); + c_assert(r >= 0); + + /* does not match: correct value in the wrong argument */ + r = sd_bus_emit_signal(sender, "/org/example", "org.example", "DoesNotMatch", "ss", "/aa/bb/", "foo"); + c_assert(r >= 0); + + r = sd_bus_emit_signal(sender, "/org/example", "org.example", "Matches", "ss", "foo", "/"); + c_assert(r >= 0); + util_broker_consume_signal(receiver, "org.example", "Matches"); + + r = sd_bus_emit_signal(sender, "/org/example", "org.example", "Matches", "ss", "foo", "/aa/"); + c_assert(r >= 0); + util_broker_consume_signal(receiver, "org.example", "Matches"); + + r = sd_bus_emit_signal(sender, "/org/example", "org.example", "Matches", "ss", "foo", "/aa/bb/"); + c_assert(r >= 0); + util_broker_consume_signal(receiver, "org.example", "Matches"); + + r = sd_bus_emit_signal(sender, "/org/example", "org.example", "Matches", "ss", "foo", "/aa/bb/cc/"); + c_assert(r >= 0); + util_broker_consume_signal(receiver, "org.example", "Matches"); + + r = sd_bus_emit_signal(sender, "/org/example", "org.example", "Matches", "ss", "foo", "/aa/bb/cc"); + c_assert(r >= 0); + util_broker_consume_signal(receiver, "org.example", "Matches"); + + r = sd_bus_emit_signal(sender, "/org/example", "org.example", "Matches", "so", "foo", "/"); + c_assert(r >= 0); + util_broker_consume_signal(receiver, "org.example", "Matches"); + + r = sd_bus_emit_signal(sender, "/org/example", "org.example", "Matches", "so", "foo", "/aa/bb/cc"); + c_assert(r >= 0); + util_broker_consume_signal(receiver, "org.example", "Matches"); + + util_broker_terminate(broker); +} + int main(int argc, char **argv) { test_wildcard(); test_unique_name(); @@ -267,4 +415,7 @@ test_noc_unique(); test_noc_well_known(); test_noc_driver(); + test_arg(); + test_args(); + test_argpath(); }
Attachment:
signature.asc
Description: This is a digitally signed message part