LWN:继续等待安全模块堆叠!

Linux安全模块堆叠:多年努力接近成果
Linux安全模块(LSM)自2001年以来已实现多种安全改进,但不支持多个模块同时运行。开发者Casey Schaufler历经多年尝试,其最新堆叠补丁集接近解决此问题,允许AppArmor等LSM与其他模块堆叠。然而,关于用户空间接口和系统调用API的争议仍存,尤其是模块ID的动态分配和运行时加载LSM的能力。尽管面临挑战,LSM有限堆叠功能的实现已渐行渐近。

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

Still waiting for stackable security modules

By Jonathan Corbet
October 31, 2022
DeepL assisted translation
https://lwn.net/Articles/912775/

Linux security module(LSM,Linux 安全模块)机制是在 2001 年第一次内核峰会中达成一致而创建的;它在设计上允许开发多种不同路径来改善 Linux 安全。这个目标已经实现了;目前的内核已经有了几个安全模块可用。不过,LSM 子系统在设计上并不支持让多个安全模块在同一个系统上一起工作。自从 LSM 子系统合并进来之后,开发者基本上持续在努力纠正这个问题,但这里的成功率有限;一些小的安全模块可以堆叠(stack)在 "主" 安全模块之上,但肯定无法进行任意堆叠。现在,在安全模块的支持合入 2.5 内核整整 20 年后,看起来堆叠问题的解决方案可能接近落地了。

The challenge

早期的想法是,LSM 将在整个系统中来强制执行安全策略(enforce a security policy),而且只允许有一个 policy。几年来唯一存在的 LSM 就是 SELinux,这也加强了这一设计理念,但开发人员很快意识到也有很好的理由可以在一个系统上运行多个 LSM。例如,采用适当的堆叠方案就可以开始使用各种小型 LSM 了,其中每个 LSM 都是针对安全策略的其中一部分。最近的发展,比如 container,也使得加载多个全系统模块可能更有意义了。

为了解决这个问题,已经进行了不少尝试。这些年进行过的尝试包括:

  • Serge Hallyn 可能在 2004 年进行了第一次尝试。

  • David Howells 在 2011 年的尝试。

  • 2012 年,Casey Schaufler。

  • 2015 年,Schaufler 又尝试了一次。

  • 在 2019 年他又一次尝试。

任何人如果想要解决这个具体问题,都要面对一些挑战。其中之一是要决定在有多个 active LSM 并且它们彼此意见不同意的情况下,是否应该采取行动。最简单的方法是让每一个 LSM 使用否决权;所有对任何具体操作表达意见的模块,必须同意允许该操作,否则这个操作就会被拒绝。最困难的问题很可能在其他地方。当多个 LSM 处于 active 状态时,不是很容易弄清楚用户空间接口应该是什么样子;即使只混进来一个模块,追踪调试 policy 问题也是很痛苦的。

还有一个重要的问题,就是要让 LSM 有办法将它们自己的 metadata 附着到系统中的对象上。最初的 LSM patch 通过添加指针来指向各种内核数据结构处理这个问题,但没有考虑过要存储多个模块的数据的情况。任何解决方案都必须允许 LSM 在这一点上配合好,同时,不能对性能产生可测量到的影响。

A viable solution

Schaufler 非常有毅力;在开始这个工作十年之后,他仍在努力希望解决这些问题从而把安全模块堆栈的解决方案纳入 mainline 内核。他的 stacking patch set 的第 38 版已于 9 月底发布。目前并没有解决所有问题,但它确实使 AppArmor LSM 可以跟其他任意模块进行堆叠使用了。经过这么多年的时间和版本迭代,人们并不在得知 Schaufler 准备好看到这项工作被合并时,并不意外;早在 8 月,他就问过是否可能在 6.1 内核周期内完成合入:

我非常希望能在 6.1 的 LSM next 分支上合入针对 Apparmor 的 LSM 堆栈补丁集的 v38 或 v39。audit 方面的修改已经完成得很好了,我相信所有关于 integrity code 的意见都已经解决了。interface_lsm 机制已经快要被打烂称为泡沫了。

这个计划之所以不那么容易达成,主要是因为另一个事件:LSM 的长期维护者 James Morris 退居幕后了,Paul Moore 接管了该子系统的维护工作。这一变动可以说对堆叠 patch 是既有积极影响,又有消极的影响。从积极的方面看,Moore 似乎有更多的时间可以参与到堆叠 patch 的工作中,并有更强烈的愿望将其并入 mainline。可是至少对于快速合并不太有利的一点是,Moore 觉得有必要从最开始来重新 review patch set,这就不可避免地引出了新的 comment 和修改要求。

具体来说,Moore 对用户空间的 API 很不满意,它是对现有的、基于/proc 的接口的扩展,甚至连 Schaufler 都说它是挺 "可怕的"。摩尔建议,也许现在是时候增加一套 LSM 专用的系统调用了:

我们过去一直避免这样做,但在过去的几十年里,LSM 已经成为 Linux 的一个核心部分,许多(所有?)的 Linux 发行版都至少带上了一个 LSM 的支持。我觉得我们应该值得拥有一套认真定义过的 syscall 了,并且可以参考 Landlock 这些先行者。

Moore 也为他心目中的系统调用 API 做了一个粗略的设计。不过,Schaufler 对这个想法不太满意:

我希望你三年前就提出这个建议,那时我可以很好地用上它。如果仅仅因为这个原因,让堆叠方案再进行两年的 redesign,那这个方案就没法落实了。我们已经花了好几年的时间打磨 /proc 接口。改变了其中的名称和内容,甚至为了适应那些拒绝采用 attr/subdir 策略的安全模块而做了向后兼容设计。

用户空间接口一旦被包含在了内核版本中,就很难改变了;如果需要重大改变,通常需要在代码合并之前进行。因此,Moore 坚持说他不能接受当前提议的接口,这并不完全令人惊讶;Schaufler 最终举了白旗,开始讨论他具体需要做什么:

好吧,那么哪些接口需要重做?我已经为刚刚成为废弃物的这组 patch 打磨了%^&*非常长的时间。我需要知道这是否是我可以解决的问题,还是说应该把整个方案扔进传说中的数字垃圾桶里去。

The system-call API

Schaufler 最终又回来了,提出了两个新的系统调用的提案。其中第一个是:

struct lsm_ctx {
  unsigned int    id;
  unsigned int    flags;
  __kernel_size_t   ctx_len;
  unsigned char   ctx[];
};

int lsm_self_attr(struct lsm_ctx *context, size_t *size, int flags);

其中的 context 是一个长度为 *size 字节的 buffer;flags 参数必须为 0。这个调用将会返回当前生效的安全模块所分配给调用进程的所有属性(attributes),这些属性在 context 所指向的 buffer 中;有一个 patch 描述了所返回的数据的格式。size 参数则将被按照返回数据的实际大小来更新。第二个系统调用可以用来确定哪些 LSM 是当前有效的:

int lsm_module_list(unsigned int *ids, size_t *size, unsigned int flags);

这个调用将用分配给每个 active module 的 ID 号来填写 ids 数组。这些 ID 号是在一个新的头文件中定义的,该文件旨在成为用户空间 API 的一部分;例如,Schaufler 的 Smack 模块被定义如下:

#define LSM_ID_SMACK 34

这个设计方案中的大部分内容都遵循了 Moore 的最初建议。似乎主题来说是没有什么争议的,但有一个重要的问题。那就是 Tetsuo Handa,Tomoyo LSM 的开发者,强烈反对使用在内核代码中分配的整数类型的模块 ID。他认为,这种做法将使我们无法在 run-time 加载那些当前内核源代码尚未定义的 loadable LSM。因此,LSM 的开发者就很难进行相应的测试,并且尤其难以让其他人来使用这些 LSM。他说,这反过来又给未来任何新的 LSM 判了 "死刑"。

正如其他人所指出的,这种说法有几个问题,首先是内核开发社区从来就不打算让 out-of-tree 代码的日子好过。另一个问题是,LSM,无论是否在 kernel 代码内,现在都不能在运行时进行加载。这种 capability 在多年前就被取消了,而且似乎不太可能再恢复回去;除此之外,LSM 太容易绕过那些针对普通内核模块施加的限制。由于这些原因,Handa 要求的直接将 security_hook_heads 变量 export 给内核模块就不太可能被落实。Schaufler 也多次说过,任何关于 loadable LSM 的新机制都必须要按照跟内置 LSM 很不同的方式来处理,因为 loadable LSM 必须受到更严格的限制。这是他个人无意承担的另一项大工作。

由于所有这些原因,Handa 的反对意见似乎不太可能最终获胜。但是,这项工作在这么长的时间里经历了如此动荡的历史,可能仍然无法立即合并。新的系统调用需要经过广泛的 review,而这一过程才刚刚开始;如果需要进行更多的修改那夜不足为奇了。即便如此,LSM 有限堆叠功能的终结,也会越来越近。那么剩下的就是 "随意堆叠(universal stacking)" 了,据 Schaufler 说,要实现这个未来,"至少还需要一年"。因此现在有了明显的进展,但这个漫长的讨论尚未结束。

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

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

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

format,png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值