Repository navigation
Replies: 6 comments 1 reply
|
补充一组对照实验,把范围从「受限令牌 × 无控制台」再收窄一步。环境与楼主不同:Windows 10 22H2 19045.6332、DSH 桌面版 0.2.0-rc.2、pwsh 7.6.6 商店/MSIX 版。结论一致,且可复现。
1. 模式 × 子系统对照(用包内 confinement runner,standalone 模式)
读法:① 受限令牌本身能起进程并正常退出( 宿主侧 2. 两种模式在代码里的差异只有三处(
|
| 位置 | 代码 | 是不是差异点 |
|---|---|---|
| L1291 | restrictTokenIntegrity(api, restrictedToken, lowLabelSid) |
❌ 两种模式都执行(都降到 Low 完整性) |
| L1293 | setTokenDefaultDaclGrant(api, restrictedToken, this.tempWriteSidPtr ?? this.writeSidPtr ?? worldSid) |
✅ read-only 回退到 EVERYONE;workspace-write 回退到工作区/临时能力 SID |
| L885 | mode === "read-only" ? [logonSid, world] : [logonSid, world, ...writeSids] |
✅ restricting 列表 |
| runner | workspace-write 把 TMP/TEMP 改写到私有临时目录;read-only 不动 |
✅ |
关键悖论:workspace-write 的 restricting 列表是 read-only 的超集(多了工作区/临时 SID),理论上更宽松,实际却更坏。所以问题不在「限制条目多少」,而落在 token 默认 DACL 的受托人(L1293)或 TMP/TEMP 改写 这一层 —— loader 初始化期创建的内核对象走的就是 token 默认 DACL,而 read-only 那一档命名的是 EVERYONE(两种 restricting 列表里都存在),workspace-write 那一档命名的是能力 SID。
3. 已排除项
- 与 shell 选择无关:未装 pwsh 时、商店版 pwsh、系统
cmd.exe、Windows PowerShell 5.1 —— 报错完全一致; - 与 pwsh 安装形态无关:楼主用 MSI 版同样复现,我用商店版同样复现;
- 与工作区 ACL 无关:包内
diagnose-windows-sandbox-acl.ps1判定VERDICT=NOT_THIS_CLASS(writeDac=true、writeOwner=true、零改动)。
4. 请求
- 确认
workspace-write的 token 默认 DACL 受托人是否应包含 EVERYONE(或保活组)——若是,L1293 的?? worldSid回退顺序可能需要调整; - 在文档中标注桌面端 + Windows 的现状与可行路径(
dsh web从控制台启动); - 让这类早亡至少落一条可读诊断:目前
0xC0000142既不匹配RUNNER_FAILURE_RULES['windows-acl']的127,也没有windows-acl-run:前缀,于是只是一条普通非零退出,现场没有任何线索。
English TL;DR: On Windows 10 22H2 (19045) with the DSH desktop host, workspace-write kills every console-subsystem child with 0xC0000142, while read-only runs cmd.exe and pwsh fine, and a GUI-subsystem child (rundll32) exits 0 even under workspace-write. The two modes differ in exactly three places in AclSandbox.init(): the integrity lowering is shared (L1291), while the token default DACL trustee (L1293: tempWriteSid ?? writeSid ?? worldSid → EVERYONE under read-only vs a capability SID under workspace-write) and the TMP/TEMP rewrite are not. Note the restricting list under workspace-write is a superset of read-only's, so "fewer entries" cannot be the cause here. Workspace ACLs were ruled out (NOT_THIS_CLASS). Repro: drive dsh-sandbox-windows-acl/lib/runner.js directly in both modes and compare exit codes.
|
补一条决定性对照(晚于上面那条)。把
有控制台宿主下 一个可能的统一解释(供定位参考,未确认):
注意 另提醒一个安装形态差异:本机 CLI 入口 顺带一个测量坑:探控制台必须用设备路径 |
|
我此前全给权限给他也会出现这样的情况,频繁弹窗显示这个报错,似乎是git的报错,win11,npm安装,版本同上 |
|
Thanks — this is a well-built report, and the matrix converges with two source facts plus the console/host control another commenter ran. Adding what I can from the shipped code, because the "no readable diagnosis" half of your request is directly actionable. 1. Why you get a bare NTSTATUS and nothing else. That is by construction, not an oversight in the runner. const RUNNER_FAILURE_RULES = {
// ...
'windows-acl': [{ allowedExitCodes: [127], fatalSignatures: ['windows-acl-run: '] }],
}Only exit 2. The restricting-list rule the third commenter derived matches the source's own construction. That is the "superset yet worse" paradox in one line: 3. The console co-factor is already in the repo's own limitation list ( 4. On your request (2): this failure does become a diagnosis today — in a plugin. 5. Honest boundary. The mechanism behind the denial is not localized upstream either — |
|
更正:我上一条结论错了,收回。 我上条断言「宿主无控制台」和「L1293 默认 DACL」都不成立,并给出「当且仅当」规则。补做 2×2 后,这是错的:
是两项的合取,不是充要条件。我上次测 L1293 时,命令恰好跑在有控制台的 pwsh 里,落在第四格 —— 那一格怎么改都活,于是我把「无论怎么改都 exit 0」误读成了「DACL 无关」。这正是合取条件最容易踩的坑,是我的疏忽。@ismoss 的 L1293 假说、@argszero 的控制台 co-factor 都是对的。 在无控制台宿主里重测,机制就清楚了。 固定用真实的
可见与 restricting 列表本身无关,只改 DACL 受托人即可救活。 统一解释:WRITE_RESTRICTED 下访问检查走两遍(pass-1 用令牌普通 SID,pass-2 用 restricting)。 两条独立的逃生路径也由此对齐:1 控制台可继承则无需创建 → 活;2 默认 DACL 受托人换成已启用组( 修订后的请求:建议调整 L1293 —— 能力 SID 继续只用于 restricting 列表,默认 DACL 始终命名保活组(或 EVERYONE)。这样 环境:Windows 10 22H2 19045、DSH 0.2.0-rc.2、 |
|
The analysis above is now shipped as an advisory — Mount it in your dsh profile (the package ships a What 0.20.0 adds because of this thread: the Two shapes from the same wave are carried as scope, and deliberately not claimed: #9463 (the same backend stalling before any child is spawned at all — no approval event, no process) and #9471 (a child that starts and then dies loading a library at runtime, with a message and a code of its own). Classifying either as this family would be a confident wrong cause; an advisory that names two threads is more useful than one that names the wrong one. Repo: https://github.com/argszero/cordis-plugin-sandbox-grant-advisor |
Uh oh!
There was an error while loading. Please reload this page.
反馈:Windows 10 上 workspace-write 沙箱模式下 pwsh 工具 100% 崩溃(0xC0000142)
环境信息
C:\Program Files\PowerShell\7,在系统 PATH 中)现象
workspace-write 模式下,pwsh 工具执行任意命令均失败:
Write-Output ok亦崩)。同一会话切回"完全权限"后,同一 pwsh 命令立即恢复正常(版本 7.6.3、
$PSHOME正常)。复现步骤
Write-Output ok;[exit code: 3221225794];已做的排除与诊断
pwsh -NoProfile -Command正常;官方 MSI 默认位置,PATH 解析正常(Get-Command pwsh -All仅此一个)。C:\Program Files\PowerShell\7全部 827 个文件。windows-acl-run:stderr 前缀、无 exit 127;推断dsh-sandbox-local成功以受限令牌 spawn 了 pwsh,崩溃发生在 pwsh 进程自身的早期 DLL 初始化阶段。Get-AppxPackage Microsoft.PowerShell*为空);用户先前"商店版可用"的时段对应旧版 DSH(无当前沙箱机制),并非安装方式差异。与 DSH 文档/源码注释的对照
DSH 打包文档(sandbox-windows-acl)与源码注释中记载:
\Device\CNGwrite trustee)会让 pwsh 崩 0xE0434352;CREATE_NO_WINDOW/CREATE_NEW_CONSOLE创建的子进程在 DLL 初始化期间死于此码(0xC0000142),并注明"children share the host console";怀疑方向:Win10 与 Win11 在控制台子系统及相关内核对象(
\Device\ConDrv、conhost 创建路径)或\Device\CNG的 DACL 上存在差异,导致 WRITE_RESTRICTED 令牌的 pass-2 检查在 Win10 上失败(例如控制台初始化依赖被有意排除在限制列表外的 S-1-2-1 console logon SID;或 DSH 宿主为无控制台的 GUI 进程时,pwsh 需要新建控制台而触发该路径)。影响
建议
\Device\ConDrv、\Device\CNG在 WRITE_RESTRICTED pass-2 检查下的行为差异;All reactions