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

2024-01-02 14:40

本文主要是介绍LWN:在GCC和glibc里支持 CHERI 的 capability!,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

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

Supporting CHERI capabilities in GCC and glibc

By Jonathan Corbet
September 26, 2022
Cauldron
DeepL assisted translation
https://lwn.net/Articles/909265/

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

CHERI

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

9011a7991ba18e81d2e2489df7676189.png

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

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

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

Morello GCC

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

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

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

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

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

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

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

Porting glibc

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

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

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

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

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

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

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

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

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

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

format,png

这篇关于LWN:在GCC和glibc里支持 CHERI 的 capability!的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/562753

相关文章

Golang支持平滑升级的HTTP服务

前段时间用Golang在做一个HTTP的接口,因编译型语言的特性,修改了代码需要重新编译可执行文件,关闭正在运行的老程序,并启动新程序。对于访问量较大的面向用户的产品,关闭、重启的过程中势必会出现无法访问的情况,从而影响用户体验。 使用Golang的系统包开发HTTP服务,是无法支持平滑升级(优雅重启)的,本文将探讨如何解决该问题。 一、平滑升级(优雅重启)的一般思路 一般情况下,要实现平滑

sqlite不支持中文排序,采用java排序

方式一 不支持含有重复字段进行排序 /*** sqlite不支持中文排序,改用java排序* 根据指定的对象属性字段,排序对象集合,顺序* @param list* @param field* @return*/public static List sortListByField(List<?> list,String field){List temp = new ArrayList(

一款支持同一个屏幕界面同时播放多个视频的视频播放软件

GridPlayer 是一款基于 VLC 的免费开源跨平台多视频同步播放工具,支持在一块屏幕上同时播放多个视频。其主要功能包括: 多视频播放:用户可以在一个窗口中同时播放任意数量的视频,数量仅受硬件性能限制。支持多种格式和流媒体:GridPlayer 支持所有由 VLC 支持的视频格式以及流媒体 URL(如 m3u8 链接)。自定义网格布局:用户可以配置播放器的网格布局,以适应不同的观看需求。硬

Science Robotics 首尔国立大学研究团队推出BBEX外骨骼,实现多维力量支持!

重复性举起物体可能会对脊柱和背部肌肉造成损伤,由此引发的腰椎损伤是工业环境等工作场所中一个普遍且令人关注的问题。为了减轻这类伤害,有研究人员已经研发出在举起任务中为工人提供辅助的背部支撑装置。然而,现有的这类装置通常无法在非对称性的举重过程中提供多维度的力量支持。此外,针对整个人体脊柱的设备安全性验证也一直是一个缺失的环节。 据探索前沿科技边界,传递前沿科技成果的X-robot投稿,来自首尔国立

bash: arm-linux-gcc: No such file or directory

ubuntu出故障重装了系统,一直用着的gcc使用不了,提示bash: arm-linux-gcc: No such file or directorywhich找到的命令所在的目录 在google上翻了一阵发现此类问题的帖子不多,后来在Freescale的的LTIB环境配置文档中发现有这么一段:     # Packages required for 64-bit Ubuntu

编译linux内核出现 arm-eabi-gcc: error: : No such file or directory

external/e2fsprogs/lib/ext2fs/tdb.c:673:29: warning: comparison between : In function 'max2165_set_params': -。。。。。。。。。。。。。。。。。。 。。。。。。。。。。。。。 。。。。。。。。 host asm: libdvm <= dalvik/vm/mterp/out/Inte

【linux学习指南】Linux编译器 gcc和g++使用

文章目录 📝前言🌠 gcc如何完成🌉预处理(进行宏替换) 🌠编译(生成汇编)🌉汇编(生成机器可识别代码) 🌠链接(生成可执行文件或库文件)🌉函数库 🌠gcc选项🚩总结 📝前言 预处理(进行宏替换)编译(生成汇编)汇编(生成机器可识别代码)连接(生成可执行文件或库文件) 🌠 gcc如何完成 格式 :gcc [选项] 要编译的文件 [选项] [目标文

超级 密码加密 解密 源码,支持表情,符号,数字,字母,加密

超级 密码加密 解密 源码,支持表情,符号,数字,字母,加密 可以将表情,动物,水果,表情,手势,猫语,兽语,狗语,爱语,符号,数字,字母,加密和解密 可以将文字、字母、数字、代码、标点符号等内容转换成新的文字形式,通过简单的文字以不同的排列顺序来表达不同的内容 源码截图: https://www.httple.net/152649.html

gcc编译常见问题

inux C gcc -lm     使用 math.h中声明的库函数还有一点特殊之处,gcc命令行必须加-lm选项 ,因为数学函数位于 libm.so 库文件中(这些库文件通常位于/lib目录下),-lm选项告诉编译器,我们程序中用到的数学函数要到这个库文件里找。本书用到的大部分库函数(例如printf)位于 libc.so 库文件中,使用libc.so中的库函数在编译时不需要加-l

QtC++截图支持窗口获取

介绍 在截图工具中你会发现,接触到窗口后会自动圈出目标窗口,个别强大一点的还能进行元素识别可以自动圈出元素,那么今天简单分析一下QTc++如何获取窗口并圈出当前鼠标下的窗口。 介绍1.如何获取所有窗口2.比较函数3.实现窗口判断 结尾 1.如何获取所有窗口 1.我们需要调用windows接口EnumWindowsProc回调函数来获取所有顶级窗口,需要包含windows.