mirror of
https://github.com/troglobit/finit.git
synced 2026-09-30 21:13:01 +07:00
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>
97 lines
3.5 KiB
Bash
Executable File
97 lines
3.5 KiB
Bash
Executable File
#!/bin/sh
|
|
# libink: org.finit.Service1 vtable + ServiceStateChanged signal.
|
|
#
|
|
# Covers per-service objects exposed at /org/finit/service/<encoded>:
|
|
# GetService lookup, Introspect on a service object, Service1
|
|
# properties via Properties.Get, Service1.Restart, authorization
|
|
# (non-root rejected), and the Manager1.ServiceStateChanged signal
|
|
# that Service1.Restart triggers.
|
|
|
|
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"
|
|
|
|
say "Manager1.GetService(keventd) returns the encoded object path"
|
|
path=$(texec "$CLIENT" get-service "$BUS" keventd)
|
|
expected="/org/finit/service/keventd"
|
|
assert "GetService returned expected path (got: $path)" "$path" = "$expected"
|
|
|
|
say "Introspect on the service object exposes Service1 methods"
|
|
xml=$(texec "$CLIENT" introspect "$BUS" /org/finit/service/keventd)
|
|
case "$xml" in
|
|
*'org.finit.Service1'*'Restart'*)
|
|
assert "Service1.Restart visible in service-object XML" 0 -eq 0 ;;
|
|
*)
|
|
fail "Service1 not visible on /org/finit/service/keventd: $xml" ;;
|
|
esac
|
|
|
|
say "Service1 properties: Identity, State, Pid"
|
|
ident=$(texec "$CLIENT" getprop "$BUS" /org/finit/service/keventd \
|
|
org.finit.Service1 Identity)
|
|
assert "Identity is keventd (got: $ident)" "$ident" = "keventd"
|
|
|
|
state=$(texec "$CLIENT" getprop "$BUS" /org/finit/service/keventd \
|
|
org.finit.Service1 State)
|
|
assert "State is running (got: $state)" "$state" = "running"
|
|
|
|
pid=$(texec "$CLIENT" getprop "$BUS" /org/finit/service/keventd \
|
|
org.finit.Service1 Pid)
|
|
assert "Pid is non-zero (got: $pid)" "$pid" -gt 0
|
|
|
|
say "Service1 properties are advertised in introspection XML"
|
|
case "$xml" in
|
|
*'<property name="Identity" type="s"'*'<property name="Pid" type="u"'*)
|
|
assert "Identity and Pid declared with types" 0 -eq 0 ;;
|
|
*)
|
|
fail "Property declarations missing from service XML" ;;
|
|
esac
|
|
|
|
say "Service1.Restart on /org/finit/service/keventd succeeds"
|
|
texec "$CLIENT" call-void "$BUS" /org/finit/service/keventd \
|
|
org.finit.Service1 Restart >/dev/null \
|
|
|| fail "Service1.Restart returned non-zero"
|
|
assert "Per-service Restart ok" 0 -eq 0
|
|
|
|
# See dbus-manager.sh: widen the test socket so a non-member reaches
|
|
# the method-level authz behind the 0660 gate.
|
|
bus_open_to_all
|
|
say "Service1.Restart from non-root is rejected with AccessDenied"
|
|
set +e
|
|
texec "$CLIENT" call-void-as-uid 1 "$BUS" /org/finit/service/keventd \
|
|
org.finit.Service1 Restart >/tmp/dbus-svcauthz.out 2>&1
|
|
svc_authz_rc=$?
|
|
set -e
|
|
assert "Non-root Service1.Restart rejected (rc=$svc_authz_rc)" \
|
|
"$svc_authz_rc" -eq 1
|
|
case "$(cat /tmp/dbus-svcauthz.out)" in
|
|
*AccessDenied*) assert "Service1 authz fires" 0 -eq 0 ;;
|
|
*) fail "Expected AccessDenied, got: $(cat /tmp/dbus-svcauthz.out)" ;;
|
|
esac
|
|
|
|
say "Service1.Restart fires Manager1.ServiceStateChanged"
|
|
rm -f /tmp/dbus-sig.out
|
|
( texec "$CLIENT" monitor-signal "$BUS" \
|
|
"type='signal',interface='org.finit.Manager1',member='ServiceStateChanged'" \
|
|
5000 > /tmp/dbus-sig.out 2>&1 ) &
|
|
mon_pid=$!
|
|
sleep 0.5
|
|
texec "$CLIENT" call-void "$BUS" /org/finit/service/keventd \
|
|
org.finit.Service1 Restart >/dev/null \
|
|
|| fail "Restart trigger returned non-zero"
|
|
set +e
|
|
wait "$mon_pid"
|
|
mon_rc=$?
|
|
set -e
|
|
assert "monitor saw a signal (rc=$mon_rc)" "$mon_rc" -eq 0
|
|
case "$(cat /tmp/dbus-sig.out)" in
|
|
*"SIGNAL org.finit.Manager1 ServiceStateChanged"*keventd*)
|
|
assert "Signal payload contains the keventd identity" 0 -eq 0 ;;
|
|
*)
|
|
fail "Unexpected signal output: $(cat /tmp/dbus-sig.out)" ;;
|
|
esac
|