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