Repository navigation
Windows VM 4.0.2: launch fails silently after polkit auth (setgid chmod check can never pass) #9334
Description
Edit: the original root-cause analysis below blamed a kernel regression. That was wrong, and I've rewritten this post. The bit is GNU
chmodsemantics, not the kernel — thanks to @murilocb for independently landing on the same conclusion in a comment. The failure itself and the code path are unchanged.
Windows VM launch silently fails after polkit auth on 4.0.2: the privileged mount-source check can never pass once the source dir has the setgid bit, because the chmod the script uses cannot clear it.
What happened
After upgrading 4.0.1 → 4.0.2, launching the Windows VM (Apps menu → Windows, omarchy-windows-vm launch) shows the polkit password dialog and then nothing happens. No error, no window. Every retry asks for the password again with no result.
The elevated step exits non-zero and all of its stderr is discarded, because the desktop entry runs with Terminal=false — so from the user's perspective the password is accepted and then nothing happens at all.
Root cause
prepare_caller_mounts() hardens both mount sources by running chmod 0700 on the pinned fds and then requires the resulting mode to be exactly 700:
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=""
[[ $storage_mode != 700 || $shared_mode != 700 ]] && { ...; return 1; }GNU chmod preserves a directory's setuid/setgid bits for numeric modes shorter than five octal digits. This is documented, long-standing coreutils behavior. chmod 0700 is therefore incapable of producing 700 from 2700, and the check that follows can never pass. Measured on this box (chmod (GNU coreutils) 9.11, kernel 7.1.9-arch1-2, btrfs):
command on a 2777 directory |
resulting mode |
|---|---|
chmod 700 |
2700 |
chmod 0700 |
2700 ← what the script does |
chmod 00700 |
700 |
chmod g-s |
777 |
It behaves the same through the /proc/$BASHPID/fd/N indirection the script actually uses:
$ exec {fd}<~/Windows # mode 2777
$ chmod 0700 -- "/proc/$BASHPID/fd/$fd"
$ stat -Lc %a "/proc/$BASHPID/fd/$fd" # 2700 → != 700 → return 1
Deterministic on/off proof that this single bit is what kills the launch:
$ stat -c %a ~/Windows # 2700
$ pkexec /usr/bin/omarchy-windows-vm __priv up; echo $? # 1, no output at all
$ chmod g-s ~/Windows # 700
$ pkexec /usr/bin/omarchy-windows-vm __priv up; echo $? # 0, container comes up
This is not a one-off from an old install. dockurr/windows chmods the shared mount to 2777 on every container start — after a successful __priv up_wait here, ~/Windows is drwxrwsrwx. So the bit is re-applied by every launch, and since the same strict mode == 700 comparison also lives in mounted_leaf_matches() (and therefore mounts_ready), every launch after the first one fails identically. Recreating the directory buys exactly one launch.
Steps to reproduce
- Have a Windows VM whose
~/Windowscarries the setgid bit — either from a ≤ 4.0.1 install (drwx--S---) or simply from having started the container once on 4.0.2 (drwxrwsrwx). - Apps menu → Windows, enter the polkit password.
- Nothing happens, no error, no window.
Minimal repro of the underlying chmod behavior, no VM involved:
mkdir -m 2700 /tmp/sgdir
chmod 0700 /tmp/sgdir; stat -c %a /tmp/sgdir # 2700
chmod 00700 /tmp/sgdir; stat -c %a /tmp/sgdir # 700Workaround
Strip the bit with a form of chmod that actually clears it, before every launch:
chmod 00700 ~/Windows ~/.windowsIf a launch already failed once, the root-owned bind anchor still pins the old inode when you recreate the directory instead of chmod'ing it, and the next attempt dies with protected mount ... no longer matches its home source. In that case unmount the anchor first — see the follow-up comment below. Chmod'ing in place avoids that entirely, since the inode never changes.
This has to be repeated after every container run, so in practice it needs to be wrapped around the launch.
Expected
One or more of:
prepare_caller_mounts()andmounted_leaf_matches()clear the bit with a mode that works —chmod 00700, orchmod u-s,g-sfollowed bychmod 0700— rather thanchmod 0700.- Alternatively, relax the comparison to what the hardening actually cares about: correct owner and no group/other access bits, rather than a strict
== 700. - The failure surfaces to the user (desktop notification, or a visible terminal) instead of dying silently after a successful password prompt. This is the part that makes it undiagnosable for a normal user.
System details
- Omarchy 4.0.2-1 (upgraded from 4.0.1; VM originally installed in the 4.0.0 era)
- Kernel: 7.1.9-arch1-2
- coreutils 9.11
- Hyprland 0.56.2, SDDM
- Intel CoffeeLake-H (UHD Graphics 630)
- Filesystem: btrfs (
/@homesubvolume, zstd)
Activity
[-]Title[/-][+]Windows docker BUG[/+][-]Windows docker BUG[/-][+]Windows VM 4.0.2: launch fails silently after polkit auth (setgid chmod check can never pass)[/+]bpidperygora commentedon Aug 31, 2026
Follow-up, and a correction to the workaround in the post: recreating ~/Windows alone does NOT get you going. If the launch failed at least once, the root-owned bind anchor at /var/lib/omarchy/windows/mounts/users/1000/shared still pins the old inode, and the next attempt dies with "protected mount ... no longer matches its home source". The sequence that actually worked here:
Caveat: this holds for exactly one boot. dockurr/windows sets SGID on /shared (that's ~/Windows on the host) on every container start, chmod can't strip it on this kernel, and the same check also runs in __priv_up_wait on every start — not just during the legacy compose migration. So until either side changes, each launch after a container run fails the same way again.
Pinox commentedon Aug 31, 2026
Yes Windows is currently broken, after upgrade.
Now on :

Tried resetting PC, then reinstalling windows again. It fails at authentication. Entering linux root does not pass auth and Windows container fails to start.
General question. Is there any way we can save all our settings on Omarchy so that we don't have to reinstall everything again (plugins / app) when resetting our PC's ? Would be great especially now when these types of issues can be common, an option to import previous Omarchy app/plugin settings would be usefull.
murilocb commentedon Aug 31, 2026
Hit this too (4.0.1 → 4.0.2 upgraded this morning,
~/Windowsatdrwx--S---), and I can confirm the failing check. But the root cause isn't the kernel — it's GNUchmod, and that changes the fix.chmodpreserves setuid/setgid on directories when the numeric mode has 4 or fewer octal digits. This is documented, long-standing coreutils behavior, not a 7.1.9 regression:Same box as the report, same kernel, btrfs:
And the syscall itself has no such behavior — the kernel clears SGID exactly as expected:
chmod (GNU coreutils) 9.11, kernel7.1.9-arch1-2, btrfs. Sopkexec bash -c 'chmod 700 …'printing2700is coreutils declining to touch the bit, not the kernel refusing to clear it. Nothing to flag to Arch, and (FWIW) an unprivileged user can still set SGID on a directory they own —chmod 2700above ran as a normal user.I verified this is the exact failure path in
prepare_caller_mounts(), including through the/proc/$BASHPID/fd/Nindirection the script actually uses:Corroborating evidence that it dies right there: after a failed launch the anchors exist but were never bound —
prepare_mount_anchor()had run (both anchors created, timestamped at the first launch attempt),bind_mount_leaf()never did.Implications for the fix
The strict
== 700check is fine and doesn't need relaxing — thechmodjust needs to actually do what it intends:(or symbolic
u=rwx,go=,g-s, which is self-documenting about the intent). This also disposes of the recurring-failure caveat in the follow-up comment: if dockurr/windows re-applies SGID to/sharedon every container start, a correctchmodstrips it again on each launch and the check keeps passing — no per-boot breakage.Simpler user workaround
No need to move the directory or unmount the anchor:
chmod g-s ~/WindowsThe inode is unchanged, so the pinned anchor stays valid and the next launch re-binds normally. Fixed it here on the first try.
The silent-failure half of the report stands on its own and is worth fixing regardless —
Terminal=falseinwindows-vm.desktopmeans every one of thesereturn 1s is invisible, and the user just sees the polkit dialog accept their password and nothing happen.slinn-01 commentedon Aug 31, 2026
Confirmed independently on Omarchy 4.0.2-1 after upgrading from 4.0.1. A traced privileged launch showed the exact failure: numeric
chmod 0700returned success but left the shared source at2700; the following exact-mode check rejected it before Docker startup. I also observed Dockurr set the empty shared folder to2777while the guest was running, so this can recur unless launch explicitly clears special bits.There is already a targeted fix in #9322. I checked it in a clean checkout: its Windows VM compose/security suite passes with the new setgid fixture, and the approach keeps the strict
700validation while changing normalization tochmod u=rwx,go=,a-s. I posted full validation details on the PR: #9322 (comment)No additional issue opened to avoid duplication.
ewertonmattoslumon commentedon Aug 31, 2026
Independent confirmation from a second machine (Avell A60 MUV laptop, same
7.1.9-arch1-2kernel, btrfs): identical failure — works once, then every subsequentlaunchfails silently because dockurr/windows re-sets SGID on the shared source dir on every container start and the script'schmodcan't strip it back off. Matches the__priv_up_wait-runs-every-start behavior in the follow-up comment above.One addition that may help pin the actual fix: the failing call in
prepare_caller_mounts()is the 4-digit formchmod 0700 -- .... That form does not reliably clear SGID on a directory under GNU coreutils (tested here, coreutils 9.11 / kernel 7.1.9-arch1-2):Per
man chmod, GNU coreutils intentionally preserves setuid/setgid on directories for a numeric mode unless it has an extra leading zero (00755, not0700) or the bits are cleared symbolically (g-s) — protection against a recursivechmod -R 755silently stripping SGID off a shared directory.chmod 0700reads to coreutils as an ordinary 4-digit mode, not an explicit clear, so it's swallowed by that protection every time — this is coreutils semantics, not the kernel/SGID behavior suspected above. Changing that one call tochmod 00700(or following it withchmod g-s,u-s --) should fix it directly, without needing the unmount/recreate workaround.Filed by Claude Sonnet 5 via Claude Code.
christianguenter2 commentedon Aug 31, 2026
Confirmed on Omarchy 4.0.2-1 with an AMD Ryzen AI 5 340.
~/Windowswas mode2700. The privileged helper'schmod 0700left it at
2700, causingprepare_caller_mounts()to fail silently.Explicitly clearing setgid fixed it:
Afterward, the VM migration completed and Windows launched successfully.
This appears to be documented GNU coreutils behavior rather than a kernel
regression: numeric modes of four or fewer digits preserve set-ID bits on
directories. Using
chmod 00700should explicitly clear them.drewdavies commentedon Sep 1, 2026
removeis blocked by the same gate, so the tool can't recover itself.__priv_remove()opens with the sameassert_mounts_safecall that__priv_up_wait()does (bin/omarchy-windows-vm:935), so it fails at the identical setgid check, andremove_windows()then exits before any user-side cleanup:removealways elevates ([[ $action != write_compose && $action != remove ]],:89), so there is no docker-group path around it.Repro on 4.0.2-1 from a working install:
chmod g+s ~/Windows— or just run the VM once; dockurr sets SGID on/sharedomarchy-windows-vm launch→❌ Failed to start Windows VM!omarchy-windows-vm remove, authorize the polkit prompt →❌ Windows VM removal stopped before user-side cleanupAfter step 3 here,
/var/lib/omarchy/windows/docker-compose.yml, thedockurr/windowsimage and~/.windows/data.imgwere all still present.This is likely the explanation for the "tried resetting PC, then reinstalling windows again, it fails" report above:
installdoesn't fail early either, becauseprepare_user_mount_sources()'schmod 0700(:1018) returns 0 while leaving the bit — it just fails again at the same check during bring-up.#9322 already covers this: patching
prepare_caller_mounts()fixesremoveandinstallalong withlaunch, since all three reach it viaassert_mounts_safe. No further code change needed — flagging only that the blast radius is wider thanlaunch, in case a removal-path fixture is worth adding.Env: Omarchy 4.0.2-1, kernel 7.1.9-arch1-2, GNU coreutils 9.11, btrfs.
chmod g-s ~/Windowscleared it with the anchor inode intact andlaunchcame straight up.Filed by Claude Opus 5 via Claude Code.
[-]Windows VM 4.0.2: launch fails silently after polkit auth (setgid chmod check can never pass)[/-][+]Windows VM 4.0.2: launch fails silently after polkit auth (chmod 0700 can never clear the setgid bit the check requires gone)[/+]bpidperygora commentedon Sep 1, 2026
Rewrote the issue body: the root cause is GNU
chmodpreserving setuid/setgid on directories for numeric modes shorter than five digits, not a kernel regression. Confirmed independently by @murilocb above — nothing to flag to Arch, and my earlier claim that an unprivileged user can no longer set SGID was wrong too.Also worth pulling out of the body, since it changes the severity: this isn't limited to installs upgraded from ≤ 4.0.1.
dockurr/windowssets the shared mount to2777on every container start, so a fresh 4.0.2 install hits the identical failure from its second launch onward.@Pinox this is why reinstalling doesn't help. As a stopgap,
chmod 00700 ~/Windows ~/.windowsimmediately before each launch clears the bit (chmod 0700will not).[-]Windows VM 4.0.2: launch fails silently after polkit auth (chmod 0700 can never clear the setgid bit the check requires gone)[/-][+]Windows VM 4.0.2: launch fails silently after polkit auth (setgid chmod check can never pass)[/+]Pinox commentedon Sep 1, 2026
thanks @bpidperygora. Yea installation did not do the trick. I'm a new user on Linux so getting some "practice" sorting out my installation flow of apps on Omarchy ;)) as these issues are highly probably and expected in a fast moving distro. Actually glad this is happening to me, must say I hope this projects moves in the direction of "software as code" removing all friction when these things happen especially if general consumers start embracing something like Omarchy.
davidboulay commentedon Sep 5, 2026
The
chmodroot cause above is right and I won't re-litigate it — independently reproduced here on 4.0.2-1 (kernel7.1.9-arch1-2, coreutils 9.11, btrfs):~/Windowsat2700,chmod 0700returning 0 without clearing it, andprepare_caller_mounts()returning 1 with no output at all.One correction worth making, because it changes the user stopgap and may matter for the fixtures in #9322 / #10046 / #10113:
dockurr/windowsdoes not re-apply2777on every container start. It only does so while the shared folder is empty.Both
chmod 2777calls in the image's/run/samba.sh(dockurr/windows:latest, image0cff9eb0e7ae) are gated on an emptiness probe taken at the top ofaddShare():A non-empty
~/Windowstakes the write probe at:128instead —mktempinside the share succeeds because samba runs as root, so a700mode doesn't block it — and lands onwritable=Y/empty=N. Nochmodruns at all, and the setgid bit is never re-applied.A/B on this machine, same install, nothing else changed:
~/Windowsat container start2777, then2700once the script's ownchmod 0700runs → every later launch fails700, unchangedThe second row is a real launch, not a staged one: Apps menu → Windows, ~5 minutes of RDP, closed normally so
launch_windowsranpriv down.~/Windowswas stilldrwx------ 700afterward, and the next launch came straight up.So as a stopgap that survives instead of needing to be repeated before every launch:
chmod g-s ~/Windowsonce, then leave any file in the folder. Samba's defaulthide dot files = yesis not overridden in the generatedsmb.conf, so a dotfile stays out of the guest's view.Two notes for the fix PRs:
2777on launch) is loosening the check for a mode the container only ever writes into an empty share — worth weighing against clearing the bits outright, since the empty-share case is also the one where none of the user's data is at stake.Env: Omarchy 4.0.2-1, kernel 7.1.9-arch1-2, GNU coreutils 9.11, docker 1:29.7.2-1, btrfs.
Filed by Claude Opus 5 via Claude Code.
josedamianm commentedon Sep 22, 2026
Still reproduces on the edge channel (
omarchy-dev 4.0.0.r2186.gee8ebf6-1, coreutils 9.11-2, kernel 7.2.5-4-omarchy, docker 29.8.1). So this isn't fixed in current source either. Thechmod 0700inprepare_caller_mountsis unchanged.After one VM boot,
~/Windowsis at2777. Trace frompkexec bash -x /usr/bin/omarchy-windows-vm __priv up_wait:Posted by Claude Opus 5 via Claude Code.
Endless3Cyb3r commentedon Sep 25, 2026
Still happens on Omarchy 4.0.4-1 (GNU coreutils 9.11, AMD Ryzen 7 9800X3D / RX 9070 XT).
What I see:
~/Windowsto2777.prepare_caller_mountsrunschmod 0700. GNU chmod keeps setgid on directories, so the folder is left at2700.$shared_mode != 700check then fails, and the launch aborts with a bare "Failed to start Windows VM!".It's 100% reproducible after any successful session, and clearing the bit by hand only fixes it for one boot.
#12323 looks like the right fix. Until it lands, my workaround is to point the
windows-vm.desktopExec at a wrapper that runschmod g-s ~/Windows ~/.windowsbeforeomarchy-windows-vm launch.dofus-ai commentedon Oct 2, 2026
Confirmed on Omarchy 4.0.4-1 using the Quickshell menu's Windows entry.
Reproduction:
stat -c '%a %n' ~/Windows; the shared directory is2700(drwx--S---).omarchy windows vm launch --keep-alive.Observed:
The container is not started on the failing attempt. The helper runs
chmod 0700but GNU chmod preserves the directory's setgid bit, so the subsequent exact-700check sees2700and exits silently. The Windows container logs show that it booted successfully when the directory is corrected.Workaround confirmed:
chmod g-s ~/Windows omarchy windows vm launch --keep-aliveAfter clearing setgid, the VM starts and the
xfreerdpwindow opens. The setgid bit is reintroduced by the container on a later startup, so the workaround has to be repeated until an upstream fix lands.Knutsi commentedon Oct 3, 2026
Also hit this on 4.0.4-1 (
/homeon btrfs): after a reboot, launch failed silently with~/Windowsat2700.On "clearing the bit by hand only lasts one boot": the bit comes from dockurr/windows
samba.sh, which runschmod 2777on the share when it is empty. If you also leave a file in the share, the bit stops coming back:After that,
~/Windowsand~/.windowshave stayed at700through several VM up/down cycles and a reboot here. It's a workaround, not a fix.prepare_caller_mountsstill needs to clear setgid explicitly (chmod 00700org-s), as the open PRs do.Posted with help from Claude Code.
omarchybot commentedon Oct 4, 2026
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