From 656be1cf69c87457e9bee62dd1ae0c4a4561a2b1 Mon Sep 17 00:00:00 2001 From: CroneKorkN Date: Fri, 15 May 2026 16:14:33 +0200 Subject: [PATCH] fix(left4me): move ProcSubset=pid from COMMON to SERVER-only MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Discovered post-deploy: ProcSubset=pid hides /proc/sys/kernel/random/boot_id which journalctl reads at startup. The web app invokes `sudo -n left4me-journalctl` to stream live server logs into the UI; journalctl bails with "Failed to get boot ID" before producing any output. Web log streaming was silently broken. Server unit keeps ProcSubset=pid (srcds doesn't invoke journalctl); web unit drops it. ProtectProc=invisible remains in COMMON — that's the load-bearing D4 defense (foreign-uid /proc hidden). Reproducer that confirms the diagnosis: systemd-run --pipe --uid=left4me --gid=left4me \ -p ProcSubset=pid -p ProtectProc=invisible \ -p ProtectSystem=strict -p PrivateTmp=true \ [...rest of web hardening...] \ -- sh -c 'sudo -n left4me-journalctl 2 --lines 3 --follow >/var/lib/left4me/tmp/out 2>&1' # cat /var/lib/left4me/tmp/out → "Failed to get boot ID: No such file or directory" # rc → 1 With ProcSubset=all: timeout 124 (helper running), 3 lines streamed. Co-Authored-By: Claude Opus 4.7 (1M context) --- bundles/left4me/metadata.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/bundles/left4me/metadata.py b/bundles/left4me/metadata.py index 88488ec..f4df47c 100644 --- a/bundles/left4me/metadata.py +++ b/bundles/left4me/metadata.py @@ -128,9 +128,14 @@ defaults = { # (paths in the left4me repo) # Directives both managed units take verbatim. +# +# ProcSubset=pid is intentionally NOT in COMMON: it hides +# /proc/sys/kernel/random/boot_id which journalctl reads at startup, +# and the web unit invokes `sudo -n left4me-journalctl ...` to stream +# live server logs into the UI. Server unit adds it back in +# HARDENING_SERVER (srcds doesn't read journalctl). HARDENING_COMMON = { 'ProtectProc': 'invisible', - 'ProcSubset': 'pid', 'ProtectKernelTunables': 'true', 'ProtectKernelModules': 'true', 'ProtectKernelLogs': 'true', @@ -154,6 +159,7 @@ HARDENING_COMMON = { # socket binds. HARDENING_SERVER = { **HARDENING_COMMON, + 'ProcSubset': 'pid', 'NoNewPrivileges': 'true', 'RestrictSUIDSGID': 'true', 'PrivateUsers': 'true',