Skip to content

Windows VM launch fails silently when ~/Windows has the setgid bit (chmod 0700 preserves setgid) #11262

Closed

Description

@madmanmatt

Summary

omarchy windows vm launch fails with a bare "❌ Failed to start Windows VM!" (no diagnostic) when ~/Windows or ~/.windows has the setgid bit set. The mount-hardening preflight runs chmod 0700 on both directories and then requires stat %a to be exactly 700, but GNU chmod deliberately preserves setgid/setuid on directories for 4-digit numeric modes, so the directory stays 2700 and prepare_caller_mounts returns 1 silently.

Environment

  • Omarchy 4.0.3-1 (bin/omarchy-windows-vm on quattro is byte-identical to the installed copy)
  • coreutils 9.11-2, docker 29.7.2, docker-compose 5.5.1
  • Intel Core Ultra 7 258V, Arc 140V (integrated), btrfs home
  • Windows VM was installed under an earlier 4.0.x, before the mount-hardening commits (c34d20c, a165185); this launch was the first since updating.

Steps to reproduce

chmod g+s ~/Windows        # or any pre-existing setgid shared folder
omarchy windows vm launch
# → "❌ Failed to start Windows VM!" immediately, nothing on stderr

Standalone demonstration of the chmod behaviour:

$ mkdir -m 2700 Windows && stat -c %a Windows
2700
$ chmod 0700 -- Windows && stat -c %a Windows
2700        # setgid preserved
$ chmod 00700 -- Windows && stat -c %a Windows
700

Where it fails

bin/omarchy-windows-vm, prepare_caller_mounts() (lines 583–594 on quattro):

  chmod 0700 -- "/proc/$BASHPID/fd/$storage_fd" "/proc/$BASHPID/fd/$shared_fd" || { ...; return 1; }
  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           # <- no error message
  fi

Trace from sudo PKEXEC_UID=$(id -u) bash -x /usr/bin/omarchy-windows-vm __priv up_wait:

+ chmod 0700 -- /proc/80069/fd/11 /proc/80069/fd/12
++ stat -Lc %a /proc/80281/fd/11
+ storage_mode=700
++ stat -Lc %a /proc/80283/fd/12
+ shared_mode=2700
+ [[ 700 != 700 ]]
+ [[ 2700 != 700 ]]
+ return 1

The same chmod 0700 -- "$storage" "$shared" pattern appears in prepare_user_mount_sources() (line 1018), so the user-side preflight doesn't catch it either.

Expected

Either the preflight normalises the mode fully, or it fails with a message telling the user which directory has the wrong mode.

Suggested fix

  • Use a 5-digit mode (chmod 00700) or an explicit symbolic clear (chmod u=rwx,go=,u-s,g-s) in both places so setuid/setgid/sticky are stripped along with the group/other bits.
  • Print an error on the != 700 branch, e.g. omarchy-windows-vm: $path must be mode 0700 (is $mode) so the failure is diagnosable from launch output.

Workaround

chmod g-s ~/Windows ~/.windows

After that, omarchy windows vm launch works normally.

Activity

  1. hapatapa commented on Sep 12, 2026

    @hapatapa

    Still reproduces on Omarchy 4.0.3-1 with coreutils 9.11, exactly as described here.

    Environment: AMD Ryzen 5 7520U, 15GB RAM, btrfs home, Docker 29.7.2, docker-compose 5.5.1.

    Confirmed the same silent failure path: prepare_caller_mounts() returns 1 after chmod 0700 leaves shared_mode=2700, so both launch and remove abort at assert_mounts_safe with no stderr message.

    One detail worth adding: the running container actively re-sets the bit. The guest exposes the shared folder through Samba (smbd: client [172.30.0.2] inside the dockurr/windows container), which puts g+s back on the host ~/Windows (mode 2700, owner uid 1000) while the VM is running. So clearing it before a launch only sticks until the next VM run — the check needs to be robust against the dir carrying setgid, not just clear it once.

    Workaround in use locally (works): chmod g-s ~/Windows before launch/remove, since numeric chmod 0700 alone cannot clear setgid on a directory.

    Happy to test a proposed fix.

  2. 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.

  3. omarchybot commented on Oct 4, 2026

    @omarchybot
    Collaborator

    Update: #12323 has merged into quattro. The setgid permission rejection is now fixed in both source-directory hardening paths, with an explicit mode diagnostic. This does not claim that runtime share privacy or every desktop failure notification is fixed.

    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