首页 >> 大全

LWN:在GCC和glibc里支持 CHERI 的 capability!

2024-01-02 大全 22 作者:考证青年

CHERI in GCC and glibc

By

26, 2022

DeepL

CHERI 架构来自于一个研究计划,希望能对普通的 CPU 架构进行扩展,来阻止多种类型的内存相关 bug(和漏洞)。在 2022 年的 GNU Tools 会议上,Alex 和 Nagy 介绍了将 GCC 和 GNU C (glibc)引入该架构的工作。CHERI 从根本上改变了内存访问方式,要想能正确地支持这个架构,可不是一个小任务。

CHERI

首先介绍了 CHERI,这是一个已经运行了十年左右的研究项目,来自于剑桥大学。它引入了 "" 的概念,这个术语在这里的含义跟平常不太一样。 说, 是访问一系列内存的一个 token,不能被伪造()。 可以传送给别人,它们可以从其他 派生()出来,但这样派生之后获得的 拥有的 不能增加,只能减少。

在 CHERI 架构的概述中可以看到更多描述找到。简而言之,一个 可以被认为是一个特殊类型的指针,占据了 129 bits。其中最低位的 64 bit 是传统的虚拟地址,而更高的 64 位(通常被称为 " (出处)")描述了相关的访问权限。其中包括了用来指示允许的操作(读、写、执行)的 , 以及该 适用的内存区域。这 128 位加在一起,就可以像一个指针一样在允许的内存范围内进行它所允许的访问。

第 129 位存储在其他地方,由 CPU 管理;只有在这个 bit 置 1 的时候,这个 才是有效的。一些 CPU 指令可以从一个旧的 衍生出一个新的 ,这些指令将保持这个 bit 的设置;对这个 的直接修改,会导致这个生效 bit 被清零。其他不被允许的操作,如试图使用一个 在允许的内存范围之外写入,也会使该 失效。如果硬件设计完好无误,那么每一个 都允许以某些方式访问内存范围,仅此而已。

在系统启动时, 为内核提供了一个对所有内存都允许访问的 。在系统的生命周期中使用的每一个其他 最终都来自于这个 "root "。设计良好的系统里,每个 可能经过几个层次的衍生之后,就被缩小到一小块内存区域了。

GCC

CHERI 是定义成附加在现有架构上的一个组件的; 项目就是在向 ARMv8-A 架构添加 CHERI 功能。现在已有原型实现了这种组合。基于 LLVM 的成熟 也有了,但 ARM 也希望有 GCC 的版本,因此 GCC 项目正在努力在 GCC 中增加支持;该项目还在移植 、GDB 和 glibc。

已经实现了两种 model,称为 "pure-cap "和 "";前者将 施加在所有指针上,而后者只对系统中的一部分指针使用 。 模式可以允许把那些支持 的代码跟不支持 的代码混合在一起运行;Linux 内核已经利用 模式获得了对 架构的支持。

在尝试这个移植时,面临了很多挑战。第一步是重新映射 type(这是描述一个用来容纳指针值的整数)。当然,这里要解决的核心问题就是普通的 long 形不够用来放置 ;如果试图使用从 long 中提取的指针,都会在运行时被捕获。因此,在按这种方式使用此类型的代码在 CHERI 系统中就无法运行了。对指针进行比较,也比较棘手;两个指向同一位置的 可能有不同的访问权限,因此两者逐 bit 比较的话并不完全相等,但在指针比较的时候应该判定它们是相等的。

说,尽管有这些陷阱,但大多数代码在 pure-cap 模式下编译就可以正常工作。不过,那些非常底层的软件代码则可能需要大量的修改,尤其是那些把玩指针的代码可能会有问题。例如,在 GCC 中有一个排序功能,它会利用指针完成一些技巧,这就会导致编译器报错。

要教会 GCC 能了解 ,就是一个很大的挑战,需要对整个代码进行许多修改。它们打破了 GCC 内部的两个基本假设: 指针和 整数是完全可以直接互相替换的,以及假设地址和 本质上是同一种性质的。编译器必须确保所有指针都有正确的出处,以及确保指针比较要给出正确的结果,等等。

GCC 的工作最开始是增加了一个 -mfake- 选项,这使得编译器在其内部表示中可以一直使用 方式,但仍像以前一样利用 来生成标准代码。这使得 的概念与 架构的具体细节可以隔离开了。开发人员首先努力使所有的地方都能使用这个 flag,然后才着手生成能在真实硬件上使用 的代码。

剩下的一个问题是, 中的地址范围的边界是用压缩浮点表示法来存储的;否则,这些信息就没法塞在那些 bits 里了。但是这就导致,无法把所有的地址、base 和 limit 的组合都被表示出来。 说,这个问题主要对内存分配器有影响,必须要能对更大范围的内存进行操作。

glibc

Nagy 接着谈到了为了把 glibc 移植到 架构上所做的工作。这项工作目前是在一个单独的分支中进行的,没有计划将其提交到上游,需要等到可以创建一个更干净的 patch set 再说了。他说,需要对 glibc 进行大量修改;CHERI C 是一种完全不同的语言。比如说需要把所有操作指针的代码都修改掉。

更细节的问题是,必须对 ()等基本函数进行特殊处理。除非特别小心,否则存储在要复制的内存中的任何 在复制目标那里都会完全无效。()必须返回 类型(这是一个 ABI 变动)才能成功返回一个指针,其他许多系统调用也需要类似的改变。

然后是 (衍生)的问题。当内核启动一个进程时,该进程获得了一个能够访问整个用户空间的一个 。当然,有可能可以继续使用这个 来完成所有一切工作,这是第一步,但它并没有真正利用上 机制。所以下一步是在不需要访问所有内存的特定情况下来缩小 。

还有一个更棘手的问题,就是动态链接器 ,它对 64 位地址进行了大量操作。不过,它是与 ELF 二进制文件配合工作的,所以它的大部分工作是以 "base 加 " 的形式进行计算的。如果 base 值是一个正确的 ,那么一切都可以正常工作。随着最初的问题被克服,下一阶段是开始将允许写入的 与允许执行的 区分开;这将需要在 中更加谨慎地处理,他说。

然后是 () 的问题。理想情况下,这个函数将返回一个可以访问到被分配对象的指针(不可以访问到其他任何东西)。在第一阶段,并没有实现缩小访问范围的工作;工作重心是希望让基本功能可以正常工作起来。第二阶段则要把返回的指针的范围缩小到只有相关的对象的范围。但这给 free() 带来了挑战,它必须能够访问存储在这个对象本身之外的 ;这要给 free() 单独准备一个特殊的 来使用。他说,要使所有这些工作顺利进行的话,还有其他各种挑战;他将为 CHERI 实际上设计了专用的 ()接口。

他说,目前 test 可以运行,但只有在 GCC 中不使用 stack bound 的情况下才能运行。此外还有一些缺失的功能,包括 、支持可执行的 stack、对 的支持,以及对存储在共享内存或通过文件描述符发送的指针的支持。他总结说,后面这些情况可能永远都无法支持起来。

[感谢 LWN 订户支持编者参加这次活动]。

全文完

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

关于我们

最火推荐

小编推荐

联系我们


版权声明:本站内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 88@qq.com 举报,一经查实,本站将立刻删除。备案号:桂ICP备2021009421号
Powered By Z-BlogPHP.
复制成功
微信号:
我知道了