mirror of
https://github.com/troglobit/finit.git
synced 2026-11-06 15:51:03 +00:00
dbus: fixes from a code review of the branch
A pass over the whole branch before merge, mostly in libink since that is the new code and the part exposed to the wire. Grouped here rather than scattered so the review is easy to read in one place. libink parser and dispatch: - Bound reader lengths so a 32-bit size_t can't wrap a wire length past the guard and read out of bounds. Reachable pre-auth on any bus, so it matters on the 32-bit targets Finit runs on. - Drop a peer when a reply send fails instead of limping on with a half-written frame; a built-in whose send failed used to fall through and put a second frame on the wire. initctl: - Copy a D-Bus error name out of the reply before closing the client; the reply points into memory the close frees. Both error paths now share one helper so this can't creep back. Authorization: - Take the caller's groups from the kernel (SO_PEERCRED plus SO_PEERGROUPS) rather than getpwuid()/getgrouplist(), which go through NSS and can block PID 1 on a slow LDAP or SSSD backend. The check is now a lookup against the group resolved once at init, with no NSS and no 256 KiB array on the stack. A caller reaching us through a broker carries no group set, so system-bus privileged methods are root-only; the local bus keeps group support. See libink/README.md for the note on lifting that. Shutdown: - Call dbus_exit() from the shutdown path so the server, its peers, and the socket are let go cleanly. The teardown existed but nobody called it. Tests, CI, docs: - A fuzz target for the message parser, run as a quick sweep in the suite and properly under libFuzzer in CI, with the corpus carried between runs. The -as-uid tests drop groups the way a login does so SO_PEERGROUPS sees the right set, and widen the test socket to reach the per-method check behind the 0660 gate. Bring the GitHub actions up to versions that run on Node 24, and tidy a few small things a /simplify pass turned up. Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This commit is contained in:
1 parent
e62b463852
commit
3231ade38a
24 files changed
+266
-108
No files matched your search
+7
-2
@@ -56,8 +56,13 @@ All relevant changes are documented in this file.
|
||||
`List`, `Dump` for [user-defined conditions](conditions.md),
|
||||
with a `ConditionChanged (ss)` signal.
|
||||
|
||||
Privileged methods reject non-root callers based on the kernel-
|
||||
authenticated peer uid (`SO_PEERCRED`); read-only methods are open.
|
||||
Privileged methods accept root and members of the `--with-group`
|
||||
group; everyone else is refused. On the local bus the caller's uid
|
||||
and groups come straight from the kernel (`SO_PEERCRED` +
|
||||
`SO_PEERGROUPS`), so the check never blocks PID 1 on an NSS lookup.
|
||||
Over the system bus the uid is resolved from the broker
|
||||
(`GetConnectionUnixUser`) and privileged methods are root-only.
|
||||
Read-only methods are open.
|
||||
See [D-Bus Integration](dbus.md) for the full surface, build flag,
|
||||
and `dbus-send`/`dbus-monitor` examples.
|
||||
|
||||
|
||||
+1
-2
@@ -44,8 +44,7 @@ Below are a few of the main switches to configure:
|
||||
|
||||
* `--enable-static`: Build Finit statically. The plugins will be
|
||||
built-ins (.o files) and all external libraries, except the C library
|
||||
will be linked statically. Privileged D-Bus methods then accept only
|
||||
`root`, see [Authorization](dbus.md#authorization)
|
||||
will be linked statically.
|
||||
|
||||
* `--enable-kernel-cmdline`: Enable Finit pre-4.1 parsing of init args from
|
||||
`/proc/cmdline`, this is *not recommended* since Finit may be running as the
|
||||
|
||||
+14
-14
@@ -209,22 +209,22 @@ to `--with-group` at build time. That is the same set the socket mode already
|
||||
admits, so the two gates agree instead of the socket letting the group in and
|
||||
every method turning it away.
|
||||
|
||||
A build configured with `--enable-static` accepts only `root`. Group
|
||||
membership comes from NSS, which the C library loads with `dlopen()`, and a
|
||||
build meant to link statically cannot count on that, so the lookup is compiled
|
||||
out rather than left to fail open. The socket mode is unchanged, so the group
|
||||
can still connect, it just cannot invoke a privileged method.
|
||||
|
||||
On the **local** bus the kernel decides this at `connect()`, supplementary
|
||||
groups included, and `SO_PEERCRED` tells Finit exactly who is calling, so
|
||||
privilege escalation through the bus is impossible.
|
||||
On the **local** bus the kernel settles this at `connect()`: `SO_PEERCRED`
|
||||
gives Finit the caller's uid and `SO_PEERGROUPS` its group set, both straight
|
||||
from the kernel. Finit matches the group against `--with-group` itself, so
|
||||
the check never touches NSS -- `getpwuid`/`getgrouplist` can block on a slow
|
||||
LDAP or SSSD backend, and PID 1 must never block. Because the group set is
|
||||
the caller's real credentials, privilege escalation through the bus is
|
||||
impossible.
|
||||
|
||||
On the **system** bus one connection carries every caller, so `SO_PEERCRED`
|
||||
describes `dbus-daemon` rather than whoever asked. For a privileged method
|
||||
Finit asks the bus driver `GetConnectionUnixUser` about the message sender and
|
||||
holds the call until the answer arrives. Nothing blocks: the reply comes back
|
||||
through the same event loop as everything else, and the held call is then
|
||||
dispatched or refused on its merits.
|
||||
describes `dbus-daemon` rather than whoever asked. Finit asks the bus driver
|
||||
`GetConnectionUnixUser` about the message sender and holds the call until the
|
||||
answer arrives -- nothing blocks, the reply comes back through the same event
|
||||
loop as everything else. The broker does not report the caller's groups in
|
||||
that reply, so **privileged methods over the system bus are root-only**; group
|
||||
membership is honoured on the local bus only. Lifting that is future work,
|
||||
see `libink/README.md`.
|
||||
|
||||
Answers are cached per sender. A bus never reuses a unique name while it
|
||||
runs, so an answer holds for as long as that bus does; Finit empties the cache
|
||||
|
||||
Reference in new issue
Block a user