Skip to content

omarchy-windows-vm launch fails silently when ~/Windows has the setgid bit (numeric chmod can't clear it) #9567

Closed

Description

@andyxqq

[BUG] omarchy-windows-vm launch fails silently when ~/Windows has the setgid bit set (numeric chmod cannot clear it)

Environment

  • Omarchy 4.0.2-1
  • Arch Linux, kernel 7.1.9-arch1-2
  • Windows VM installed via omarchy windows vm install, container omarchy-windows running and healthy (web console at 127.0.0.1:8006 shows a booted desktop; RDP answers X.224 on 3389)
  • User not in the docker group (default), so launch elevates through pkexec

What happened

$ omarchy windows vm launch
Starting Windows VM (this may prompt for authorization)...
❌ Failed to start Windows VM!
   Try checking: omarchy-windows-vm status

No reason is printed — not on the terminal, not in a notification. status reports RUNNING, the web console works, RDP is up; only launch refuses.

Root cause

prepare_caller_mounts() in omarchy-windows-vm chmods the opened FDs of the caller's ~/.windows / ~/Windows and then verifies the mode:

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=""
if [[ $storage_mode != 700 || $shared_mode != 700 ]]; then
  exec {storage_fd}<&-
  exec {shared_fd}<&-
  return 1      # <-- silent
fi

In my case ~/Windows carried the setgid bit (mode 2700, drwx--S---). A numeric chmod 0700 cannot clear setgid on a directory — the setgid bit is left as-is (setting it via numeric mode works, clearing it doesn't; g-s is required). So the chmod "succeeds", the verification still reads 2700, and the function returns 1 without any message. launch surfaces only the generic failure box.

Confirmed with bash -x under pkexec:

+ chmod 0700 -- /proc/396250/fd/11 /proc/396250/fd/12
++ stat -Lc %a /proc/396582/fd/11
+ storage_mode=700
++ stat -Lc %a /proc/396584/fd/12
+ shared_mode=2700
+ [[ 700 != 700 ]]
+ [[ 2700 != 700 ]]
+ exec
+ return 1

Workaround

chmod g-s ~/Windows

After this, omarchy windows vm launch works (verified).

Suggested fix

  1. Clear the setgid bit explicitly, e.g. chmod 700,g-s (symbolic g-s), at the FD chmod in prepare_caller_mounts() — and audit the other numeric chmod 0700 calls on user-owned directories (there are two more) for the same trap.
  2. Print a diagnostic before returning 1 in that failure path — the silent exit makes this (and any future mode mismatch) undiagnosable from the user side.

Reproduce

  1. Install the Windows VM normally.
  2. chmod g+s ~/Windows (any source of setgid works; mine arrived with mode 2700).
  3. omarchy windows vm launch → generic failure, no diagnostics.

Activity

  1. rookepoole commented on Sep 1, 2026

    @rookepoole

    This is the same GNU chmod/setgid root cause tracked earlier in #9334. Existing open implementations are:\n\n- #9504 clears special bits in both user preflight and privileged mount preparation, with compose and mount-boundary regression coverage.\n- #9322 hardens both migration paths and adds a setgid migration fixture.\n- #9414 applies the symbolic-mode fix in omarchy-windows-vm.\n\nAll three address the failing launch path described here. Linking them so this report is connected to the existing implementation work and another duplicate PR is not opened.

  2. omarchybot commented on Sep 1, 2026

    @omarchybot
    Collaborator

    Confirmed, and fixed in #9605.

    prepare_caller_mounts() in bin/omarchy-windows-vm hardens both mount sources with chmod 0700 and then asserts the mode is exactly 700. chmod with a numeric mode does not clear S_ISGID on a directory — the kernel preserves it whenever the caller is in the file's group or holds CAP_FSETID, which root always does. So a 2700 directory stays 2700, chmod still returns 0, and the != 700 branch rejects the source and returns 1 with nothing on stderr. Reproduced directly: mkdir /tmp/t && chmod 2700 /tmp/t && chmod 0700 /tmp/t && stat -c %a /tmp/t still prints 2700.

    #9605 switches the three sites that make these directories private to a symbolic mode, which does clear the set-ID bits, and adds a message to the verification branch so a future failure here says why. Regression cases start the sources at 2700/6700; they fail against the current code and pass with the fix. ./test/cli and the four windows-vm suites pass on a clean VM.

    This was reported three times independently — #9374, #9540 and #9567 — with the same root cause; #9605 closes all three.

    Reviewed by Claude Opus 5 and by Codex at xhigh. Codex verified the mode arithmetic across every set-ID combination and caught that the existing suites start these directories at 0755, so they would have passed against the broken chmod; the regression cases came out of that. Waiting on a maintainer to merge.

  3. bjarneo commented on Sep 20, 2026

    @bjarneo
    Member

    Automated duplication check: this issue looks similar to #9334, which covers the same Windows VM setgid permission check. I keep that one open and close this one to keep the discussion in one place.

    If you feel this is the wrong decision, please open the issue again with a note on the difference.

  4. omarchybot commented on Oct 4, 2026

    @omarchybot
    Collaborator

    Update: #12323 has merged into quattro. The reported numeric-chmod/setgid rejection is fixed in both mount-source hardening paths on quattro. Launch, install and removal re-harden the sources without weakening the exact mode-700 check.

    Scope checked by GPT-6 in Codex and Codex Medium against the discussion and landed change; review independence is not guaranteed. No tests were rerun for this cleanup.

    Omabot on behalf of DHH

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions