LWN: 用eBPF实现seccomp()

关注了就能看到更多这么棒的文章哦~

eBPF seccomp() filters

By Jonathan Corbet
May 31, 2021
DeepL assisted translation
https://lwn.net/Articles/857228/

seccomp() 机制允许进程加载一个 BPF 程序,用来限制后续此进程可以调用哪些系统调用。这是一个简单而灵活的沙盒机制,已经在广泛使用了。不过,那些 filter 程序运行在 "classic" BPF 虚拟机上的,而不是内核中其他地方在使用的 extended BPF(eBPF)虚拟机。经常有人提出希望将 seccomp() 迁移到 eBPF,但大家一直担心有安全问题,因此一直没能达成这个目标。YiFei Zhu 最近提出的一组 patch set 就是迁移到 eBPF 的最新尝试。它是否能克服之前其他 patch 的缺点还有待观察。

seccomp() 中 BPF 程序的用途就是决定是否应该允许一个特定的系统调用。因此,这些程序只需要访问系统调用中的少数参数就够了。此外还需要一个通知机制,在需要的时候,可以把决定权交给用户空间的守护程序(daemon)。使用这个 filter 程序之后,浏览器或 container-management system 等工具可以限制它们和子进程可以做哪些事情。

使用 eBPF 来编写这些程序的话,有很多好处。基本上也是相同的这些好处导致 eBPF 最初创建出来。迁移到 eBPF 的话,seccomp() filter 程序就可以具有许多新的功能了,包括 BPF map、helper function、per-task storage、更丰富的指令集等等。eBPF 程序可以用 C 语言来编写,classic BPF 程序则不可以,因此才使得人们发明了 easyseccomp 等特殊语言。围绕 eBPF 的工具已经形成了一个完整的生态系统,seccomp() 的开发者们都希望能用上。

鉴于上述所有这些原因,人们可能会认为不会有人反对用 eBPF 来实现 seccomp()。实际上,在安全方面还是有障碍的。目前的机制来说很相对简单,容易验证,而 eBPF 带来了一个全新复杂因子,有点让人担心。用 seccomp() 来落实一个 filter 程序的过程是一个非特权操作,人们希望保持这种方式(不需要特权用户的权限),但 BPF 的开发者已经放弃了修改 eBPF 使之可以安全地用在非特权用户的场景下的想法。没有人希望把 seccomp() 本身再变成一个 security 问题。

Zhu 的计划是给 eBPF filter 程序增加一些限制,从而避免这个难题,在大多数情况下,用户不能用 eBPF 做任何之前无法用 classic BPF 和用户空间通知机制无法实现的功能。最大的例外也许是可以访问 BPF map 和标准的 helper 函数集了。这么做的理由是,非特权用户现在可以通过 socket-filter 程序访问到这些功能了,所以这里并没有暴露出任何新的信息出去。不过,这组 patch set 确实添加了一个 Linux security module,用来控制是否允许 seccomp() filter 程序使用这些功能,因此有必要的话可以禁用这些功能。还有一个 Yama security module 的 patch,可以更容易地控制这个功能。

为 tracing program 提供的一组额外的 eBPF helper 函数也可以提供给 filter 程序,但前提是加载这个 filter 程序的用户要有加载 tracing program 所必需的权限(CAP_BPF 和 CAP_PERFMON)。这些 helper 函数之中还提供了在 seccomp() 上下文中可能会用得上的访问内存方式。例如,可以更深入地检查系统调用参数。还有一种机制是在某个 task 中存储状态信息,以便可以在不同的 filter 中使用,但它需要相应的权限才能真正起效果。

值得注意的是,对这些功能的权限检查是在加载新类型(BPF_PROG_TYPE_SECCOMP)的 BPF 程序时进行的。而将 filter 程序 attach 到某个进程上的过程中总是无特权的。因此,一个有特权的守护进程可以加载一组批准过的程序,并将它们传递给其他用户,然后这些用户就能够利用更完整的 eBPF 特性了。

如果要让这样的 patch 被合并的话,需要先说服两组不同的人:BPF 维护者,还有关注安全的开发者。BPF 这方面的情况还不清楚。eBPF 的创建者 Alexei Starovoitov 在 2019 年 5 月声称,"seccomp 需要开始使用 ebpf"。而三个月后,他的立场反而是。"我绝对反对在 seccomp 中使用 eBPF"。这一变化也是因为他变得反对向非特权用户提供 ebPF 了,他担心 eBPF 永远无法在付出较小成本的情况下满足安全要求,而且这种需求本身就不多。不过,在对 Zhu 的 patch 的讨论中,他只是询问了实施的细节,并没有对这个想法整体表示反对。所以也许 BPF 方面已经准备好允许 eBPF 与 seccomp() 配合使用了。

要说服安全开发人员可能更难。早在 2018 年,Kees Cook 就强烈反对在 seccomp() 中使用 eBPF,他认为 eBPF 的变化太快了,而且在这种环境中也出现过太多的安全问题。在目前的讨论中,Andy Lutomirski 已经告诉大家这组 patch 会面临一个 "非常高的 review 标准"。他担心如果使用更复杂的 eBPF 系统的话,就会更难验证这个实现本身的安全性,而让非特权用户可以使用 eBPF 这个想法的阻力会一直存在:

上一次试图让 eBPF 在较少特权或者无特权的情况下能正常工作的时候,当时维护者们大多都拒绝了开发一个针对 maps 的 permission model、清理 bpf object id system 等的想法。在这些底层的 permission model 准备好之前,很难说服 seccomp 的维护者能允许这些机制跟 seccomp 交互起来。

这一部分的讨论到此为止了。这里的分歧可能会对整合 eBPF 和 seccomp() 的方案有决定性的影响,BPF 开发者不希望去支持这些非特权使用场景,而 seccomp() 开发者则需要支持这种功能。在没有比较好的解决方案的情况下,目前的 eBPF-in-seccomp() 功能似乎很可能会和它的前辈们一样,在同一个地方碰壁,而无法进入 mainline。这是一件不幸的事情,因为这本身是 seccomp()用户很希望得到的功能。

全文完
LWN 文章遵循 CC BY-SA 4.0 许可协议。

欢迎分享、转载及基于现有协议再创作~

长按下面二维码关注,关注 LWN 深度文章以及开源社区的各种新近言论~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值