# 沙箱 沙箱使用 Linux Landlock 将进程限制在一组可配置的文件系统路径内。它需要显式启用,在所有宿主(`deft`、`retro`、`retra`)中均可用,并由内核强制执行——越出授权路径的 `[fs/write]` 或文件打开操作会直接失败,而不会静默成功。 网络不受限制。Landlock 仅针对文件系统;进程保持完整的网络访问。 ## 启用 在环境中设置 `DEFT_SANDBOX=1`(或 `true`): ```bash $ DEFT_SANDBOX=1 deft script.dft $ DEFT_SANDBOX=1 retro ```` 未设置该变量时,沙箱不生效。在非 Linux 平台以及不支持 Landlock 的旧内核(内核 5.13+,见 内核支持)上同样不生效;这些情况会打印一条消息并继续以非沙箱方式运行,而不是拒绝启动。 沙箱在预置文件和配置注册表加载之后、用户代码运行之前、TUI 事件循环启动之前生效,因此所有初始化读取都已完成。启用是一道单向门(`landlock_restrict_self`):进程此后永远无法扩大自身的访问权限。 ## 配置 静态路径列表位于项目预置文件的 `:sandbox` 键下(见预置文件):
%Prelude{
    :sandbox %{
        :readonly @{ "/etc" "/usr/bin" "/usr/lib" "/usr/lib64" "/usr/share" "/proc" "/sys" }
        :writable @{ "~/.config" "~/.local" }
    }
}
- `:readonly` —— 可读(并可执行)但不可写的路径。 - `:writable` —— 完全可写的路径:读取、写入、创建、删除。 两个列表都是可选的。应用沙箱时,开头的 `~` 会展开为 `$HOME`,因此 `"~/.config"` 会授权真实主目录下的该子树。 `deft init` 会为你写入一个模板 `:sandbox` 块。你可以直接在 `.deft/prelude.dft` 中编辑这些列表,也可以使用 `deft sandbox` CLI 代为编辑: ``` $ deft sandbox list # show both lists $ deft sandbox add /srv/data # add read-only $ deft sandbox add ~/code/write-dir -w # add writable $ deft sandbox remove /srv/data ```` 完整的子命令参考见 [`deft` 二进制文件](/docs/cli?lang=zh)。 ## 始终授予的权限 运行时自身会应用一小组宿主必需、由环境派生的授权,且无法通过编辑去除: | 路径 | 访问权限 | 原因 | |------|--------|-----| | cwd 子树 | 完全 | 运行时所在的项目 | | `/tmp` | 完全 | 临时文件、套接字 | | `$XDG_RUNTIME_DIR` | rw socket | Wayland/X11 合成器套接字 | | `$HOME` | 只读 | Xauthority、fontconfig 缓存、配置读取 | | `/dev`、`/dev/pts` | rw + ioctl | GPU 渲染节点、输入、集成终端 PTY | | `/` | 仅执行 | 二进制文件的绝对路径解析 | | 字体路径(TUI) | 只读 | 当配置的字体位于 cwd + `/tmp` 之外时 | `:writable` 列表中的可写子树(如 `~/.config`)在同一规则集内与只读的 `$HOME` 规则求并集,因此它们变为可写,而不会扩大主目录其余部分的权限。 ## 语义与限制 - 目录粒度的授权。 规则以目录为根并覆盖其子树。添加指向文件的列表项会发出警告并被跳过——应改为添加其父目录。 - 单向门。 启动后,进程的文件系统视图在其生命周期内固定不变。不存在运行时逃生通道。 - 仅限文件系统。 套接字、网络和进程信号不受影响。这不是完整的安全沙箱——对于不可信代码,应配合 `runtime/*` 堆隔离使用(见运行时);子运行时共享同一进程,因此也共享同一个沙箱。 - 不是逐应用的边界。 沙箱约束的是整个进程。TUI 宿主中的所有面板以及所有子运行时都运行在同一组授权之内。 ## 内核支持 系统会自动检测 Landlock ABI,并使用所支持的最广泛访问权限集: | ABI | 内核 | 说明 | |-----|--------|-------| | v6 | 6.13+ | 作用域访问 | | v4 | 6.7+ | 规则集属性中的 networking 字段 | | v3 | 6.2+ | 最高支持 `TRUNCATE` | | v2 | 5.19+ | 最高支持 `REFER` | | v1 | 5.13+ | 基线:读/写/创建/删除/执行 | 在不支持 Landlock 的内核上,进程会打印 `sandbox: landlock unavailable (kernel too old)` 并继续不受限制地运行。 ## 诊断 被拒绝的操作会以常见的操作系统级错误失败(`permission denied`、打开时的 `no such file or directory`),并作为 `fs/*` 和 `sqlite/*` 标准库函数抛出的普通 Deft 错误呈现。检查启动行 `sandbox: active (landlock, cwd + /tmp + prelude paths)` 以确认沙箱已生效,然后将缺失的路径添加到相应的列表: ``` $ deft sandbox list read-only: /etc /usr/bin writable: ~/.config $ deft sandbox add ~/data -w added ~/data (writable) ```` ## 另见 - 预置文件 —— `:sandbox` 键位于 `.deft/prelude.dft` - [`deft` 二进制文件](/docs/cli?lang=zh) —— `deft sandbox` 子命令 - 运行时 —— 堆隔离与操作系统沙箱的对比