Skip to content

fix(toolchain): #273 sandbox containment — explicit trust root for post-install rewrites (+ CI wine cache)#275

Merged
Sunrisepeak merged 2 commits into
mainfrom
fix/patchelf-sandbox-containment
Jul 23, 2026
Merged

fix(toolchain): #273 sandbox containment — explicit trust root for post-install rewrites (+ CI wine cache)#275
Sunrisepeak merged 2 commits into
mainfrom
fix/patchelf-sandbox-containment

Conversation

@Sunrisepeak

Copy link
Copy Markdown
Member

Fixes #273

沙盒围栏:显式信任根,非启发式设计

整体评估发现入口层自 #109 起已有 ownership guard 与内容指纹 marker——事故主向量在当前 main 已被入口挡住(损坏应发生于更早版本)。本 PR 修复其三处残余缺口,并把围栏下沉为架构级契约:

  1. error_code 复用:旧 guard 两次 weakly_canonical 共用一个 ec,第二次成功清掉第一次失败,判定可基于空路径。
  2. 裸字符串前缀无组件边界:<registry>-evil 兄弟目录能穿过 starts_with
  3. binutils 兄弟目录 walk 不在 guard 内:gcc fixup 通过入口 guard 后还会 walk binutils 各版本目录,若其被符号链接指向外部,入口 guard 管不到(toolchain: patchelf_walk follows symlinks out of the sandbox and corrupts the user's real ~/.xlings gcc payload (e2e 13_toolchain_pin.sh seeds via ln -s; PT_INTERP left dangling into a deleted mktemp dir) #273 事故里只是碰巧 binutils 是真实下载)。

设计

  • 信任根 = cfg.registryDir(系统一等事实),containment_root() 在入口 canonical 化一次,作为显式参数穿透到所有改写者(patchelf_walk 逐文件、fixup_gcc_specs/fixup_clang_cfg 入口)——绝不从 payload 路径反推(先 canonical 化 payload 会把恶意符号链接解析掉,围栏沦为恒真式)。
  • fail-closed:空根或路径不可解析 → 视为逃逸,拒绝改写。
  • 判定谓词 escapes_containment 独立导出,单测复刻事故拓扑(symlink payload、.. 穿越、兄弟前缀、空根)。
  • 13_toolchain_pin.sh 的 symlink 种子有意保留为真实环境金丝雀(围栏后无害;若围栏回归,机器上的 gcc 会立刻大声坏掉)。

附带

  • cross-build CI 的 wine 安装缓存 .deb 依赖闭包(固定包集,首跑回填、命中免 apt update/下载,~1-2min/轮)。

验证

  • 新单测 8/8;全量单测 37/37;e2e 152–160 + 13(金丝雀)全绿。

…ed through every post-install rewriter

- containment_root(cfg.registryDir) resolved once at entry, passed down;
  never re-derived from payload paths (canonicalizing the payload first
  dissolves the fence)
- per-file fence in patchelf_walk covers interior symlinks AND the binutils
  sibling walks the entry ownership guard never vetted
- entry guard rewritten on the shared predicate: fixes error_code reuse
  masking failures and raw-string prefix matching without a component
  boundary; fails closed on unresolvable paths
- unit tests pin the incident topology (symlinked payload, dot-dot
  traversal, sibling string prefix, empty-root fail-closed)
- 13_toolchain_pin.sh symlink seed kept as a live canary (now harmless)
- CI: cache wine .deb closure in cross-build workflow
@Sunrisepeak
Sunrisepeak merged commit dea5f1f into main Jul 23, 2026
15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant