Proof Portal
Omarchy
ProbeLabs65 findings · 95 requirementsA proof layer — requirements, tests and verified fixes — for two of Omarchy's subsystems: the application menu (launcher scripts, QML model, JSONC config, search and selection) and the lock screen (lock scripts, QML, PAM authentication). Scope is deliberately limited to those components of omacom/omarchy; the rest of the distribution is not covered.
Windows VM launch fails: $BASHPID bug in prepare_caller_mounts causes shared_mode check to read wrong fd
Reported by blackway · filed Sep 3, 2026Closed upstream on 2026-09-20 by bjarneo via an automated message, as a duplicate of #9334 (R-1173). GitHub close reason: completed.
At a glance
- 1 · What is claimed?
- Only the report text below — no validator has restated it as checkable claims yet.
- 2 · What does it affect?
- Not yet mapped to any requirement or component.
- 3 · Is it reproducible?
- No validation has been run yet.
- 4 · What remains unclear?
- Not validated yet: no claims, no reproducer.
- 5 · What happens next?
- Our staff decide whether the report is valid. Where this project allows it, agents decide whether it duplicates another report or a known issue. No decision has been recorded yet.
Original report
Bug Description
omarchy-windows-vm launch fails with "Failed to start Windows VM" due to a $BASHPID variable expansion bug in the prepare_caller_mounts function of omarchy-windows-vm.
Root Cause
In prepare_caller_mounts, the script runs:
chmod 0700 -- "/proc/$BASHPID/fd/$storage_fd" "/proc/$BASHPID/fd/$shared_fd"
storage_mode=$(stat -Lc "%a" "/proc/$BASHPID/fd/$storage_fd")
shared_mode=$(stat -Lc "%a" "/proc/$BASHPID/fd/$shared_fd")The chmod runs in the parent shell context (correct PID), but the $(stat ...) command substitution creates a subshell where $BASHPID resolves to the subshell PID instead of the parent PID. This causes stat to read a completely different fd, returning stale/incorrect permissions.
Debug Trace
+ chmod 0700 -- /proc/554585/fd/11 /proc/554585/fd/12 ← parent PID
++ stat -Lc %a /proc/554834/fd/11 ← subshell PID (different!)
+ storage_mode=700
++ stat -Lc %a /proc/554838/fd/12 ← subshell PID (different!)
+ shared_mode=2700 ← reads wrong fd
+ [[ 700 != 700 ]]
+ [[ 2700 != 700 ]] ← fails check
+ return 1The chmod correctly changes ~/Windows to 700, but stat reads permissions from a different process fd, seeing the old 2700 (setgid) value. The check [[ $shared_mode != 700 ]] fails and prepare_caller_mounts aborts.
Reproduction
- Have
~/Windowsdirectory with setgid bit (mode 2700) - Run
omarchy-windows-vm launch - Fails with "Failed to start Windows VM"
Environment
- Omarchy latest (updated 2026-09-04)
- Arch Linux, kernel 7.1.9
- Docker version 29.7.2
- bash (BASHPID behavior in command substitution)
Suggested Fix
Store $BASHPID in a local variable before the command substitution:
local _bashpid=$BASHPID
chmod 0700 -- "/proc/$_bashpid/fd/$storage_fd" "/proc/$_bashpid/fd/$shared_fd"
storage_mode=$(stat -Lc "%a" "/proc/$_bashpid/fd/$storage_fd" 2>/dev/null) || storage_mode=""
shared_mode=$(stat -Lc "%a" "/proc/$_bashpid/fd/$shared_fd" 2>/dev/null) || shared_mode=""Workaround
Manual bind mount + docker-compose up:
sudo mount --bind ~/.windows /var/lib/omarchy/windows/mounts/users/1000/storage
sudo mount --bind ~/Windows /var/lib/omarchy/windows/mounts/users/1000/shared
sudo docker-compose -f /var/lib/omarchy/windows/docker-compose.yml up -dView raw text
## Bug Description `omarchy-windows-vm launch` fails with "Failed to start Windows VM" due to a `$BASHPID` variable expansion bug in the `prepare_caller_mounts` function of `omarchy-windows-vm`. ## Root Cause In `prepare_caller_mounts`, the script runs: ```bash chmod 0700 -- "/proc/$BASHPID/fd/$storage_fd" "/proc/$BASHPID/fd/$shared_fd" storage_mode=$(stat -Lc "%a" "/proc/$BASHPID/fd/$storage_fd") shared_mode=$(stat -Lc "%a" "/proc/$BASHPID/fd/$shared_fd") ``` The `chmod` runs in the parent shell context (correct PID), but the `$(stat ...)` command substitution creates a subshell where `$BASHPID` resolves to the **subshell PID** instead of the parent PID. This causes `stat` to read a completely different fd, returning stale/incorrect permissions. ## Debug Trace ``` + chmod 0700 -- /proc/554585/fd/11 /proc/554585/fd/12 ← parent PID ++ stat -Lc %a /proc/554834/fd/11 ← subshell PID (different!) + storage_mode=700 ++ stat -Lc %a /proc/554838/fd/12 ← subshell PID (different!) + shared_mode=2700 ← reads wrong fd + [[ 700 != 700 ]] + [[ 2700 != 700 ]] ← fails check + return 1 ``` The `chmod` correctly changes `~/Windows` to 700, but `stat` reads permissions from a different process fd, seeing the old 2700 (setgid) value. The check `[[ $shared_mode != 700 ]]` fails and `prepare_caller_mounts` aborts. ## Reproduction 1. Have `~/Windows` directory with setgid bit (mode 2700) 2. Run `omarchy-windows-vm launch` 3. Fails with "Failed to start Windows VM" ## Environment - Omarchy latest (updated 2026-09-04) - Arch Linux, kernel 7.1.9 - Docker version 29.7.2 - bash (BASHPID behavior in command substitution) ## Suggested Fix Store `$BASHPID` in a local variable before the command substitution: ```bash local _bashpid=$BASHPID chmod 0700 -- "/proc/$_bashpid/fd/$storage_fd" "/proc/$_bashpid/fd/$shared_fd" storage_mode=$(stat -Lc "%a" "/proc/$_bashpid/fd/$storage_fd" 2>/dev/null) || storage_mode="" shared_mode=$(stat -Lc "%a" "/proc/$_bashpid/fd/$shared_fd" 2>/dev/null) || shared_mode="" ``` ## Workaround Manual bind mount + docker-compose up: ```bash sudo mount --bind ~/.windows /var/lib/omarchy/windows/mounts/users/1000/storage sudo mount --bind ~/Windows /var/lib/omarchy/windows/mounts/users/1000/shared sudo docker-compose -f /var/lib/omarchy/windows/docker-compose.yml up -d ```
Validation
Not checked yet. A validator will restate this report as checkable claims, map it to the project's requirements and write a reproducer that the proof engine runs.
Linked
Not linked to any known issue, other report or change yet.
Decision
Decisions are recorded by our staff — or, where this project allows it, by agents: checked by a second, independent agent, or by a single agent where the project's policy says so. Any decision reached so far is shown below.
No decision has been recorded yet.