LWN:两种加强可加载module管控的方式!

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

Two approaches to tightening restrictions on loadable modules

By Jonathan Corbet
November 15, 2024
Gemini-1.5-flash translation
https://lwn.net/Articles/998221/

内核的可加载模块机制 (loadable-module facility) 允许将代码加载到运行中的内核中(有时有需要从中移除)。可加载模块使得仅运行系统硬件和工作负载所需的子系统成为可能。它还可以方便地让树外 (out-of-tree) 代码访问内核开发人员更希望保持私有的部分;这在过去导致了 许多讨论。这一话题再次出现在内核邮件列表中,其中有两个不同的补丁集旨在进一步加强对可加载模块的限制。

当静态内核映像 (static kernel image) 链接时,对符号 (函数和数据结构的名称) 的引用是使用整个全局命名空间 (global namespace) 来解析的。加载模块也涉及链接步骤,但模块无法访问完整的命名空间;相反,它们只能访问已明确导出给它们的符号。有两组导出的符号:任何可加载模块都可以访问的符号,以及只有声明与 GPL 兼容许可证的模块才能访问的符号。访问符号是限制可加载模块功能的主要手段,因此这两个补丁集都对该机制进行了更改,这并不令人意外。

受限命名空间

在内核存在的大部分时间里,只有一个命名空间来保存可加载模块可用的所有符号;如果模块具有适当的许可证,该命名空间仅包含受 GPL 限制的符号。2018 年,内核获得了 一种符号命名空间功能,可以隔离一些符号并限制其对明确导入相关命名空间的模块的可用性。此功能的用途之一是使滥用 (模块访问其不应该访问的符号) 更明显,但它没有访问控制功能;只需导入包含它们的命名空间,就可以使符号可用。

长期以来,人们一直希望能够导出供特定模块使用而其他模块不使用的符号。Peter Zijlstra 的 这个补丁 添加了此功能。在当前内核中,符号使用类似以下声明导出到特定命名空间 (foo) 中:

EXPORT_SYMBOL_NS_GPL(symbol_name, foo);

任何包含以下行的模块:

MODULE_IMPORT_NS(foo);

都可以访问导出到该命名空间的符号。Zijlstra 的补丁对导出声明进行了一些调整。要导出仅在名为 foo 的模块内可用的符号,声明将是:

EXPORT_SYMBOL_NS_GPL(symbol_name, MODULE_foo);

这将创建一个具有几个特殊属性的命名空间。加载名为 foo 的模块时,将隐式导入此命名空间;不需要 MODULE_IMPORT_NS() 声明。实际上,任何尝试导入名称以 MODULE_ 开头的命名空间的尝试都将被阻止。最终结果是该符号可用于 foo ,但不能用于任何其他模块。

在讨论中,没有人反对添加此功能。关于语法,有几点想法。模块加载器 (module-loader)维护者 Luis Chamberlain 建议 使用单独的 EXPORT_SYMBOL_GPL_FOR() 语法可能比 MODULE_ 约定更好;他还说,能够将符号导出到多个模块将很有用。

内核构建系统 (build system) 的维护者 Masahiro Yamada 表示 将命名空间名称作为 C 字符串而不是裸名会更好。这将消除内核代码中的一些歧义;该字符串也可以是目标模块的逗号分隔列表。这将是一个很大的改变,正如 Zijlstra 尝试过的那样: 结果补丁修改了 847 个文件。

不过,引号字符串方法似乎更有可能在未来受到青睐。Zijlstra 已经编写了 一个支持使用该语法导出到多个模块的补丁版本。“在非常有限的测试中似乎有效”,但尚未重新发布到列表中。如果一切顺利,预计很快就会发布 发布,但此工作很可能为时已晚,无法进入 6.13 内核版本。

当“GPL”不是 GPL 时

与此同时,一个单独的补丁正在采用一种截然不同的方法来解决可加载模块不恰当访问符号的问题。内核是根据 GNU 通用公共许可证 (GNU General Public License, GPL) 版本 2 许可的,而不是其他版本。当自由软件基金会 (Free Software Foundation) 创建 GPL 版本 3 时,它与版本 2 不兼容;内核社区拒绝切换到新的许可证,因此无法接受根据 GPLv3 许可的代码。因此,通常情况下,人们不会期望看到根据该许可证发布的设备驱动程序 (或其他内核模块)。

然而,事实证明,Tuxedo Computers 维护 一组其硬件的设备驱动程序,这些驱动程序确实是在 GPLv3 下获得许可的。但是,在这些模块中的 MODULE_LICENSE() 声明中,许可证声称为“GPL”。结果,这些模块可以访问仅限 GPL 的内核导出,即使它们的许可证与内核的许可证不兼容。

这种情况已经公开了一段时间,但直到 Thorsten Leemhuis 的 这项研究 将所有内容整合在一起之后,才被提到了前面。Neal Gompa 在 2020 年 指出了这一点,并要求重新许可为 GPLv2。此后讨论多次浮出水面,但该公司拒绝做出更改。今年早些时候,Tuxedo 的 Werner Sembach 明确表示了公司立场:“我们不打算直接重新许可 tuxedo-drivers 项目,因为我们希望控制上游的节奏”。换句话说,不兼容的许可证是公司为使其驱动程序在其自己选择的时间之前不进入主线 (mainline) 而故意做出的选择。

许可决定可能有点奇怪,但这肯定在公司的权利范围内。声明兼容的许可证以访问受限符号则不行。作为回应,Uwe Kleine-König 发布了 一个补丁系列,明确阻止 Tuxedo 驱动程序访问仅限 GPL 的符号。安装此补丁后,这些驱动程序将无法再正确加载到内核中,并将停止工作。

对该补丁的回应总体上是积极的 (虽然 并非完全如此)。但 Sembach 毫不意外地 不喜欢。据他所说,这种情况是由于可以理解的混淆造成的:“我们最终陷入这种情况,因为 MODULE_LICENSE("GPL") 本身并没有暗示 GPL v2,如果一个人没有意识到文档中的许可证定义表的话”。他说,许可证情况正在处理中,最终将得到解决。

如果该公司确实打算真诚地解决问题,在该工作进行的同时,推迟明确阻止其模块几乎肯定是有意义的。然而,鉴于这个问题已知已久,并且考虑到公司故意使用许可证不兼容来保留对其代码的控制权,让开发社区相信其诚意可能很困难。但这并没有阻止 Sembach 尝试;他 已重新许可 了相关的一些模块,并承诺尽快更改其余模块。

这是一个朝着正确方向迈出的一步,但是没有什么愤怒能比得上一个内核开发者对模块许可感到被欺骗的愤怒。Kleine-König 表示 他打算在 6.13 合并窗口期间尝试合并该补丁。然后,他说,如果许可证问题完全得到解决,“你将得到我的支持来撤销正在讨论的补丁”。事情是否真的会发展到这一步尚不清楚;如果 Tuxedo 正在努力快速解决这个问题,那么在此期间合并惩罚该公司的补丁的意愿可能很小。不过,Tuxedo 不太可能再次尝试这种特殊的技巧,而任何考虑这样做的人都应该三思而后行。

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

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

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

110b1ace2bd716808eb744f0b9fd9897.jpeg

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值