LWN:非特权的BPF以及进行额外授权的security hook!

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

Unprivileged BPF and authoritative security hooks

By Jonathan Corbet
April 27, 2023
DeepL assisted translation
https://lwn.net/Articles/929746/

当 Linux 安全模块(LSM, Linux security module)子系统的开发者跟其他内核开发者有分歧时,往往是因为其他开发者没有想到(或者根本不想)给他们自己崭新的子系统内部添加安全钩子(security hooks)。不过,有时候,非 LSM 开发者所添加的新钩子也会导致一些问题。Andrii Nakryiko 发布了两个与 BPF 相关的安全 hook,引起了一些有趣的问题,其中一个引发了大量的讨论,还好另一个比较正常。

Nakryiko 建议增加两个新的 LSM hook 来控制对 BPF 功能的使用。第一个 hook 将管理 BPF 地图的创建,而第二个 hook 是为了控制 BPF type format(BTF)数据(描述了内核中的函数和数据结构)的加载。不过,计划并不止这些:

这组 patch set 实现并演示了一个从创建 BPF map 和 BTF object 开始的通常方法,这是典型的 BPF 应用的生命周期中的前两个步骤。后续还需要对 BPF_PROG_LOAD 命令做类似的修改,从而允许 BPF 程序被加载和验证。

该计划的这一部分并没有受到太多反对意见;如果在检查 CAP_BPF 的 capability 之外还有对这些功能进行访问控制的使用场景的话,那么增加这些 hook 从而使得创建一个 policy 来实现这个控制就是有好处的。但这并不是这些 hook 的目标使用方式。相反,它们可以被用来完全绕过 CAP_BPF 检查,这意味着它们可以让缺乏这种能力的进程使用到这些功能。

Authoritative hooks

LSM 子系统起源于 2001 年的第一次内核峰会(the first Kernel Summit)。当时,人们希望将早期版本的 SELinux 合入内核,但是 Linus Torvalds 指出,还有其他正在开发中的提高安全性的方法,他不想将内核跟其中任何一个绑定起来。相反,他希望创建一个框架可以支持多种安全机制。

该框架实现了一套丰富的 hook ,可以在系统调用路径的相关点上做出安全决策,最终该框架被合并,成为 Linux 安全模块子系统。但是在这之前,关于 LSM 子系统是否应该支持 hook 授予进程所没有的权限、或者它们是否只能在内核的其他访问控制机制已经实现的限制之外再额外增加限制,进行了激烈的讨论(当时在 LWN 上报道过)。最后,人们决定不允许支持 "authoritative hook" (也就是可以增加权限的 hook)。设立这条规则有很多原因,其中之一人们认为这样可以用来避免安全模块本身引入安全漏洞。

在做出这个决定后的 21 年里,已经新增了许多安全模块,但它们都遵守了这个规则。这些年中偶尔会有讨论是否要放宽对这种 authoritative hook 的限制,但从未被认真考虑过。因此,当 Nakryiko 提议增加几个 authoritative hook 时,LSM 的维护者 Paul Moore 很快做出了回应:

LSM 的标志之一一直是它不进行额外授权(non-authoritative):它不能单方面地授予访问权,它只对传统 Linux 系统上所允许的东西进行额外限制。换句话说,LSM 不应该破坏 Linux 自己原有的一些访问控制的决策功能,比如说不可以破坏 capability 限制。

他说,真正的解决办法是修改 BPF 代码中对 CAP_BPF capability 的处理逻辑。Kees Cook 不同意,他认为这些 hook 可以被看作是 "细粒度的访问控制",而不是实际上绕过了安全保护(enforcement),但 Moore 坚定地反对这个想法。

Nakryiko 抗议说,这个想法是通过使用比单一的 CAP_BPF capability 更细粒度的控制来提高安全性。他说,我们的方案如果仅仅支持施加限制的话,最终会更加脆弱。他还补充说,在牵涉到用户命名空间(user namespace)时,基于 capability 来进行授权判断的话会有几个实际问题。第一个问题是,许多 BPF 程序,比如那些需要跟 trcing 功能交互的程序,本质上是整个系统看作一个整体来进行观测的,并不能真正算在某一个命名空间中。所以 CAP_BPF 的 capability 的检查就不可能牵涉到具体的命名空间。

除此之外,由于 capability 检查在 BPF 子系统中的实现方式决定了,目前来说如果一个进程在用户命名空间中运行的话,甚至不可能给它 CAP_BPF。因此,他认为,在用户名称空间内运行的程序根本不可能真正利用 BPF。他提出的 hook 是为了提供一种方法来解决这个缺陷。

Casey Schaufler 在 2001 年时曾支持 authoritative hook ,现在却不以为然了:

这听起来不像是个问题,听起来 BPF 被明确地设计为防止 namespace 的干扰。但现在你想在某些情况下通过命名空间来限制它。

看来,BPF 的预期用途不再与它最初的安全模型相符了。这很不幸,而且很可能需要对 BPF 的实现进行重大改变。

或者,正如 Moore 所说: "为了解决另一个访问控制机制的问题而改变 LSM 层的核心行为是不可行的"。Nakryiko 已经很好地明白了这个意图,并答应后续会再提出一个不同的方案给大家看。因此,目前看来,彻底解决 BPF 社区所遇到的问题看起来短期内还是做不到的。

Unprivileged BPF

这个讨论中没有太多提及的,是 BPF 社区内关于安全问题的一个明显改动。再次引用 Nakryiko 的 cover letter 中的话:

这种 LSM hook 语义提供了更安全的默认策略,即不给应用程序任何 CAP_BPF/CAP_PERFMON/CAP_NET_ADMIN 的能力(这种 capability 通常是在内核中使用 BPF 子系统所必需的)。相反,所有的 BPF 进程都是完全非特权的(unprivileged),只有被允许的、经过验证的生产环境中使用场景下的例外情况才会被授予使用 bpf() 系统调用的权限,就好像这些应用具有类似于 root 的 capability 一样。

在 extended BPF 的早期,人们有一些工作的目标就是为了使 BPF 的使用不需要任何特殊权限。不过到了 2019 年,unprivileged 情况下使用 BPF 的想法已被明确废除。BPF 的共同维护者 Alexei Starovoitov 将 Linux 描述为 "一个单用户系统",并宣称将不再尝试在没有特权的情况下使用 BPF。保持系统安全所涉及的麻烦事实在是太多了;Spectre 漏洞的出现让事情变得更糟了。

因此,看到 BPF 开发者再次谈论 unprivileged 操作,还是感到很新奇的,尽管是在安全策略的监视下进行这种操作。在 BPF 邮件列表中似乎没有关于权限模型整体变化的任何讨论,所以并不完全清楚这个变化是如何产生的。

看起来很清楚的是,如果 BPF 开发者想摆脱简单的 CAP_BPF 检查,他们将不得不重新审视他们到目前为止所做的许多与安全有关的决定了。添加 authoritative LSM hook 的方法在 mainline 上似乎并不可行,因此必须考虑其他解决方案,包括重新考虑用户命名空间问题。这看起来不像是一个可以快速解决的问题。

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

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

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

format,png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值