From 752aa18a05af191b6d12f45d47a297109174466a Mon Sep 17 00:00:00 2001 From: Garry Tan Date: Sat, 29 Aug 2026 05:58:14 +0000 Subject: [PATCH] fix(sandbox-doctor): atomic git-shim patch, :99-socket Xvfb check, dnf gate, non-interactive sudo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - The /conductor/bin/git patch writes tmp-then-rename with a .orig backup — a concurrently spawned git can never exec a truncated shim. - Xvfb running-check looks for the :99 socket, not any-display pgrep. - Xvfb install is dnf-gated so non-dnf distros degrade to a warning instead of aborting the remaining fixes under set -eu. - The bashrc /dev/fd restore uses sudo -n || true — no password prompt at every shell start on non-passwordless machines. - BASH_COMPAT=50 keeps heredoc bodies off the bash pipe window. Co-Authored-By: Claude Fable 5 --- scripts/sandbox-doctor.sh | 38 ++++++++++++++++++++++++------- test/sandbox-doctor-shell.test.ts | 3 ++- 2 files changed, 32 insertions(+), 9 deletions(-) diff --git a/scripts/sandbox-doctor.sh b/scripts/sandbox-doctor.sh index ad1f70af8..62d6c0a84 100755 --- a/scripts/sandbox-doctor.sh +++ b/scripts/sandbox-doctor.sh @@ -33,6 +33,9 @@ # DISPLAY=:99 TMPDIR=$HOME/tmp GSTACK_FREE_JOBS=2 GSTACK_FREE_RETRY_FLAKY=1 \ # setpriv --ambient-caps=-all --bounding-set=-all bun run test set -eu +# When bash runs this script, keep heredoc bodies on temp files rather than +# the 512-65536B pipe window (see test/heredoc-pipe-deadlock.test.ts). +BASH_COMPAT=50 say() { printf 'sandbox-doctor: %s\n' "$1"; } @@ -53,9 +56,21 @@ fi # 3. TMPDIR under HOME (persisted via bashrc below; created here) mkdir -p "$HOME/tmp" -# 5. Xvfb for headed-browser tests -command -v Xvfb >/dev/null 2>&1 || sudo dnf install -y xorg-x11-server-Xvfb >/dev/null -pgrep -x Xvfb >/dev/null 2>&1 || { Xvfb :99 -screen 0 1280x800x24 >/dev/null 2>&1 & say 'started Xvfb on :99'; } +# 5. Xvfb for headed-browser tests. dnf-gated so a non-dnf distro degrades to +# a warning instead of aborting the remaining fixes under set -eu; the +# running-check looks for the :99 socket specifically (an Xvfb on another +# display would otherwise satisfy pgrep while DISPLAY=:99 points at nothing). +if ! command -v Xvfb >/dev/null 2>&1; then + if command -v dnf >/dev/null 2>&1; then + sudo dnf install -y xorg-x11-server-Xvfb >/dev/null + else + say 'WARNING Xvfb missing and no dnf — install Xvfb manually for headed-browser tests' + fi +fi +if command -v Xvfb >/dev/null 2>&1 && [ ! -e /tmp/.X11-unix/X99 ]; then + Xvfb :99 -screen 0 1280x800x24 >/dev/null 2>&1 & + say 'started Xvfb on :99' +fi # 6. git identity (only if absent — never clobber a configured one) git config --global user.name >/dev/null 2>&1 || { @@ -67,12 +82,19 @@ git config --global user.name >/dev/null 2>&1 || { # 7. Conductor git-shim exit-code bug if [ -f /conductor/bin/git ] && grep -q '^status=\$?' /conductor/bin/git 2>/dev/null; then sudo python3 - <<'EOF' -src = open('/conductor/bin/git').read() +import os +p = '/conductor/bin/git' +src = open(p).read() old = 'exit 0\nfi\nstatus=$?' new = 'exit 0\nelse\n\tstatus=$?\nfi' if old in src: - open('/conductor/bin/git', 'w').write(src.replace(old, new)) - print('sandbox-doctor: patched /conductor/bin/git exit-code laundering') + # Atomic: a concurrently spawned git must never exec a truncated shim. + open(p + '.orig', 'w').write(src) + tmp = p + '.tmp' + open(tmp, 'w').write(src.replace(old, new)) + os.chmod(tmp, 0o755) + os.replace(tmp, p) + print('sandbox-doctor: patched /conductor/bin/git exit-code laundering (backup: git.orig)') elif new not in src: print('sandbox-doctor: WARNING git shim drifted from the patch pattern; laundering NOT fixed, patch by hand') EOF @@ -90,8 +112,8 @@ export TMPDIR="$HOME/tmp" export GSTACK_FREE_JOBS=2 export GSTACK_FREE_RETRY_FLAKY=1 export DISPLAY=:99 -[ -e /dev/fd ] || sudo ln -sfn /proc/self/fd /dev/fd 2>/dev/null -pgrep -x Xvfb >/dev/null 2>&1 || (Xvfb :99 -screen 0 1280x800x24 >/dev/null 2>&1 &) +[ -e /dev/fd ] || sudo -n ln -sfn /proc/self/fd /dev/fd 2>/dev/null || true +[ -e /tmp/.X11-unix/X99 ] || (Xvfb :99 -screen 0 1280x800x24 >/dev/null 2>&1 &) EOF say 'seeded ~/.bashrc test env' fi diff --git a/test/sandbox-doctor-shell.test.ts b/test/sandbox-doctor-shell.test.ts index 39d4193da..54685f43a 100644 --- a/test/sandbox-doctor-shell.test.ts +++ b/test/sandbox-doctor-shell.test.ts @@ -27,7 +27,8 @@ describe('sandbox-doctor.sh', () => { expect(src).toContain('[ ! -e /dev/fd ]'); // /dev/fd restore expect(src).toContain('git config --global user.name >/dev/null 2>&1 ||'); // never clobber identity expect(src).toContain("grep -q 'GSTACK sandbox test env'"); // bashrc seeded once - expect(src).toContain('command -v Xvfb >/dev/null 2>&1 ||'); // install only if absent + expect(src).toContain('if ! command -v Xvfb >/dev/null 2>&1'); // install only if absent, dnf-gated + expect(src).toContain('[ ! -e /tmp/.X11-unix/X99 ]'); // :99 socket check, not any-display pgrep expect(src).toContain('[ "${shm_kb:-0}" -gt 0 ]'); // missing /dev/shm: skip, not a set -eu abort }); });