git.lucas.co / cce-display-manager
login greeter
git clone https://git.lucas.co/cce-display-manager.git

commit7146b3ed4310ef9de19fbcc39fef888c53ad094a
parentbb9aed1f60
authorLucas Galante <[email protected]>
date2026-08-20 14:47
unlockd sandbox: /run/user needs its own ReadWritePaths entry

Deployed live, the sandbox broke every unlock with "I/O error:
Permission denied": /run/user is a separate tmpfs, so ReadWritePaths=/run
stopped at the mount boundary and ProtectSystem=strict left the submount
read-only — connect() to /run/user/<uid>/bus fails EACCES on a read-only
mount. Verified from the daemon's own /proc/<pid>/mounts (/run rw,
/run/user ro) and the request log.

Co-Authored-By: Claude Fable 5 <[email protected]>

 cce-keyring-unlockd.service | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/cce-keyring-unlockd.service b/cce-keyring-unlockd.service
index a159f9c..7ce1df0 100644
--- a/cce-keyring-unlockd.service
+++ b/cce-keyring-unlockd.service
@@ -17,7 +17,10 @@ Environment=RUST_LOG=info
 NoNewPrivileges=yes
 CapabilityBoundingSet=CAP_SETUID CAP_SETGID CAP_SYS_PTRACE
 ProtectSystem=strict
-ReadWritePaths=/run
+# /run/user is its OWN tmpfs: ReadWritePaths=/run does not reach into the
+# submount, ProtectSystem=strict remounts it ro, and connect() to the user
+# bus socket then fails EACCES — which broke every unlock until listed here.
+ReadWritePaths=/run /run/user
 ProtectHome=yes
 PrivateTmp=yes
 ProtectKernelTunables=yes