第 43 讲:Native 模块(Landlock)

DeepSeek Harness 源码解析 · 第 43 讲

DeepSeek Harness 源码-Native 模块(Landlock) 第 43 讲:Native 模块(Landlock) 💡 本讲一句话 当 bwrap(bubblewrap)因为没装、非特权 user namespace 被禁、或 LSM profile 拒绝 mount 而用不了时,DeepSeek Harness 靠一个纯 C 的 landlock-run 启动器兜底:它先给自己装一套 Landlock allow-list 规则集,再 exec 目标命令——规则集跨 execve 继承,整棵子进程树都被约束。读完你能带走三件事:为什么"自限然后 exec"比"包裹一个 namespace"更省依赖、ABI 协商如何区分 full/partial、以及 exit 125 + fatal line 双证据门是怎么避免把命令自己的非零退出误判成沙箱故障的。 一、为什么需要 Landlock 这一档 第 16 讲我们拆过沙箱隔离的四种后端:bwrap(Linux mount namespace)、Seatbelt(macOS SBPL)、e2b(远程)。但 bwrap 有一个硬前提——它要 unshare + mount,这在"没装 bubblewrap、非特权 user namespace 被内核禁掉( kernel.unprivileged_userns_clone=0 )、或 LSM profile 拒绝 mount"的机器上全部失效。Landlock 是 Linux 5.x 引入的 独立 syscall 家族 ,不需要 namespace、不需要 mount、不需要任何特权——它直接在内核里给当前进程装一套文件系统访问白名单。这正是 native/landlock-run 存在的理由:它是 Linux runner 链的第二档。 🎯 本讲源码地图 核心是 native/landlock-run/packages/entry/src/main.c (298 行,整个审计面就这一个 C 文件 + 内核稳定 syscall 契约);JS 侧是 packages/entry/src/index.ts (launcherPath/grantArgs/probe 三函数);消费方在 packages/sandbox/sandbox-local/src/index.ts + profiles.ts ;失败归因分类器在 packages/shell/bash-sandbox/src/helpers.ts 。 二、main.c:自限然后 exec 的 C 启动器 main.c (L58-94)开头做了一件很"审计友好"的事:它 不 include <linux/landlock.h> ,而是把 Landlock UAPI 结构体和访问位 逐字自定义 。注释里写得很直白——内核用户态 ABI 按契约是稳定的,自己定义既让构建不依赖工具链头文件的新旧版本,又让这些定义本身成为"这个启动器到底碰了哪些内核 API"的审计记录。 📄 native/landlock-run/packages/entry/src/main.c(L58-94,节选) struct landlock_ruleset_attr { // 规则集属性:声明本进程要"治理"的访问位,未列出的内核直接放行(allow-list 边界) uint64_t handled_access_fs; // 受治理的文件系统访问位掩码——这是整个沙箱白名单的范围 }; struct landlock_path_beneath_attr { // path-beneath 规则:对某路径子树授予一组具体访问 uint64_t allowed_access; // 该子树下允许的访问位(读/写/执行…) int32_t parent_fd; // 锚点 fd——规则以它指向的目录为根向下递归生效 } __attribute__((packed)); // packed:内核头文件里此结构是紧凑布局,用户态必须逐字节对齐否则 ABI 错位 #define LANDLOCK_CREATE_RULESET_VERSION (1U << 0) // create_ruleset flags 位:…

阅读全文:DeepSeek Harness 源码解析 第 43 讲