LWN:stable kernel中的bug fix导致专有module的麻烦!
共 3611字,需浏览 8分钟
·
2021-07-07 20:10
关注了就能看到更多这么棒的文章哦~
A stable bug fix bites proprietary modules
By Jonathan Corbet
June 21, 2021
DeepL assisted translation
https://lwn.net/Articles/860262/
长久以来,内核开发社区与那些开发并发布专有的(proprietary)loadable module 的公司关系都很紧张。在许多开发者看来,这样的 module 违反了 GPL,应该被禁止使用。但这个愿望并未成为现实。相反,社区一直在追求的处理方法是模糊法律而在技术上创造不变,从而阻止专有的 module。一个近一年前合入的 "technical-inconvenience" patch 已经出现在 stable kernel release 中,已经有开发者(至少一位)抱怨说这个做得有点过了。
直接链接到 Linux kernel 的代码都可以使用它可以看到的任何 symble。而 loadable module 则被限制只能访问所有 symbol 的一个较小的子集(尽管仍然很大),这个子集中的 symbol 都是明确地 "ecxport" 出来供 module 使用的。用 EXPORT_SYMBOL() 导出的符号对所有 loadable module 来说都是可以使用的,而用 EXPORT_SYMBOL_GPL() 导出的符号则只能供声明了 GPL 兼容许可证的 module 使用。如果某个不兼容 GPL 的 module 试图调用一个只适用于 GPL 的 symbol,那就在 load 的时候就会出错。
GPL-only 这种 export 方式产生的逻辑是,这类 symbol 都是内核中很核心的代码,使用到这些 symbol 的 module 必须算是内核的派生产品(derived product),因此就要遵守 GPL 的要求。在实践中,大家很少会真的去做这种分析判断,因而某些 symbol 是否采用 GPL-only export 主要是由开发者个人决定的。许多开发者因为非常讨厌 proprietary module,因此习惯性地会把对他们所 export 出来的每一个 symbol 都使用 EXPORT_SYMBOL_GPL()。一些维护者也鼓励那些经他们之手合入的代码都采用这种做法。
多年来,proprietary module 的作者们采取了许多技巧来绕过 GPL-only export 的限制。其中之一就是用 kallsyms_lookup_name() 来手动查找 symbol 的地址。这种做法在 2020 年初之后无法再使用了。另一个方法是将一个 module 分成两个,其中之一是 GPL 许可的,另一个则采用专有的协议。GPL 许可的 module 直接与内核对接,可以在需要的时候使用 GPL-only 的 symbol,然后它再调用 proprietary module 来完成真正要做的工作。
在 2020 年 7 月,这种跳板功能的 module 在邮件列表中引起了轩然大波,于是 Christoph Hellwig 发布了一组 patch 来给这种用法增加困难。具体来说,任何调用了由 proprietary module 所 export 出来的 symbol 的 module,本身都会被标记为 proprietary module,无论它向内核声明的许可是什么。因此,那些使用了 proprietary module 的 module 将无法再访问 GPL-only 的 symbol,这样一来它们就不可能再完成它的跳板功能了。这个系列在 10 月份的 5.9 内核版本中被合并。
当时就这么结束了,直到 2021 年 5 月,这组 patch 被包括在了 5.4.118、4.19.191 和 4.14.233 的众多更新之中。大概又过了接近一个月,5.4.118 才被某个发行版所包含,然后让用户碰到了问题,这时 Krzysztof Kozlowski 问道,为什么这样的改动会被包含在一个 stable update 中:
这怎么会算是一个该进入 stable kernel 的改动?它修复了什么具体的、真正困扰人们的 bug 吗?或者说,它修复了发行版中某个 kernel 用户报告的严重问题了吗?也就是说,这组 patch 符合 stable kernel 的原有规则吗?
它已经被证实导致了一些之前已经存在的 kernel tree 之外、并且 stable kernel 的有些用户一直在用的 module 不再可用了。因此,我想知道这里修复的是什么 bug,这样破坏现有功能以及打扰 stable kernel 的用户是否合理。
Stable-kernel 的维护者 Greg Kroah-Hartman 回应说:
它修复了人们报告出来的一个错误,即通过某种方式将 symbol export 出来供那些不应该有权使用的 module 使用了。这个问题在 mainline 和较新的 stable kernel release 中已经存在了相当长的时间,因此大家也不应该想不到它会被进一步地 backport 会更老版本的 stable kernel 之中。
讨论基本上就这么结束了,有些人可能会对这个改动进入那些旧版本的内核感到不那么高兴,但不清楚是不是有人真的寄希望于这组 patch 被 revert 掉。不过,可以后续再观察一下各个发行版提供商的内核更新,看看他们是会保留这种对 proprietary module 的额外限制呢,还是会悄悄删除掉,这会很有趣。
不过,这一改动确实说明了 kernel 的 "no regressions" 政策至少有一个限制。这个政策的核心思想是,内核的升级不应该破坏一个现在能正常运行的系统。内核开发者希望用户能够有信心来转移到较新版本的内核而不用冒一些出错的风险。据 Kozlowski 说,这一改动确实让一些用户碰到了麻烦。但是 kernel module 从来未被包括在内核的 stability 保证中,就连 GPL-licensed kernel module 也没有保证稳定。当某个 proprietary module 碰到麻烦时,内核开发者很少会感到伤心,这次也同样。
当 Hellwig 的这组 patch 第一次发布时,LWN 就注意到它并没有堵上全部漏洞。具体来说,如果一个 GPL-licensed module 将 symbol 重新包装一下再 export 给一个 proprietary module 的话,只要并没有从该 proprietary module 中 import 过 symbol,那么就仍然可以正常工作。这个问题是由 David Laight 在这次讨论中也指出了。Kroah-Hartman 回应并承诺说:"正在努力解决这个问题,预计会放在下周的一组 patch 之中"。所以,对于开发和使用 proprietary loadable module 的人来说,后续可能还会有更多的麻烦。
多年以来内核社区对 loadable module 的策略受到了来自各方的批评。一些人认为,哪怕是勉为其难地容忍这些 proprietary module,这也是事实上削弱了 GPL 所提供的保护,并且是纵容了那些不想按规则行事的厂商。另一些人则认为这是对使用 Linux 的一种障碍,因为它减少了所能支持的硬件,使得用户需要克服不必要的麻烦。不过,评判这一政策的最好方法是看看过去近三十年来它带来了什么效果。
目前 proprietary module 仍然存在,但这是少数情况。大多数硬件都得到了自由软件协议的驱动程序(free drivers),而且情况似乎还在继续改善。过去一些坚持使用 proprietary module 的厂商已经找到了方法来改变这种做法。如果这些厂商完全被排除在 Linux 社区之外的话,可能就不会是现在这种情况了。因此,也许从长远来看,可能最有成效的策略仍是让这些 module 的发布方过得不太舒服、同时又不去直接禁止它们。
全文完
LWN 文章遵循 CC BY-SA 4.0 许可协议。
长按下面二维码关注,关注 LWN 深度文章以及开源社区的各种新近言论~