Files
finit/test/dbus-authz.sh
T
Joachim Wiberg 63aabaa6df libink/dbus: identify the caller behind a broker
On the local bus SO_PEERCRED says who is calling and the kernel is the
one saying it.  Behind a broker one connection carries every caller,
so that credential describes dbus-daemon and nothing else, and every
privileged method was refused there, root included.

Ask the bus driver instead.  libink parks the call and hands us the
sender; we ask GetConnectionUnixUser and answer when the reply lands,
through the same event loop as everything else.  Nothing blocks:
blocking in PID 1 is why libuEv exists.  That needs calls libink can
make on a connection it already has, so it gained those too.

Answers are cached, since a bus never reuses a unique name while it
runs.  Not across a restart though: a new dbus-daemon numbers from
scratch and :1.7 becomes somebody else, so the cache goes when the
broker does.  A sender name too long to key on is refused rather than
truncated, two callers sharing a truncated key would share an
identity.

Privilege is no longer uid 0 alone.  The socket is already owned by
the --with-group group, so refusing its members every method that
changes anything left a wheel user able to open the bus and unable to
reboot.  Both gates now say the same thing.

Group membership needs NSS, which the C library loads with dlopen(),
so the lookup is compiled out where Finit is built to link statically.
That leaves such a build root-only, which is worth saying out loud
rather than leaving to be discovered.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-08-13 10:15:06 +02:00

53 lines
1.8 KiB
Bash
Executable File

#!/bin/sh
# Who may invoke a privileged method. Root always, and anyone in the
# group the bus socket is owned by, which is DEFGROUP from
# --with-group, 'root' in a test build. Everyone else is refused.
#
# A caller that gets past the check still has to name a service that
# exists, so NoSuchService is how we tell "allowed, then failed" apart
# from "not allowed at all".
set -eu
TEST_DIR=$(dirname "$0")
# shellcheck source=/dev/null
. "$TEST_DIR/lib/setup.sh"
# shellcheck source=/dev/null
. "$TEST_DIR/lib/dbus-setup.sh"
# uid 1000 is 'wheelie', a member of group root in the test sysroot.
# uid 2 is 'bin', a member of nothing that matters here.
say "A member of the group may call a privileged method"
set +e
allowed=$(texec "$CLIENT" call-s-as-uid 1000 "$BUS" /org/finit/manager \
org.finit.Manager1 Restart nosuchservice 2>&1)
set -e
case "$allowed" in
*AccessDenied*) fail "Group member was refused: $allowed" ;;
*NoSuchService*) assert "Group member passed authorization" 0 -eq 0 ;;
*) fail "Unexpected reply for group member: $allowed" ;;
esac
say "A caller outside the group may not"
set +e
denied=$(texec "$CLIENT" call-s-as-uid 2 "$BUS" /org/finit/manager \
org.finit.Manager1 Restart nosuchservice 2>&1)
set -e
case "$denied" in
*AccessDenied*) assert "Non-member refused" 0 -eq 0 ;;
*NoSuchService*) fail "Non-member passed authorization: $denied" ;;
*) fail "Unexpected reply for non-member: $denied" ;;
esac
say "Root is still allowed"
set +e
asroot=$(texec "$CLIENT" call-s "$BUS" /org/finit/manager \
org.finit.Manager1 Restart nosuchservice 2>&1)
set -e
case "$asroot" in
*AccessDenied*) fail "Root was refused: $asroot" ;;
*NoSuchService*) assert "Root passed authorization" 0 -eq 0 ;;
*) fail "Unexpected reply for root: $asroot" ;;
esac