RFC-0090 - 驱动程序共享库许可名单

RFC-0090:驱动程序共享库许可名单
状态已接受
区域
  • 内核
说明

为驱动程序共享库添加了许可名单。

Gerrit 更改
作者
审核人
提交日期(年-月-日)2021-03-30
审核日期(年-月-日)2021-04-28

摘要

此 RFC 建议驱动程序框架添加一个明确的许可名单,其中列出了驱动程序可以依赖的共享库。此许可名单将在 Fuchsia 树中的 build 时和驱动程序管理器中的运行时进行检查。依赖于不在许可名单中的共享库的驱动程序将无法运行。

此 RFC 旨在将驱动程序作者与驱动程序框架之间长期存在的非正式协议正式化。驱动程序作者目前知道他们不应依赖无关的共享库,但目前还没有明确的共享库许可名单。

问题陈述和动机

Fuchsia 中的驱动程序以共享库的形式实现。驱动程序会加载到驱动程序宿主中。 驱动程序宿主表示可以容纳多个驱动程序的单个进程。驱动程序本身可以依赖于其他共享库,这些共享库也需要加载到驱动程序宿主中。

由于驱动程序及其共享库都存在于同一进程中,因此共享库可能会以微妙且未定义的方式发生冲突。树外构建的驱动程序可能会尝试链接到另一个驱动程序正在使用的同一共享库的较新或较旧版本。两个共享库中同一符号的多个实现会使符号解析变得不确定。此外,共享库中的全局变量可以视为同一驱动程序主机中驱动程序之间意外的共享状态。如果没有许可名单,驱动程序可能会开始通过不受支持的共享库进行通信。驱动程序框架需要某种方式来阻止驱动程序使用不受支持的共享库,这既是为了安全,也是为了正确性。

此 RFC 提出的解决方案是为驱动程序提供构建时和运行时共享库许可名单。驱动程序将无法链接到不在许可名单中的共享库。此许可名单上的所有共享库都将由 Fuchsia 平台提供,而不是由各个驱动程序提供。

此问题的长期解决方案是使用命名空间型动态链接器。借助这种链接器,每个驱动程序在进程中都有自己的“命名空间”,并且驱动程序的共享库不会发生冲突。如果驱动程序框架具有命名空间的动态链接器,则不再需要共享库许可名单。

为何要立即启用?

驱动程序框架正在实现两项需要严格许可名单的新功能:树外驱动程序和驱动程序软件包。这两项功能都会从新位置加载驱动程序,这意味着系统如何处理驱动程序的共享库变得不明确。明确规定驱动程序的共享库将从 Fuchsia 平台加载,可减少系统歧义,并确保每个驱动程序在运行时获得相同版本的共享库。拥有共享库的许可名单是保持所有驱动程序的共享库在 Fuchsia 映像中的前提条件。

设计

驱动程序框架将维护一个共享库列表,其中包含允许驱动程序链接的共享库。此列表的初始内容将是驱动程序当前链接的所有共享库。可以向该列表添加库或从中移除库,但需要获得驱动程序框架团队的许可。

此许可名单上的所有共享库都将由 Fuchsia 平台提供。许多此类共享库将作为启动文件系统 (bootfs) 项存在于 ZBI 中的 /boot/lib/,以便驱动程序在早期启动时加载它们。驱动程序的加载器服务将仅从许可名单中加载共享库,而不会加载各个驱动程序提供的库。

驱动程序将无法链接到不在许可名单中的共享库。如果驱动程序尝试链接到不在列表中的共享库,驱动程序框架将创建构建时错误。如果已加载的驱动程序尝试访问不在列表中的共享库,驱动程序管理器将记录运行时错误。

新共享媒体库的考虑标准

驱动程序框架团队将能够根据自己的判断将新的共享库添加到许可名单中。对于任何新的共享库,都必须考虑以下事项:

  • 库的大小。如果共享库将存储在 ZBI 中,则必须有空间。如果库将位于存储空间中,则这一点不太重要。

实现

许可名单将根据驱动程序当前使用的共享库列表生成。 然后,实现用于在 build 时检查许可名单的机制。之后,系统将实现用于在运行时检查许可名单的机制。由于初始列表将包含驱动程序当前使用的所有共享库,因此无需进行驱动程序更改。

运行时实现可以通过在驱动程序框架中使用自定义 fuchsia.ldsvc.Loader 实现来完成。此实现不需要对代码库的其他区域进行架构更改。

性能

这不会对效果产生任何影响。

安全注意事项

此提案对安全性有积极影响。它使驱动程序的共享库使用情况更易于审核,并减少了因共享库冲突而导致未定义行为的可能性。

隐私注意事项

这可能会对隐私权产生积极影响,因为它可以减少驱动程序之间共享状态的表面。

测试

我们将先实现 build 时间检查,这意味着主要测试是树是否正确构建。目前没有树外驱动程序,因此如果树构建正确,则所有驱动程序都符合共享库许可名单。

实现 build 时检查后,将实现运行时检查,以期支持未来的树外驱动程序。这将包含集成测试。

文档

此 RFC 记录了我们决定创建许可名单的过程。

有关许可名单的详细信息将添加到 fuchsia.dev 网站上的驱动程序教程中。 这包括请求和批准许可名单变更的流程。

缺点、替代方案和未知因素

一个缺点是,如果我们有命名空间的动态链接器,则不需要此许可名单。如果存在该链接器,我们将能够重新评估并可能移除许可名单。

许可名单限制了驱动程序可以关联的共享库的数量,但可能无法充分确保共享库的版本相同。树外驱动程序可能会尝试针对许可名单中的较新版本的共享库进行构建,但当系统在运行时使用来自 bootfs 的较旧版本的库时,会失败。在实现许可名单后,可能需要进行后续工作,以确保树外驱动程序针对同一版本进行构建。

另一个缺点是,驱动程序所有者可能会通过静态链接其库来响应共享库许可名单。使用静态链接的库会增加驱动程序的代码大小。这是这种方法带来的一个令人遗憾但又不可避免的副作用。如前所述,此问题的长期解决方案是使用命名空间的动态链接器,这样驱动程序就可以在不使用许可名单的情况下使用共享库。

在先技术和参考资料

Zircon build 最初有一个驱动程序的共享库许可名单。在 build 统一期间,为了简化统一流程,移除了此许可名单。我们一直打算重新实现它,但直到现在才将其列为优先事项。

驱动程序管理器目前具有共享库许可名单的运行时实现,但从未开启过。目前,该功能已通过内核命令行选项 devmgr.devhost.strict-linking 启用。为了实现许可名单,我们将更新此实现。