-
protocol7-core-5.5.3-24 Stable
released this
2026-07-15 04:38:10 +02:00 | 4 commits to main since this releaseprotocol7-core-5.5.3-24 ~ Changelog
Note: The three hardening techniques addressed in this release ~ restricting allowed socket address families, preventing ASLR-personality changes, and restricting namespace creation ~ were prompted by reviewing how Whonix/Kicksecure hardens its own systemd services (
RestrictAddressFamilies,LockPersonality,RestrictNamespaces), and manually reimplementing those same protections in protocol7-core's daemons via libseccomp, since there's no systemd here to enforce them through a config directive.
Security Hardening (
lainos-dbus-bridge)- Added a redundant, defense-in-depth caller-identity check to
Reboot/PowerOffD-Bus methods via manual, logic-focused code review (conducted 2026-07-09, a category of review distinct from fuzzing/memory-safety testing). The D-Bus system bus's default<policy context="default">allowssend_destinationfrom any local process with no UID restriction, so this check adds an explicit authorization layer at the application level. In practice, this was never exploitable: the daemon runs asnobodyafter privilege drop, andopenrc-shutdownitself refuses to run without root regardless of caller ~ so the missing check never allowed an actual reboot/poweroff. The fix closes the gap at an earlier point in the call chain rather than relying solely on that downstream protection. - Fix: added an explicit caller-UID check before the fork, using
dbus_bus_get_unix_user()to resolve the sender's real UID via the trusted bus daemon, rejecting any caller that is neither the active session user nor root with a properorg.freedesktop.DBus.Error.AccessDeniedreply. - Seccomp interaction:
dbus_bus_get_unix_user()requires libdbus's internal blocking-call machinery, which invokesclone(). Addedcloneto the seccomp whitelist, scoped viaSCMP_CMP_MASKED_EQto the specificCLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREADflag pattern libdbus's worker-thread creation uses, rather than an unconditional allow. - Scope note: this review covered
lainos-dbus-bridgeonly.Reboot/PowerOffare the only two Manager-interface methods with real, irreversible system-level effects; all other action methods either have no real effect (Suspendis a documented no-op,Hibernate/HybridSleepreturnNotSupported) or are read-only. Session/User-interface methods (Lock,Unlock,Terminate, etc.) are not implemented inhandle_method()at all and correctly returnUnknownInterface.
Security Hardening (
lainos-notifydandlainos-dbus-bridge)- Restricted
socket()toAF_UNIXonly, via seccomp argument filtering (SCMP_CMP(0, SCMP_CMP_EQ, AF_UNIX)). Both daemons only ever communicate over Unix domain sockets (/run/systemd/notifyfor notifyd, the D-Bus system bus for dbus-bridge); this closes offAF_INET/AF_INET6/AF_NETLINK/raw sockets and any other address family the syscall would otherwise permit. Equivalent to systemd'sRestrictAddressFamilies=AF_UNIX, as hardened by Whonix. - Added the missing
#include <sys/socket.h>tolainos-dbus-bridge.c, required for theAF_UNIXconstant used by the new restriction (notifyd already had it via an existing include).
Security Review (no code changes required)
- Confirmed
LockPersonalityandRestrictNamespacesequivalents, as hardened by Whonix, are already effectively enforced in both daemons under the existing default-deny (SCMP_ACT_KILL) seccomp policy:personality(),unshare(), andsetns()were never present in either daemon's syscall whitelist, meaning they were already fully blocked. The oneclone()allowance (added for the authorization fix above) remains narrowly scoped, not general namespace creation.
Verification
lainos-dbus-bridge: full dfuzzer 2.6 regression pass ~ Exit status: 0, all methods/properties PASS, real (non-bypassed) seccomp filter active. Valgrind memcheck ~ 0 errors, 0 leaks (definite/indirect/possible); 19,837 bytes still reachable in 79 blocks, consistent with the pre-fix baseline (no new leak). Manual allow-path and deny-path authorization tests both passed correctly. Functional D-Bus smoke test (CanReboot) confirmed working.lainos-notifyd: Valgrind memcheck under real, exercised traffic (Tor daemon restart, generating genuinesd_notifymessages) ~ 0 errors, 0 leaks, daemon survived without crash.- Both daemons compile cleanly against the new restrictions (only the pre-existing, previously-triaged
unused variable 'path'warning inlainos-dbus-bridge.c, unrelated to this change).
Security Verification (
lainos-init)-
Previously verified only by manual code review, not automated testing.
lainos-initis one-shot (single execution per login, called by greetd), but unlikelainos-ghost-units(a genuinely input-free daemon), it reads real, environment-controlled input (P7_CMD,P7_COMPOSITOR,P7_SESSION_TYPE) and uses it to decide what binary toexeclp()~ a real attack surface that "one-shot" alone does not make safe. -
Built a libFuzzer harness (
fuzz_compositor_is_safe.c) against the actual, unmodifiedcompositor_is_safe()function ~ the gatekeeper deciding whether an environment-supplied compositor value is allowed to reachexeclp(). Ran 7,332,678 executions under AddressSanitizer with an RSS-limited, time-boxed configuration ~ zero crashes, zero memory-safety findings. -
Manually tested a set of semantically adversarial inputs the coverage-guided fuzzer is not guaranteed to prioritize: path traversal (
../../../etc/passwd), command-injection-style payloads (sway; rm -rf /), shell substitution (sway$(whoami)), a raw shell path (/bin/sh), and flag-injection-style input (-e). All correctly rejected with no crash. -
Built a second libFuzzer harness (
fuzz_path_construction.c) verifying the exactsnprintf-based overflow-detection pattern used forXDG_RUNTIME_DIR/DBUS_SESSION_BUS_ADDRESSpath construction, with an explicit invariant check (abort()on any case where the overflow check reports success but the resulting buffer is actually out-of-bounds or non-terminated). Ran 1,769,984 executions ~ zero crashes, invariant held in all cases. -
preserve_critical_env()reviewed and confirmed to have no fuzzable logic of its own (unconditionalgetenv/setenvpassthrough, no parsing or branching on value content); any risk from preserved variable values lies in downstream consumers outside protocol7-core's scope, not in this function. -
This confirms
compositor_is_safe()'s whitelist-or-verified-absolute-path validation and the path-construction overflow checks both hold under sustained fuzzing and targeted adversarial testing, closing the gap between "reviewed by inspection" and "verified by testing" for this daemon's real external-input paths.
Known gap, unchanged:
lainos-ghost-unitsconfirmed to take no external input at all (fixed array of 8 literal paths, no arguments/environment/file parsing), and is not prioritized for fuzzing on that basis.Downloads
- Added a redundant, defense-in-depth caller-identity check to