From 7e31500ec1bce08918e3a5a14f2d7121e1cd648d Mon Sep 17 00:00:00 2001 From: Vijit Singh Date: Sat, 11 Jul 2026 20:24:46 -0500 Subject: [PATCH] test(rig-lock): open the lock read-only so a non-root reserve can't EACCES the root gate (#242) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit /var/lock -> /run/lock is a sticky world-writable tmpfs with fs.protected_regular=2. A lock file first created by a NON-root flock (a manual reserve after a reboot clears the tmpfs) is owned by that user, and protected_regular then blocks even root's O_CREAT-write (exec 9>) of it with EACCES — the release perf gate aborted with 'Permission denied' until the file was rm'd (hit live during the v1.7.0 rollout). Open the lock read-only (exec 9<) instead: a read-open is never protected_regular-guarded and flock -x/-s works on a read fd, so this sidesteps it without rm-ing a possibly-held lock. Applied to both e2e-real.sh and e2e-pithead.sh (drift guard keeps them identical); 2 new tests; live-verified on miner-3 (vijit-created lock: old 9> EACCES, new 9< ACQUIRED). Closes #242 Co-Authored-By: Claude Fable 5 --- CHANGELOG.md | 10 ++++++++++ tests/e2e-pithead.sh | 11 +++++++++-- tests/e2e-real.sh | 11 +++++++++-- tests/run.sh | 16 ++++++++++++++++ 4 files changed, 44 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a6c02e7..6736537 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,16 @@ All notable changes to RigForge are documented here. The format is based on ## [Unreleased] +### Fixed + +- **rig-lock survives a non-root reserve (#242).** The shared `rig_lock` helper now opens + `/var/lock/rig-e2e.lock` read-only (`9<`) instead of write (`9>`). A lock file first created by a + non-root `flock` (a manual reserve after a reboot clears the `/run/lock` tmpfs) is owned by that + user, and `fs.protected_regular=2` then blocked even root's `O_CREAT`-write of it with EACCES, + aborting the release perf gate until someone `rm`ed the file. A read-open is never guarded and + `flock` works fine on a read fd, so this sidesteps it without ever removing a possibly-held lock. + The `~/README.md` box contracts also now say to reserve as root. Test-infra only. + ## [1.7.0] - 2026-07-11 ### Added diff --git a/tests/e2e-pithead.sh b/tests/e2e-pithead.sh index 8cd031b..696e4f8 100644 --- a/tests/e2e-pithead.sh +++ b/tests/e2e-pithead.sh @@ -49,8 +49,15 @@ die() { rig_lock() { # rig_lock [shared] local mode=-x [ "${3:-}" = shared ] && mode=-s - exec 9>"${RIG_LOCK_FILE:-/var/lock/rig-e2e.lock}" - chmod 666 "${RIG_LOCK_FILE:-/var/lock/rig-e2e.lock}" 2>/dev/null || true # a non-root shared reader can join later + local lf="${RIG_LOCK_FILE:-/var/lock/rig-e2e.lock}" + # Open the lock READ-only (9<). A lock file first created by a NON-root flock (a manual reserve + # after a reboot clears the /run/lock tmpfs) is owned by that user, and fs.protected_regular then + # blocks even root's O_CREAT-*write* of it (a 9> open) with EACCES. A read-open is never guarded, + # and flock -x/-s works fine on a read fd, so this sidesteps it without rm-ing a possibly-held + # lock. Create it first if absent; keep it 0666 so a shared reader can still join. (#242) + [ -e "$lf" ] || : >"$lf" 2>/dev/null || true + chmod 666 "$lf" 2>/dev/null || sudo chmod 666 "$lf" 2>/dev/null || true + exec 9<"$lf" if ! flock -n $mode 9; then if [ "${RIG_LOCK_WAIT:-0}" = 1 ]; then echo "rig busy ($(cat "${RIG_LOCK_HOLDER:-/run/rig-e2e.holder}" 2>/dev/null || echo unknown)) — waiting..." >&2 diff --git a/tests/e2e-real.sh b/tests/e2e-real.sh index 6e4baab..db0619c 100755 --- a/tests/e2e-real.sh +++ b/tests/e2e-real.sh @@ -69,8 +69,15 @@ die() { rig_lock() { # rig_lock [shared] local mode=-x [ "${3:-}" = shared ] && mode=-s - exec 9>"${RIG_LOCK_FILE:-/var/lock/rig-e2e.lock}" - chmod 666 "${RIG_LOCK_FILE:-/var/lock/rig-e2e.lock}" 2>/dev/null || true # a non-root shared reader can join later + local lf="${RIG_LOCK_FILE:-/var/lock/rig-e2e.lock}" + # Open the lock READ-only (9<). A lock file first created by a NON-root flock (a manual reserve + # after a reboot clears the /run/lock tmpfs) is owned by that user, and fs.protected_regular then + # blocks even root's O_CREAT-*write* of it (a 9> open) with EACCES. A read-open is never guarded, + # and flock -x/-s works fine on a read fd, so this sidesteps it without rm-ing a possibly-held + # lock. Create it first if absent; keep it 0666 so a shared reader can still join. (#242) + [ -e "$lf" ] || : >"$lf" 2>/dev/null || true + chmod 666 "$lf" 2>/dev/null || sudo chmod 666 "$lf" 2>/dev/null || true + exec 9<"$lf" if ! flock -n $mode 9; then if [ "${RIG_LOCK_WAIT:-0}" = 1 ]; then echo "rig busy ($(cat "${RIG_LOCK_HOLDER:-/run/rig-e2e.holder}" 2>/dev/null || echo unknown)) — waiting..." >&2 diff --git a/tests/run.sh b/tests/run.sh index df0e4e9..72f9b7d 100644 --- a/tests/run.sh +++ b/tests/run.sh @@ -5435,6 +5435,22 @@ else assert_eq "queued waiter actually acquired (#183)" \ "$([ -f "$RLD/got.q" ] && echo acquired || echo blocked)" "acquired" + # #242: the lock is opened READ-only, so a pre-existing lock file (a leftover a non-root + # reserve created earlier) is acquired without needing to O_CREAT-write it — which is what + # dodges fs.protected_regular's block on root re-opening a non-root-created file in /run/lock. + RIG_LOCK_FILE="$RLD/pre" RIG_LOCK_HOLDER="$RLD/pre.holder" + : >"$RIG_LOCK_FILE" # pre-exists before any rig_lock call + (eval "$RL_SRC" && rig_lock rigforge pre-existing "" && touch "$RLD/pre.ok") 2>/dev/null + assert_eq "acquires a pre-existing lock file (#242)" "$([ -f "$RLD/pre.ok" ] && echo y || echo n)" "y" + # A lock file left at a restrictive mode is normalized and still acquired (the root+sticky + # protected_regular sidestep itself — read-open of a non-root-created file — needs a live root + # rig and is covered by the e2e gate, not this sandbox). + RIG_LOCK_FILE="$RLD/ro" RIG_LOCK_HOLDER="$RLD/ro.holder" + : >"$RIG_LOCK_FILE" && chmod 444 "$RIG_LOCK_FILE" + (eval "$RL_SRC" && rig_lock rigforge restrictive "" && touch "$RLD/ro.ok") 2>/dev/null + assert_eq "normalizes + acquires a restrictive-mode lock file (#242)" "$([ -f "$RLD/ro.ok" ] && echo y || echo n)" "y" + chmod 666 "$RLD/ro" 2>/dev/null || true + unset RIG_LOCK_FILE RIG_LOCK_HOLDER fi