Commit fec2c34
Add a diagnostic job demonstrating the TokenOwner mechanism
Temporarily add a `diag-token` job to
`.github/workflows/cygwin-test.yml` that creates a directory through
four code paths and reports its NTFS Owner. The intent is to
empirically establish the cause of the Owner asymmetry that will be
described in detail by a later commit on this chain: a Cygwin or
Cygwin-derived runtime (`cygwin1.dll` for Cygwin git; `msys-2.0.dll`
loaded by Git for Windows's bundled MSYS2 `sh.exe`) rewrites the
process token's `TokenOwner` field at DLL initialization, and
`CreateProcessW` propagates that mutation to every descendant.
The four tests are:
| Test | Chain | Predicted Owner |
| ---- | ---------------------------------------------- | ------------------------ |
| A | PowerShell `New-Item` | `BUILTIN\Administrators` |
| D | Cygwin `mkdir` | `runneradmin` (197108) |
| F | Cygwin bash -> Git for Windows `git init` | `runneradmin` (197108) |
| G | PowerShell -> Git Bash -> PowerShell `New-Item`| `runneradmin` (197108) |
A is the Win32 baseline. The kernel-default `TokenOwner` for
`runneradmin`'s full administrative token is `BUILTIN\Administrators`,
because `runneradmin` is the built-in local Administrator (RID 500) and
`FilterAdministratorToken=0` exempts it from UAC token filtering.
D is the Cygwin baseline. Cygwin's `cygheap_user::init` calls
`NtSetInformationToken(TokenOwner, &user_sid, ...)` at DLL init, and
the resulting Owner reflects the rewritten token.
F is the load-bearing case. The child is a Win32 binary that loads no
Cygwin runtime of its own. It produces a user-owned `.git`, proving
that the rewrite performed by the parent Cygwin bash propagates through
`CreateProcessW`'s token duplication to a Win32 descendant.
G strengthens the case: the first and last links are pure Win32 (a
fresh PowerShell using its own `New-Item` builtin), and only the middle
link is a Cygwin-family runtime (Git for Windows's bundled MSYS2
`bash.exe`, linked against `msys-2.0.dll`). The directory is still
user-owned, proving the mechanism does not depend on git, on
shell-dispatch via `git submodule`, or on any property of the
final-link binary -- only on whether *some* process in the ancestry
has loaded a Cygwin-family runtime.
This `diag-token` job, like the `reproduce-safe-dir` matrix added in
the previous commit, is temporary and should be removed before this
work is integrated.
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>1 parent f4ce395 commit fec2c34
1 file changed
Lines changed: 67 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
102 | 102 | | |
103 | 103 | | |
104 | 104 | | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
105 | 172 | | |
106 | 173 | | |
107 | 174 | | |
| |||
0 commit comments