diff --git a/deploy/files/usr/local/libexec/left4me/left4me-script-sandbox b/deploy/files/usr/local/libexec/left4me/left4me-script-sandbox index aa533f0..d3ce299 100755 --- a/deploy/files/usr/local/libexec/left4me/left4me-script-sandbox +++ b/deploy/files/usr/local/libexec/left4me/left4me-script-sandbox @@ -19,6 +19,18 @@ # not signal-able due to UID mismatch. set -euo pipefail +# Self-wrap into PID 1's mount namespace before doing anything mount-related. +# The web app's left4me-web.service has PrivateTmp=true, which gives it a +# private mount namespace. When the worker invokes us via sudo, we inherit +# that namespace; our `mount --bind` would land there. systemd-run below +# spawns transient units in PID 1's namespace (where they don't see the +# private bind), so the sandbox would bind onto an empty staging dir and +# permission-deny on every write. The sentinel env var avoids an exec loop. +if [[ "${L4D2_SANDBOX_IN_PID1_MNT_NS:-}" != "1" ]]; then + exec env L4D2_SANDBOX_IN_PID1_MNT_NS=1 \ + /usr/bin/nsenter --mount=/proc/1/ns/mnt -- "$0" "$@" +fi + [[ $# -eq 2 ]] || { echo "usage: $0