oss

Landlock 让进程在身后锁上门

7 条来源 5 条一手来源 已翻译 2026年8月12号

正文
Mickaël Salaün 在座无虚席的 FOSDEM 2023 教室里讲解 Landlock 的兼容性。

Mickaël Salaün 在 FOSDEM 2023 Rust 开发者会场讲解 Landlock 的兼容性模型。Thomas Debesse 摄影,经裁剪,CC BY 4.0。[7]

视频模式

本文包含 1 个可跳转的视频片段。

  1. 1 Mickaël Salaün 讲解 Landlock 的无特权 Linux 自我沙箱 YouTube 视频

大多数 Linux 安全策略都由进程之外的上层角色制定。管理员配置 LSM,容器运行时组合命名空间,服务管理器决定某个单元可以接触哪些资源。Landlock 则把收紧权限的决定交给进程自身:普通进程可以要求内核削减自己原本拥有的访问权限,然后继续运行,再也无法撤回这项决定。

这项单向性是 Landlock 设计的重心。它无权授予文件权限、削弱 SELinux,也无法挣脱父级策略,只会再叠加一层拒绝。应用开发者由此可以仅凭原有权限,把访问控制策略与受保护的行为一同发布。Mickaël Salaün 在 Open Source Summit Europe 2024 的演讲值得细看,因为他讲清了这份契约的两个方面:自我沙箱何以安全,以及一项安全的内核功能会怎样因接入方式有误而留下缺口。[1][2]

这场演讲也展示了克制的 API 设计。实际使用的界面只有三项 Landlock 系统调用、一个规则集文件描述符、显式权限掩码和一次不可逆转的切换。真正费工夫的是界面之外的决策:选择进入沙箱的时点,识别当前内核支持的能力,并如实处理旧内核。所有相关线程也必须进入受限域。

图像背景:封面是一张摄于 Salaün 在 FOSDEM 2023 讲解安全功能向前与向后兼容性时的真实照片,Landlock 正是演示案例。照片早于文中嵌入的 2024 年演讲,却记录了同一位维护者讲授同一个兼容性问题。[7]

Linux 基金会于 2024 年 9 月 17 日在维也纳录制了下面这场演讲,并发布在官方频道。配套幻灯片收录了演讲中的代码片段和已采用 Landlock 的项目清单。[1][2]

约 03:19 — 访问控制与环境封装解决不同的问题

演讲开头,Salaün 依次谈到虚拟机、容器、系统级 LSM 策略、BPF LSM 和 seccomp。这些方案各自回答不同的问题,比较的重点在于分清职责。虚拟机或容器会改变执行环境,seccomp 会缩小系统调用范围,SELinux 与 AppArmor 能表达覆盖全系统的访问规则,Landlock 则让进程用应用自身的策略限制对内核对象的访问。[2][4]

这一区分很重要,因为“放进容器里运行”一句话经常把数道界线混在一起。容器可以让程序只看到较窄的文件系统范围,这项部署配置通常掌握在运维层。seccomp 过滤器依据系统调用编号和参数拒绝调用;语义层面的文件授权属于另一类工作。Landlock 能为某条路径之下的层级规定允许的文件系统操作,也能用网络规则描述端口。它与这些工具相互补充,各自保持原有职责。演讲在 07:42 给出的沙箱定义点明了实际要求:环境只应暴露软件获准使用的资源。[2]

这个思路也解释了 Landlock 为何历经多年才进入主线内核。内核要接受一个无特权调用者提交的策略,而该调用者已经遭到入侵也在设计考虑之内;与此同时,调用者不能干扰其他进程,内核也不能因此暴露新的提权入口。最终确定的规则只会限制调用者所在的域,可以与现有访问控制逐层叠加,多层组合后限制只会继续收紧。维护者的设计论文和 LWN 对上游历程的记述,比功能清单更能显出这项约束。[5][6]

约 09:01 — 进程只能削减权限,永远不能凭空增加

演讲在系统调用讲解之前就提出了最重要的安全性质:Landlock 策略具有单调性。约 09:01,Salaün 展示了嵌套策略如何组合;到 14:30,他把原则概括为限制由后代继承,并且只沿一个方向收紧。线程一旦进入 Landlock 域,就再也无法移除其中的策略。之后仍可继续叠加新规则集,但一次访问只有通过每个生效层、系统常规 DAC 和其他 LSM 的全部检查,才会获准。新建的子线程会继承父线程所在的域。[2][3][4]

这种设计给无特权自我沙箱划出了清楚的威胁模型。设想一个归档解包程序,它需要读取一棵输入目录树,并写入一棵输出目录树。程序可以先完成初始化,描述这两个层级,进入自己的域,再开始解析由攻击者控制的字节。即使漏洞利用把解析器引向存放凭据的目录,已经失守的进程也找不到任何 Landlock 操作来恢复原本可用的环境访问范围。

继承让这项规则从单个函数的防护扩展成进程树的权限界线,其覆盖范围从调用线程向后延伸,已经存在的兄弟线程仍保持原状。在 2024 年演讲展示的界面中,限制一个线程时,调用线程及其未来子线程会纳入该域,已经存在的兄弟线程不会自动受到限制。当前上游文档又为支持 ABI 8 的内核加入 LANDLOCK_RESTRICT_SELF_TSYNC 标志,可以在整个线程组内同步执行限制。面对较旧的 ABI,采用者应在进程仍为单线程时进入该域,或者明确协调所有线程逐一执行限制。前一句“主线程已受 Landlock 限制”只描述主线程,后一句“整个进程已受 Landlock 限制”还要求其余线程一并受限。[2][3]

17:10–19:03 — 三项系统调用创建一个域

这组界面可以分三步梳理:

  1. 调用 landlock_create_ruleset 创建规则集文件描述符,其中的 handled_access_fshandled_access_net 及相关字段说明该策略会管理哪些访问类别。
  2. landlock_add_rule 添加针对具体对象的许可。LANDLOCK_RULE_PATH_BENEATH 规则可以以某个 O_PATH 文件描述符指向的路径为根,允许在其下执行选定操作;网络端口规则可以允许选定的绑定或连接操作。
  3. 无特权进程执行限制时,先设置 PR_SET_NO_NEW_PRIVS,再调用 landlock_restrict_self。限制成功后关闭规则集描述符。

对于多数权限,某个类别一旦列入处理范围,默认结果就是拒绝。假如规则集声明自己处理文件读取,却只允许读取 /usr 和应用数据目录之下的内容,其他文件读取都会遭拒。反过来,处理掩码中省略的权限通常处在这一层策略的管理范围之外,不会因为省略而自动遭拒。LANDLOCK_ACCESS_FS_REFER 是一个有意保留的历史例外,即使没有声明为受处理权限,仍存在遭拒的情形。因此,处理掩码以及每个 ABI 对应的具体语义都属于安全承诺本身,不能当作规则外围的例行样板。[2][3]

执行顺序同样重要。Landlock 的限制从生效时点向后延伸,已经取得的资源保持原状。上游文档明确说明,进入沙箱之前打开的文件或目录不会重新受文件系统限制约束,与文件描述符相连的访问权限通常在打开描述符时就已经确定。程序应当先关闭无意保留的描述符,并在开始处理不受信任的任务之前进入自己的域。等解析器已经打开了整个世界再加沙箱,实际收紧的范围会小于策略文本所呈现的范围。[3][4]

回看 16:44 — ABI 协商本身就是策略选择

Salaün 的代码流程从调用 landlock_create_ruleset(NULL, 0, LANDLOCK_CREATE_RULESET_VERSION) 开始。这个探测会返回当前内核支持的最高 Landlock ABI。随后,应用先移除旧 ABI 无法理解的权限,再创建实际使用的规则集。例如,TCP 绑定与连接控制始于 ABI 4;当前文档还记载,UDP 控制始于 ABI 10。[2][3]

其中的细微之处在于,兼容性会决定究竟还保护着什么。显式列出受处理权限,可以防止较新的内核自行收紧既有应用的沙箱并引发故障;在较旧的内核上,实际保护至多覆盖内核认识的权限子集。追求尽力加固的程序可以屏蔽不受支持的权限,记录缩减后的限制范围,再继续运行。高保障模式则可以认定缺失的权限不可缺少,一旦缺少就拒绝继续运行。只探测 ABI,却对结果置之不理,算不上策略。

探测失败时也面对同样的选择。当前文档会区分两种情形:内核缺少这项系统调用,或者 Landlock 已被禁用。桌面文档查看器可以合理地优先维持可用性,同时报告加固并未生效;一款承诺“在隔绝网络的条件下打开这个恶意文件”的工具,则不应悄悄取消网络限制继续运行。合适的后备方案取决于产品承诺,这项分支逻辑必须明确并纳入测试。

演讲所称的 2024 年“当前”功能集,也应当视为一张带日期的快照,不能当作永久不变的文档。幻灯片展示了文件系统权限、TCP 端口规则、隐式 ptrace 与挂载限制,以及仍在规划中的 IPC 限定。到 2026 年,上游文档已经纳入后续 ABI 新增的信号与抽象 UNIX 套接字限定、线程同步、路径名 UNIX 套接字解析、UDP 规则和勘误查询。长期有效的是协商方式;部署目标究竟有哪些可用权限位,应以部署目标配套的头文件和文档为准。[2][3]

约 19:23 — 能否采用,取决于生命周期中的限制时点

Salaün 列出的候选者包括解析器、渲染器、网络服务、软件包工具和容器运行时。这些候选者都有一个共同特点:完成设置后,合法运行所需的资源会大幅减少。它们也都能明确找到这一阶段。网络守护进程可以绑定套接字、载入密钥和配置、降低权限、安装 Landlock 域,然后才开始接受恶意请求。图像转换器则可以在解码文件之前,只放行一棵输入目录树和一棵输出目录树。[2]

与项目规模相比,这个阶段分界更适合用来判断能否采用 Landlock。输入输出契约清楚的小型 CLI 会很合适。对于带有插件、用户所选路径、延迟加载驱动和辅助进程的大型应用,是否需要多个嵌套域、是否已有稳定的关门时点,都要逐项确认。宽泛规则若安装得太晚,只会成为安全剧场;狭窄规则若安装得太早,则会带来难以解释的故障。

面向生产环境的接入中,下面四项测试比一次正常路径演示更有价值:

  1. 在 Landlock 不可用的内核上运行,验证预定的后备行为。
  2. 针对支持范围内最旧的 ABI 运行,并断言哪些保护仍然生效。
  3. 逐项拒绝敏感的文件系统或网络操作,确认操作被拒后应用仍保持安全。
  4. 在准确的限制时点前后,测试线程创建、派生子进程、exec、继承的描述符以及延后打开的资源。

持续维护的语言封装库可以降低手工编写版本掩码的风险。后备方案和生命周期中的限制时点仍由产品决定,这些决定应贴近应用的实际语义。团队还要让失败留下可供排查的诊断信息:访问遭拒时应说明原因;landlock_restrict_self 意外失败时,必须按沙箱未生效处理。

约 24:30 — Landlock 只承担完整沙箱中的一层防护

演讲以采用情况和路线图幻灯片收尾,其中最有力的结论仍是对适用范围的说明。Landlock 会限制当前 ABI 所支持的内核对象访问类别。内存安全验证、CPU 时间约束、全量系统调用过滤和 UID 隔离仍分别属于其他工具的职责,Landlock 也无法让内核漏洞变得无害。一个坚实的沙箱还可以组合使用 Landlock、seccomp、丢弃 capabilities(权能)、命名空间、资源限制,并把特权范围刻意缩到很小。[2][4]

Landlock 把其中一层防护的维护权交给项目自身。项目现在可以主动把应用行为写成文件系统与网络策略,不再只能等待每个发行版或运维人员从外部完成这项转换。它可以随代码发布一套可测试的限制,根据当前内核支持的 ABI 调整这套限制,并让父级与子级策略逐层组合。

门的比喻只有在铰链经过检查后才成立。应用要先关闭多余的描述符,再于敌意输入的处理开始之前安装策略,并覆盖每个相关线程。遇到当前 ABI 不支持的权限时,程序必须明确选择后备方案。负向测试必须证明对受禁路径的访问确实失败。满足这些条件后,Landlock 的单向切换便会为应用划出清晰的权限分界:从策略生效的准确时刻起,环境权限不再属于应用设计的一部分。

来源

  1. Linux 基金会,“Linux Sandboxing with Landlock — Mickaël Salaün”,Open Source Summit Europe 2024,YouTube 视频。
  2. Mickaël Salaün,“Linux sandboxing with Landlock”,Open Source Summit Europe 2024 官方幻灯片。
  3. Linux 内核文档,“Landlock: unprivileged access control”,当前用户空间 API 指南。
  4. Linux 内核文档,“Landlock LSM: kernel documentation”,当前设计与安全指南。
  5. Mickaël Salaün,“Landlock: From a security mechanism idea to a widely available implementation”,SSTIC 2024。
  6. Jonathan Corbet,“Landlock (finally) sets sail”,LWN.net,2021 年 4 月 21 日。
  7. Thomas Debesse,“Une balade au FOSDEM”,LinuxFr.org——FOSDEM 2023 照片的来源报道,CC BY 4.0。
Previous 近 50 万英镑资助瞄准 R 的审查瓶颈,扩充贡献者梯队

Recommended In oss

Matched by subject and format