Repository navigation
[Windows] workspace-write 沙箱下受限子进程启动即 0xC0000142,且被当作普通退出码上报 #9336
Replies: 3 comments
|
Thank you for the control arms — the exclusion table and the "which chain" table are what make this usable, and the last line of your report is the part I want to pick up first. The diagnosability ask already has a user-facing answer, and it is a pluginClassifying "a confined child died in the loader with no output of its own" as a sandbox failure rather than a bare exit code is exactly what
That is the "sandbox unavailable" sentence, said next to the call that failed instead of in place of it. It also carries the honest part, which your report independently confirms: the status alone cannot name its own cause. The advice states that producers on both sides of the restriction land on this code, and it prints the one comparison that separates them rather than guessing — hold the command and the tool fixed, change only the mode, and see whether So the plugin covers the user-facing half (what the operator reads) for every mode and both stdio shapes; what stays upstream is the core half you asked for — Two things your report changes, and one of them is a correction to that pluginThe mode switch is necessary here but not sufficient — and the plugin currently presents it as sufficient. Its The mechanism you name is not the one the plugin attributes. The plugin currently frames this producer as the The coverage note is worth separating from the bug
That is a statement about why CI cannot catch this, and it is independent of the root cause you are still hunting: the checks exercise the one chain where the confined token behaves. Whoever ends up doing the kernel-level tracing you asked for may want the reproduction to come from the application's own chain, which is the opposite of what the terminal-driven harness naturally provides. One boundary I would hold in the meantime: your point that |
|
Both corrections promised in my earlier comment are now shipped, and your report changed the check itself rather than just its wording. 1. The mode switch is now step one of two, and your experiment is the reason. The plugin already covered this code with a producer whose discriminator was "hold the command and the tool fixed, change only the MODE". Your second table falsifies that as a complete answer: from the desktop chain, So the advisory now runs the check in two steps: step 1 is the mode switch (which confirms the sandbox is the difference), step 2 asks whether the runner owns a console — because a console-less host separates the two modes the same way. That second step is a separate report filed the same day, One honest note where the two reports do not agree: 2. The default-DACL ACE you suspected is now named — as a candidate, not as a finding. Your reasoning was right about the asymmetry and it is now stated precisely in the advisory, with the source it rests on. What the advisory does not do is promote it: it says the candidate is unmeasured, and it says why the obvious experiment is unsafe — every new object the confined process creates takes its DACL from that default, so an ACE removed to test the theory takes every piped grandchild spawn down with it ( 3. Your point is now in the text with the authority it deserves rather than as a remark: the backend's README states that under On your appendix (the diagnosability defect): agreed, and it is upstream's to fix — the plugin cannot reclassify a success into a runner failure, because Install: |
来自第二台机器的独立复现(Win10 19045 / 桌面版 0.2.0-rc.2)先说有用的部分:同一症状、不同机器、不同安全软件、宿主控制台状态直接可测 —— 1. 环境与现象
2. ★ 本机只有 Windows Defender(没有第三方安全套件)你报告里"安全软件是否参与尚未定论",我这里可以当一条对照: → 第三方安全套件不太可能是必要条件(当然不能反过来完全排除 Defender 参与)。 3. ★ 宿主进程确实没有控制台 —— 这是直接测量,不是推断判据: 先用"我自己带控制台的 pwsh"验证判据有效,再逐个测桌面版的进程:
也就是说:#9238 里"宿主是否拥有控制台"这个变量,在本机能直接观测到答案是没有。 4. ★ 但这个宿主无法从外部补上控制台(三种办法都实测失败)
结论:只有进程自己调 5. 对"控制台拓扑"这条线的具体建议#9238 已经测出:隐藏控制台的
桌面版是 GUI 子系统程序,它自己永远不会有控制台(本机 8/8 实测), 6. 一个我无法回答的不一致(但本机正好是干净实验台)#9238 的规则是"宿主有控制台 × 受限令牌",但你的实验里 我这台只测了 7. 一句旁证(关于可诊断性)你们建议把"受限子进程以加载器状态码死亡且自身无输出"归类为 |
Uh oh!
There was an error while loading. Please reload this page.
Summary
Windows 10 22H2 上,默认
workspace-write沙箱下任何受限子进程(cmd、PowerShell 7.6.6、Windows PowerShell 5.1)都在加载阶段以0xC0000142 (STATUS_DLL_INIT_FAILED)终止。pwsh工具因此每次只返回空输出 +[exit code: 3221225794],模型和用户都看不出这是沙箱故障。同一台机器上:
read-only模式正常;同一沙箱 runner 的完全相同调用从普通用户进程链启动时,workspace-write也正常,且越界写入被正确拒绝。Reproduction
1)桌面应用内最小复现
任何
pwsh调用(例如pwsh -Command "'hello'")→ 空输出 +[exit code: 3221225794];同一条命令加sandbox_permissions: danger-full-access单次重试 → 正常返回。会话当前权限模式即默认的workspace-write。2)绕开 harness,直接调用沙箱 runner
在桌面应用的进程链里运行,得到:
cmd /c echopwsh -Commandcmd /c echopwsh -Commandpowershell.exe(5.1)即
cmd同样死亡 —— 与 PowerShell、与 .NET 无关。3)启动链对照(关键)
同为
explorer → cmd → pwsh这条普通用户进程链,用同样的 argv 调同一个 runner:结论:失败需要「桌面应用的启动链」与「workspace-write 令牌」同时成立;两者单独都不复现。
Current behavior
3221225794/0xC0000142表示进程在加载阶段就失败,所以连echo都没有输出;不是超时、不是被杀(被杀在本仓库表现为 exit 1),也不是策略拒绝(那会带[sandbox: file access denied under <mode> mode])。退出码 127+ stderr 带windows-acl-run:前缀才被判定为 runner 失败(packages/sandbox/sandbox-local/src/index.ts的RUNNER_FAILURE_RULES;signature 由packages/sandbox/sandbox-windows-acl/src/runner.ts打印)。子进程在加载期死亡既不满足退出码、也没有输出,于是用户只看到一个无法解释的退出码。read-only不能作为通用替代:该模式下 pwsh 会进入 ConstrainedLanguage,[System.IO.File]::*、Get-CimInstance等被拒(与包 README 记录的 AppLocker 探针行为一致)。Expected behavior
workspace-write下受限子进程应能正常启动(其令牌构造仅比read-only多两个写 SID);SANDBOX_UNAVAILABLE)并给出原因,而不是裸退出码。Environment
已排除的变量
以下每一项都单独改过并且不改变结果:
cmd /c echo亦失败)FILE_DELETE_CHILDdeny、低完整性标签全部不施加(manageDacls: false的 seam-managed 调用)windowsHide(true/false)CreateAppContainerProfile)KILL_ON_JOB_CLOSE作业)尚未定位(请求帮助的方向)
workspace-write相比read-only唯一剩下的令牌差异是packages/sandbox/sandbox-windows-acl/src/workspace-sid.ts派生、经token.ts::createRestrictedToken进入限制列表、并经index.ts的setTokenDefaultDaclGrant进入令牌默认 DACL 的两个合成S-1-4-…SID。按写限制令牌的语义,往限制列表增加 SID 只会放宽写权限;因此更可疑的是默认 DACL 中那条指向合成 SID 的 ACE。但为何必须叠加"桌面应用启动链"才复现,我们无法在本机定位到内核环节,需要内核级跟踪或干净的对照机器。旁证一条,可能有助于判断 CI 为何未覆盖:仓库的 Windows 检查在终端驱动的普通用户进程链里运行,而本次实验显示那条链恰好是能正常工作的配置。
附带的可诊断性缺陷
建议把"受限子进程以加载器状态码死亡(如
0xC0000142)且自身无输出"归类为 runner failure /SANDBOX_UNAVAILABLE,让用户看到的是"沙箱不可用:受限子进程加载期失败(0xC0000142)",而不是一个裸退出码。这条与主问题独立,改动小、收益直接。All reactions