mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-09-10 18:45:53 +00:00
5c1c89a363
Adversarial review of9db25ba60found four residual defects in the auto-update asset install, plus a doc line it left contradicting itself. - install_auto_update_assets copied the bundled helper into the staged mktemp file with an unchecked cp, and both call sites invoke the function under `if !`, which suppresses errexit for its whole body. A failed copy (ENOSPC, EIO) fell through to configure_auto_update_script_repo, whose awk emits a lone GITHUB_REPO= line for empty input, so a shebang-less one-line stub replaced the working helper with a "script" that only ever exits 0 - silently disabling unattended updates. Check the cp, and refuse the swap unless the staged helper is non-empty and starts with #!. - Both units were rendered with a bare truncating `cat > "$unit"` whose status was never checked, and the function's last statement is safe_systemctl daemon-reload, which returns 0 by design. A failing write truncated a working unit and still reported success. Render each unit to ${path}.tmp and commit it with a checked rename, so a failure leaves the installed unit byte-identical. - The widened ReadWritePaths could not reach deployed boxes: the unit that grants the write access is itself the file that has to be rewritten, and on an existing install the sandbox running the installer excludes /etc/systemd/system and /usr/local/bin (EROFS). The Go update pipeline cannot carry it either - pulse.service runs as User=pulse with its own ProtectSystem=strict over the install and config dirs only. So probe each destination directory up front and, when one is blocked, re-exec this already-signature-verified installer through systemd-run with a new internal --repair-auto-update-units entry point: PID 1 forks the transient unit, so it starts in the host mount namespace instead of inheriting the sandbox. The installer is copied into the install dir first because the calling unit's PrivateTmp=yes hides its /tmp copy from PID 1. The escape needs root and systemd-run, and never recurses. - Keep the ReadWritePaths entries as directory grants: every write now commits with a rename from a sibling staging file, and rename needs write access on the containing directory, so the file-level entries systemd would otherwise accept cannot work. Document the tradeoff in the unit and the subsystem contract instead. The deployment-installability contract still claimed the update sandbox leaves "only the install dir, config dir and /tmp" writable, which the paragraph the same file gained in9db25ba60contradicts; the same stale rationale had been copied into two test comments. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>