Replies: 1 comment 1 reply
|
我遇到了同样的问题,Windows 上 pytest 的 tmp_path 测试全部失效,Python 3.11.15 / 3.13.14 + pytest 9.1.1 均复现 我制作了一个临时的插件来缓解这个问题:dsh-python-tempfile-shim。 通过注入 sitecustomize shim 使 os.mkdir 忽略 mode,如有需要可在官方解决该问题前尝试该方案。 |
1 reply
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
摘要
在 Windows 的 workspace-write 会话里,Python(UCRT)以
os.mkdir(path, 0o700)创建目录时(tempfile.mkdtemp/ pytesttmp_path的标准路径),CRT 会把 POSIX mode 翻译成一个显式安全描述符:[SYSTEM: 完全控制、Administrators: 完全控制、OWNER RIGHTS: 完全控制](全部可继承)。显式描述符使该目录不继承父目录的任何 ACE(包括沙箱的 workspace capability SID)。而沙箱的 WRITE_RESTRICTED 令牌只在其 restricting SIDs(logon SID / Everyone / workspace SID / temp SID)有对应 ACE 的地方放行写入;该目录四条都不满足,OWNER RIGHTS 不参与受限二次检查——于是连创建它的进程自己都无法再在该目录里写文件、列目录、删除内容(PermissionError: [WinError 5]/[Errno 13])。这完整解释了 #81 的全部现象(93 个 tmp_path 夹具 error、basetemp 扫描失败、会话结束后残留"锁死"目录无法清理)。已在 rc.6 + Python 3.14(Windows 11)上端到端复现,并用对照实验锁定 mode 是唯一触发变量。复现步骤(实证,已复现)
os.mkdir(ws + r"\d1", 0o777)→ 目录正常继承全部 ACE,可写可列。os.mkdir(ws + r"\d2", 0o700)→ 目录 ACL 变为SYSTEM:(OI)(CI)(F) / Administrators:(OI)(CI)(F) / OWNER RIGHTS:(OI)(CI)(F),立即自锁(与 pytest 现象一字不差)。
mkdir(无 mode 语义)→ 正常继承。根因(两层)
_wmkdir(path, mode)把 mode 翻译成显式安全描述符(mode≠0o777 时物化);
tempfile.mkdtemp/ pytesttmp_path传 0o700 →目录带 [SYSTEM/Administrators/OWNER RIGHTS] 显式 ACL,不继承父目录 ACE。
dsh-sandbox-windows-acl):WRITE_RESTRICTED 令牌的写入放行条件是目标 DACL 中存在 restricting SIDs 之一的写 ACE。该目录的 ACL 不含 logon SID、
Everyone、workspace capability SID、temp SID 中任何一个;OWNER RIGHTS(S-1-3-4)
只参与第一遍全量检查、不参与 restricted 第二遍交集检查 → 创建者本人也拿不到写权限。
这是受限令牌的标准语义,不是实现 bug——但产品没有处理"进程用显式描述符创建对象"
这个真实世界高频模式(所有 POSIX-mode 语义的工具:pytest、rsync、git-for-windows
的部分路径、Node 的 mkdirSync(mode) 等同理)。
建议修复
workspace-write 工具调用前)扫描工作区树,对缺 capability ACE 的目录执行
grantWrite(合并进现有显式 DACL,保留 CRT 的 ACE)。此修复同时解决 [Bug] Windows 下,工作区连接后新增的子目录无法写入 #401(移入目录永不补授)与本问题——两个 bug 共用同一个补授缺口。
写明"以 POSIX mode 创建目录(pytest/mkdtemp 默认行为)会导致自锁"。
danger-full-access(不受限令牌凭 owner权限即可读写这些目录,已验证);
sitecustomize.py把tempfile.mkdtemp包裹为os.mkdir(path, 0o777)再返回路径。
影响
tmp_path/tmp_path_factory的测试套件 100% 报错(发现一个DSH沙箱导致的pytest生成文件无法访问,进而导致的pytest产生错误的问题 #81:522 passed + 93 errors)
tempfile.mkdtemp/os.mkdir(mode)类工具(含部分打包器/解压器)产出的目录自锁,残留目录连后续会话都无法清理(各会话 temp SID 不同)
环境
验证材料
bug-81/repro/(probe.py / probe2.py / probe3.py + icacls 记录)锁定目录同样适用(grantWrite 合并进显式 DACL)
First analysis of discussion #81. Happy to open a PR with fix option A (shared with #401/#423).
All reactions