Appearance
沙箱系统 — 练习
练习 1:分析 Landlock 规则配置
阅读 codex-rs/sandboxing/src/ 中的 Landlock 相关代码,分析文件系统权限规则的定义方式。
参考答案
Landlock 的规则配置在 sandboxing/src/ 目录中分为几个层次:
规则定义:在
landlock模块中,文件系统权限通过 Landlock LSM 的landlock_rules定义。核心是区分三类访问:- 可读写(
access-fs):仅 workspace 目录及其子目录,代理可在此创建、修改、删除文件 - 只读(
access-fsread-only):系统目录(/usr、/lib、/bin)、Cargo 缓存等,代理可读取但不能修改 - 完全禁止:敏感路径(
~/.ssh、~/.gnupg、~/.aws),代理完全无法访问
- 可读写(
Bubblewrap 集成:
bwrap模块使用 Bubblewrap 创建新的 mount namespace,将上述 Landlock 规则映射为--bind(读写)、--ro-bind(只读)、--tmpfs(临时文件系统)等挂载参数。辅助二进制:
linux-sandbox/src/lib.rs的run_main()是独立的沙箱入口,它首先在进程内应用 seccomp 限制,然后执行被包装的命令。launcher模块负责启动这个辅助二进制。权限配置:
SandboxTransformRequest中的sandbox_policy_cwd字段指定 workspace 根目录,additional_permissions列表包含用户审批后临时授予的额外权限。
这个设计确保了即使代理生成了恶意命令,也无法越出 workspace 目录的边界。
练习 2:对比 Landlock 和 Seatbelt 实现
对比 Linux 和 macOS 两个平台的沙箱实现,总结共性和差异。
参考答案
共性:
- 两者都通过
SandboxManager::transform()统一接口调用,对外暴露相同的SandboxExecRequest - 都支持
additional_permissions动态扩展权限 - 都通过
ExecPolicy策略层在命令执行前评估权限(Allow/Prompt/Forbidden) - 都限制了文件系统访问范围,确保代理只能操作 workspace 目录
差异:
| 维度 | Landlock (Linux) | Seatbelt (macOS) |
|---|---|---|
| 底层机制 | LSM 内核模块 + seccomp | sandbox-exec 系统调用 |
| 隔离方式 | Bubblewrap 命名空间 + Landlock 文件规则 | plist 声明式规则 |
| 辅助二进制 | 需要 codex-linux-sandbox 独立进程 | 不需要辅助进程 |
| 网络隔离 | 通过 NetworkSandboxPolicy 控制 | 通过 Seatbelt 规则控制 |
| 配置格式 | Rust 代码中的规则构建 | 动态生成的 plist |
| 错误处理 | SandboxTransformError::MissingLinuxSandboxExecutable | SandboxTransformError::SeatbeltUnavailable |
核心洞察:SandboxManager 的设计让平台差异对上层透明。select_initial() 根据 SandboxablePreference(Auto/Require/Forbid)和当前平台自动选择合适的沙箱类型,调用者无需关心底层实现。
练习 3:测试沙箱边界
分析代理在沙箱限制下的行为边界,哪些操作被允许、哪些被拒绝。
参考答案
沙箱边界由 ExecPolicy 和平台沙箱共同定义,形成两层过滤:
第一层:ExecPolicy 策略评估(Policy::check())
- 自动允许(Allow):常见的只读命令(
ls、cat、grep、git status)、构建工具(cargo build、npm install在 workspace 内)、测试运行 - 需要审批(Prompt):文件删除(
rm)、系统包安装(apt-get、brew)、网络请求(curl、wget) - 直接拒绝(Forbidden):明确的危险操作、覆盖关键系统文件
第二层:平台沙箱隔离
- 文件系统:代理只能读写 workspace 目录内的文件;系统目录只读;敏感目录(
~/.ssh、~/.gnupg)完全不可见 - 网络:通过
NetworkRule控制可访问的域名,默认限制为必要的 API 端点 - 进程:Linux 上通过 PID namespace 隔离,子进程继承限制
边界测试场景:
cat /etc/passwd→ ExecPolicy Allow + 沙箱只读 → ✅ 成功echo test > ~/outside.txt→ ExecPolicy Allow + 沙箱文件系统拒绝 → ❌ 失败rm -rf /→ ExecPolicy Forbidden → ❌ 直接拒绝ssh user@host→ 沙箱阻止~/.ssh访问 → ❌ 无法认证
这种双重防御确保了即使某一层被绕过,另一层仍然提供保护。
拓展挑战
- 阅读
SandboxManager::transform()的完整实现,理解命令包装的具体步骤 - 分析
linux-sandbox/src/lib.rs中 seccomp 规则的定义 - 对比
SandboxablePreference::Auto在不同平台上的默认选择逻辑 - 追踪
additional_permissions从用户审批到沙箱应用的完整路径