LWN:封印系统映射表的最新进展!

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

An update on sealed system mappings

By Daroc Alden
February 4, 2025
Gemini-1.5-flash translation
https://lwn.net/Articles/1006375/

Jeff Xu 一直在研究 一个补丁集,希望让进程地址空间中的某些内存映射无法更改,从而防止篡改(tampering)。这具有一些潜在的安全优势,主要是确保没有人可以对 vsyscall 和 vDSO 映射 重新修改位置。但是,一些内核开发人员对这些补丁并不满意。虽然核心功能(密封映射)是合理的,但一些用于启用和禁用新功能的支持代码,因违背了此类功能的常规设计而引起关注。审查人员还质疑此功能将如何与检查点(checkpointing)和沙箱(sandboxing)交互。

与 mseal() 系统调用(可用于密封任何内存映射)不同,Xu 的补丁集专门用于在任何用户空间代码开始执行之前,密封内核使用的映射。该补丁集密封了五个对象的内存映射:vDSO(在用户空间中实现某些系统调用的代码),vvar(vDSO 调用的数据),sigpage(在 Arm 上实现信号处理的代码),uprobe(用户空间跟踪)和 vsyscall(一种较旧且已过时的系统调用机制)。这些工具中的每一个都涉及让内核将一些额外的页面映射到用户空间进程中;除了 uprobe 页面之外,所有这些页面都是在进程启动时创建的,并且通常应保持不变直到进程终止。Uprobe 是动态插入的,内核会在此时映射页面,但是该映射也一直存在直到进程终止。

这些映射中的每一个都用于执行原本应由内核执行的功能。因此,对于安全性而言,用户空间代码不更改这些页面非常重要。如果某个进程存在允许更改页面(或映射)的漏洞,则可能会欺骗某些系统调用的结果,这是非常容易被利用的。虽然不是最常见的漏洞利用类型,但它是一种 已知的攻击类型。完全消除这种可能性将是防御恶意软件的另一层深度防御(defense-in-depth)。

这些映射通常设置为只读或仅执行,具体取决于体系结构支持的内容,但是 Xu 的补丁将更进一步,通过密封映射(mapping)本身,来防止它们被设置为可写或取消映射。此更改应提供额外的安全性,而不会影响行为良好的用户空间程序的行为,因为它们通常不应接触任何这些映射。

检查点(Checkpointing)

但是,有一个主要的例外:用户空间检查点/恢复(Checkpoint/Restore In Userspace,CRIU),它可以冻结应用程序或容器,并将状态“检查点”保存到磁盘,然后再恢复它。它需要在恢复存储的应用程序期间移动这些映射,以将它们返回到检查点进程中的位置。Xu 的补丁集的第四版(也是截至撰写本文时的最新版本)仅适用于在构建时未启用检查点支持的内核,并且仅适用于 64 位 x86 和 Arm 架构。一些审查人员对这种限制并不满意。CRIU 的开发人员之一 Andrei Vagin 说:

我喜欢这个补丁集的想法,但是我不喜欢强迫用户在此安全功能和检查点/恢复功能之间进行选择的想法。我们需要探索使此功能与检查点/恢复一起使用的方法。依赖 CAP_CHECKPOINT_RESTORE 是一种显而易见的方法。

CAP_CHECKPOINT_RESTORE capability(权限) 控制进程执行某些特权操作的能力,CRIU 使用这些特权操作来实现检查点和恢复,包括读取其他进程的 /proc 中的内存映射文件。由于只有受信任的程序才能获得此权限,因此允许此类进程有选择地禁用系统映射的密封不应使系统面临更大的风险。

Vagin 还指出,CRIU 只需要在恢复过程中移动映射,而不需要更改其属性或内容。Xu 认为 这是一个需要考虑的重要细节。他同意“强迫用户进行选择是不理想的”。他质疑是否应该使用 prctl() 选项来控制在同时启用这两个功能的系统上是否密封映射,但他仍然认为,在未启用检查点支持的系统上,代码应无条件地密封映射。

Xu 的补丁集在内核处理对 execve() 的调用时密封创建的映射;提议的 prctl() 选项将无法禁用现有进程的密封,但可用于关闭新创建进程的密封。Vagin 同意 这样的选项适用于 CRIU,因为它控制恢复进程的创建方式。但他提到,其他程序(例如 gVisor)可能无法使用该选项。

命令行参数

然而,更大的抱怨来源是 Xu 的补丁集如何处理它添加的内核命令行参数( exec.seal_system_mappings )。该补丁集既有内核配置设置,又有内核命令行参数。这并不罕见——许多功能都有一个配置设置来将该功能构建到内核中,然后使用一个命令行参数在运行时启用或禁用它。Xu 的补丁集的设置方式恰恰相反:该功能始终构建到内核中,配置设置控制它默认是启用还是禁用,并且该设置可以被命令行覆盖。Lorenzo Stoakes 反对 说,内核命令行标志“似乎只是一个在任意内核上进行实验的调试标志”。

Xu 表示 这种设计是故意的,目的是允许用户即使发行版选择不在其内核版本中启用该安全功能,也能启用它。Stoakes 不相信 这种说法。Xu 重申 说,用户应该知道自己在做什么,如果用户想在也支持 CRIU 的内核上启用该功能,并且这会破坏某些东西,那么这是他们的特权。当 Xu 证明不愿意在这一领域做出改变时,Stoakes 阻止 了该补丁集合并,他说:“此系列补丁目前的形式是不可接受的,因为它允许未经测试的架构和已知损坏的配置启用此功能。”

即使 Stoakes 阻止了最新版本的补丁集,讨论仍在继续。Kees Cook 总结 了到目前为止的讨论,他说,如果 Xu 能够澄清有关哪些映射和平台包含在内的一些细节,清理命令行参数,并添加一个 prctl() 选项,他将拥有下一个版本的补丁集所需的一切。然而,Liam Howlett 认为 需要更多的研究:

那么我们至少有两个用户空间用例会被破坏:检查点恢复和现在的 gVisor,但谁知道还有什么?在决定默认情况下不能启用它之前,我们需要多少个配置选项?

[…]

而且我们真的不完全了解它会产生什么影响——考虑到 v4 仍在导致新的东西被破坏。

Stoakes 表达了同样的观点,他说他们应该对此功能“谨慎行事”,并呼吁进行广泛的测试和对安全优势的额外论证。Cook 认为,虽然额外的测试是明智的,但要求测试架构和相关标志的每种组合是不合理的。他主张从最少数量的支持平台开始,并对这些平台进行窄范围的测试。

Xu 提出了 完全删除内核命令行参数,仅依靠内核配置设置来启用或禁用密封的可能性。这对于 Android 和 ChromeOS 来说就足够了,并且可以避开审查人员指出的一些问题。他 后来建议,由于启用他的更改后,破坏的不仅仅是 CRIU,因此他的更改和 CRIU 之间的构建时冲突提供了一种虚假的安全感,可以将其删除。Stoakes 强烈反对 这种想法,他说任何补丁都不能让用户意外地破坏他们的内核。他 希望看到这个补丁集合并,但前提是它不包含一个如果使用不当会默默地破坏某些东西的启动参数。Matthew Wilcox 更加严厉,暗示 Xu 试图获得 Google 上游所需的最低限度的东西。

Pedro Falcato 提出了 将密封这些映射的工作留给用户空间的想法,并指出 GNU C 库(glibc)已经在 努力 密封地址空间的某些部分(这项工作 可能很快就会完成)。Xu 解释说,从 glibc 密封 vDSO 比看起来更复杂。动态链接器不知道 vDSO 有多大,特别是由于它在架构和内核版本之间有所不同。此外,uprobe 映射(稍后创建)无法由动态链接器密封。

第五个版本的补丁集正在开发中。通过删除审查人员反对的命令行参数,并修复补丁的其他一些技术问题,Xu 希望能够使下一个版本被接受。但是,这将需要时间,并且需要另一轮审查,这可能会引发同样详细的一组评论。尽管如此,内核离锁定另一个潜在的安全问题又近了一步,而不会让用户有另一种搬起石头砸自己的脚的方式。

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

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

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

7a730e221c70ae081071620b126d2ad7.jpeg

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值