
1. 项目概述为什么RISC-V需要一个全新的TEE方案在当前的机密计算领域可信执行环境TEE已经成为保护云端和边缘设备上敏感数据与代码的基石。无论是Intel SGX、AMD SEV还是ARM CCA它们都依赖于特定的、闭源的硬件扩展来构建那个被称为“飞地”的安全隔离区域。然而当我们将目光投向RISC-V——这个以开放、模块化著称的指令集架构时会发现一个尴尬的局面现有的TEE方案在标准RISC-V平台上往往在可扩展性和兼容性之间难以两全。问题的根源在于RISC-V标准中广泛支持的物理内存保护PMP机制。PMP通过一组数量有限的硬件寄存器来定义内存区域的访问权限是实现隔离的直接硬件原语。但它的设计初衷是简单的嵌入式系统安全当面对需要支持成百上千个并发飞地的云场景时其有限的条目数通常只有8或16个就成了难以逾越的瓶颈。像Keystone这样的先驱项目其飞地数量就被限制在16个以内。另一方面为了突破这个限制而提出的方案如Penglai或TIMBER-V要么依赖尚未标准化的硬件扩展要么需要对MMU等核心部件进行定制修改这极大地牺牲了硬件兼容性使得它们无法部署在大量已上市的商用RISC-V设备上。这就是COFFER诞生的背景。我们团队在设计和实现这个项目时核心目标非常明确在不修改标准RISC-V硬件的前提下构建一个既能支持海量飞地又能高效运行并且具备高度软件兼容性的TEE系统。我们不仅要解决“能不能用”的问题更要解决“好不好用”的问题。这意味着我们需要在PMP这个“简陋”的硬件基础上通过纯粹的软件创新变魔术般地变出近乎无限的隔离能力同时还要保证飞地应用的性能开销可以忽略不计。如果你正在RISC-V平台上探索机密计算的可能性或者对如何用软件“增强”硬件安全特性感兴趣那么COFFER的设计思路和实现细节或许能给你带来一些全新的启发。接下来我将带你深入COFFER的内部拆解我们是如何用两个核心创新——逻辑PMPLPMP和飞地模块EModules——来攻克上述挑战的。2. 核心设计思路LPMP与EModules如何重塑RISC-V TEECOFFER的整体架构可以看作一次对传统TEE设计哲学的重新思考。我们摒弃了“依赖特权环境REE提供功能”和“受限于硬件条目”这两个固有思维转而追求飞地的自主性和系统的无限扩展性。2.1 逻辑PMP将有限的硬件变成无限的“缓存”LPMP是整个系统的基石它的核心思想是虚拟化PMP条目。你可以把它理解为一个软件管理的“PMP条目缓存”。2.1.1 对称设计打破飞地数量的枷锁传统的RISC-V TEE如Keystone采用了一种非对称的内存视图。在主机操作系统看来它需要用PMP条目来“禁止”访问所有飞地的内存因此所需的PMP条目数随着飞地数量线性增长N_host_pmp N_enclave 1很快就耗尽了硬件资源。COFFER的LPMP采用了对称设计。我们将主机操作系统也视为一个特殊的“飞地”。系统启动时我们从物理内存中预留出一块连续的“飞地内存池”。主机操作系统的内存是另一块连续区域与飞地内存池相邻。通过一个灵活的边界主机可以在内存压力大时从飞地内存池的边缘进行分配如果边缘被飞地占用内存管理器会迁移飞地内存为主机腾出空间。在这种设计下无论是主机还是任何一个飞地在任一时刻都只需要一个PMP条目来允许访问自己的内存区域。飞地数量的理论上限被彻底移除系统的可扩展性只受限于总物理内存大小。实操心得内存池管理实现这个灵活边界是关键。我们在安全监视器中维护了一个内存所有权表。当主机需要内存时内存管理器会优先尝试从飞地内存池的边界区域分配。如果该区域已被飞地占用管理器会选择一个内部区域作为目标执行内存拷贝和页表更新然后将原区域释放给主机。这个过程对飞地是透明的确保了主机内存分配的灵活性。2.1.2 虚拟条目与缓存策略应对内存碎片化对称设计解决了飞地数量的问题但每个飞地内部可能拥有多个离散的内存段例如多个动态分配的堆块。硬件PMP条目仍然有限无法覆盖所有段。LPMP的答案是为每个飞地维护一个虚拟的LPMP条目链表链表长度不限可以记录飞地拥有的所有内存段。硬件PMP寄存器则作为这个链表的缓存。在上下文切换到某个飞地时安全监视器将链表头部的N_max_pmp个条目加载到真实的PMP寄存器中。当飞地访问一个地址而该地址所在的段不在当前的硬件PMP缓存中时会触发一个“LPMP陷阱”。安全监视器会处理这个陷阱它检查该地址是否属于该飞地通过查询内存所有权表如果是则将对应的LPMP条目移动到链表头部并更新硬件PMP配置将“最近最少使用”的条目换出。这个过程模拟了CPU缓存的工作方式。为了进一步优化我们借鉴了现代缓存设计的指令/数据分离策略。我们为指令访问和数据访问分别保留至少一个专用的PMP条目。这是因为代码段通常具有很高的空间局部性程序顺序执行而数据访问可能更随机。如果不分离频繁的数据访问可能会不断换出代码段的PMP条目导致不必要的陷阱。分离后代码段的PMP条目得以常驻显著减少了指令取指引发的陷阱频率。2.1.3 利用TLB意想不到的性能加速器在深入研究商用RISC-V平台如HiFive Unmatched时我们发现一个有趣的现象当MMU启用时PMP检查只在TLB缺失即页表遍历时发生。对于已经缓存在TLB中的地址转换PMP检查会被跳过直接使用之前缓存的结果。RISC-V规范建议在每次PMP配置更新后刷新整个TLB以确保安全。但我们发现这个要求可以放宽。我们只需要保证TLB中缓存的PMP检查结果与飞地的LPMP链表一致而非与瞬时的硬件PMP配置一致。因此在发生LPMP陷阱时我们只选择性刷新TLB中那个导致陷阱的、具有“禁止访问”结果的特定条目。其他TLB条目只要其对应的LPMP条目仍在链表中即使当前未被加载到硬件PMP其缓存的结果就依然有效。这相当于利用TLB的容量进一步扩展了有效的PMP条目数。安全原则TLB维护的两条铁律利用TLB缓存是性能优化的关键但必须确保安全。我们制定了两个必须遵守的原则TLB独占所有权在任何时刻所有TLB条目必须完全属于单一实体主机或某个飞地。为此在每次进入或退出飞地的上下文切换时LPMP控制器都会执行完整的TLB刷新。新鲜度保证TLB缓存的PMP检查结果必须与飞地LPMP链表的最新状态一致。当飞地的LPMP链表被修改时如内存分配也必须执行完整的TLB刷新。 这两条原则确保了即使利用缓存内存隔离的强安全性也绝不会被破坏。2.2 飞地模块构建自主、精简的可信计算基传统TEE飞地为了保持TCB可信计算基小巧往往将大量系统功能如文件操作、网络委托给不可信的主机操作系统处理。这不仅导致了频繁且昂贵的域切换上下文切换更扩大了攻击面使得飞地容易遭受诸如Iago攻击通过操纵系统调用返回值进行攻击的威胁。COFFER提出了飞地模块的概念来彻底解决这个问题。EModule是一个个模块化、轻量级的库每个专注于提供一项特定的OS功能如内存分配、文件系统访问、设备驱动。一个特殊的、必需的模块叫EMod_Manager它负责飞地启动、管理其他EModule并处理一些最基础的系统调用。2.2.1 动态组装与按需加载飞地不再是静态链接所有库的臃肿镜像。相反它在运行时按需动态加载所需的EModule。当EApp飞地应用调用某个由特定EModule提供的功能时EMod_Manager会验证并加载该模块。每个飞地都附带一个用户定义的EModule权限表。在加载任何EModule前EMod_Manager会检查飞地是否拥有该模块的权限。如果没有则立即中止飞地执行。这个权限表会与EApp一起进行完整性度量生成飞地摘要报告确保其不可篡改。这种设计带来了巨大的灵活性。即使运行相同的EApp不同的用户也可以为其配置不同的权限表从而定制出完全不同的TCB。一个只需要进行纯计算的飞地可能只包含EMod_Manager和一个内存分配模块而一个需要复杂I/O的飞地则可以动态加载文件系统、网络等模块。2.2.2 实现飞地自主性通过EModule飞地实现了关键功能的自主性。它不再需要将系统调用代理给主机所有OS服务都在飞地内部完成。这极大地减少了与不可信REE的交互不仅提升了性能减少了域切换更重要的是显著缩小了攻击面。恶意操作系统无法再通过操纵系统调用返回值或页表来攻击飞地。当然完全的自主并不意味着完全与世隔绝。为了高效的批量I/O安全监视器提供了一个安全的消息通道接口。发送方将数据写入一个新分配的内存区域然后通知安全监视器将该区域的所有权转移给接收方。在整个过程中独占所有权原则被严格执行数据本身无需在REE中“暴露”实现了安全高效的数据交换。3. 实现细节从理论到可运行的代码理解了设计思路我们来看看如何将其落地。我们的COFFER原型基于OpenSBI v0.9实现安全监视器并成功在HiFive Unmatched、VisionFive 2等商用RISC-V开发板上运行。3.1 安全监视器的四大组件安全监视器运行在机器模式是系统的信任根。它由四个核心组件构成飞地管理器负责飞地的全生命周期管理包括创建、进入、退出、暂停、恢复和证明。它修改了medelegCSR以拦截所有来自用户模式和监管模式的ecall并将主机的系统调用重定向回OS内核。内存管理器管理预留的飞地内存池。我们将内存池划分为2MB大小的块与RISC-V SV39标准的大页大小对齐以简化管理。内部维护一个内存所有权表。它支持动态分配并在主机需要时执行内存迁移以调整灵活边界。LPMP控制器这是实现可扩展隔离的核心。它为每个飞地维护LPMP条目链表使用静态数组实现大小等于内存池块数。在上下文切换时它用链表中的条目填充PMP CSR。对于对齐的地址使用NAPOT模式非对齐的则使用TOR模式每个区域消耗两个CSR。发生LPMP故障时它检查访问地址的归属更新链表MRU策略并相应地更新PMP配置和TLB。消息通道控制器为REE和TEE之间的通信建立安全通道。提供了channel_listen,channel_send,channel_stop三个ecall接口。发送消息时控制器会先根据内存所有权表验证消息源物理内存的所有权然后通过临时切换内存访问模式等方式安全地完成内存拷贝。3.2 EModule的实现我们实现了六个最基础的EModule来验证概念EMod_Manager必需模块约2100行代码。负责飞地初始化、模块管理和简单系统调用分发。EMod_Alloc堆内存分配器移植自musl-libc的分配器。EMod_Futex快速用户态互斥锁支持移植自Linux内核。EMod_UART串口设备驱动移植自Linux内核。EMod_VFS虚拟文件系统支持RAMFS移植自Unikraft的vfscore库约5490行代码是当前最复杂的模块。这些模块共同提供了50多个最常用的系统调用足以支持运行Redis、SQLite3、DarkNet等真实应用。实操心得模块的完整性与信任链从成熟项目如Linux内核、musl-libc移植代码大大减少了工程工作量并保证了功能正确性。每个EModule镜像都包含开发者的数字签名。EMod_Manager在加载任何模块前都会先进行ECDSA签名验证。平台所有者控制着签名密钥这建立了一个清晰的信任链。虽然当前原型专注于基础的签名验证但完整的生命周期管理如自动版本追踪、撤销机制、运行时补丁是未来工作的重要方向。4. 性能与可扩展性评估理论再好也需要数据支撑。我们在HiFive Unmatched开发板四核SiFive U74, 16GB DRAM上进行了全面的评估所有数据均为30次重复实验的平均值。4.1 可扩展性支持2000并发飞地数量可扩展性我们启动了多达2048个并发飞地均匀分布在四个核心上每个飞地运行RV8基准测试集中的sha512。结果显示即使并发飞地数量超过2000个其平均执行时间与最慢飞地的执行时间相比单飞地运行时的开销也始终保持在1%以内。这证明了LPMP的对称设计和虚拟化机制的有效性性能开销不会随飞地数量增加而显著增长。内存可扩展性我们让飞地运行stress-ng的memrate工作负载分配从128MiB到2GB不同大小的内存缓冲区。与原生Linux进程相比COFFER飞地的性能开销大约在6%左右。这部分开销主要来自我们原型中使用的轻量级内存分配器EMod_Alloc它并未针对缓存友好性进行深度优化。使用更成熟的内存分配器可以进一步改善性能。4.2 内存碎片化下的效率接近原生性能我们模拟了最坏情况飞地的所有物理页都不相邻且仅使用TOR模式最通用但最难扩展的模式。我们在这种极端碎片化环境下运行RV8基准测试和stress-ng的vm工作负载。结果令人振奋未优化的LPMP在内存密集型测试中完全无法在合理时间内完成超过1小时。仅启用指令/数据分离优化后对计算密集型RV8基准测试提升有限但对纯内存访问的stress-ng测试提升巨大。仅启用TLB增强优化后情况相反对RV8基准测试提升显著对stress-ng提升一般。当同时启用两项优化时在所有测试中COFFER飞地的性能开销相比无PMP保护的基线都控制在3%以内。这表明我们的优化策略是互补且高效的使得飞地即使在物理内存高度碎片化的情况下也能以近乎原生的速度执行。4.3 通用性能与真实应用在RV8基准测试套件上COFFER飞地的性能开销普遍低于5%。对于primes和qsort测试飞地甚至比Linux进程更快。这是因为我们原型中为了复用Linux调度器每100次定时器中断才切换回Linux一次这比Linux原生进程的调度切换次数更少。但这不应被视为COFFER的性能优势而是一种实现策略的副作用。在真实应用测试中DarkNet神经网络推理COFFER飞地性能与Linux进程相当。SQLite3数据库对于写密集型负载开销较高~15%这是因为我们使用的EMod_VFS是一个轻量级RAMFS实现对于读密集型负载开销则低于5%。这说明了I/O模块的性能对整体体验的影响也指明了未来优化的方向——集成更高效的文件系统EModule。5. 对比分析与未来展望我们将COFFER与现有的先进RISC-V TEE进行了对比见表VI。结论很清晰COFFER是首个在标准RISC-V平台上同时实现高可扩展性支持超2000飞地、高兼容性仅依赖标准PMP、飞地自主性且性能优异的软件TEE方案。Keystone软件方案兼容性好但受PMP条目限制仅支持≤16个飞地。Penglai/TIMBER-V可扩展性好但依赖定制硬件修改MMU或使用内存标签兼容性差。Sanctum/Composite Enclaves同样存在可扩展性或兼容性限制。COFFER的创新在于它没有等待新的硬件安全扩展而是通过纯粹的软件设计将现有硬件的潜力挖掘到了极致。LPMP框架本身也可以作为一个独立的软件扩展约700行代码集成到Keystone等现有TEE中帮助它们突破飞地数量的限制。我们已经将LPMP的实现提交给了Keystone项目。我个人在实际开发和测试中的体会是软件定义的灵活性是RISC-V生态最大的魅力所在。COFFER的成功证明了通过精巧的软件架构我们完全可以在标准、通用的硬件上构建出强大且安全的基础设施。当然这并非终点。EModule的生态建设、对更多外设和安全扩展如IOPMP的支持、以及更强大的形式化验证都是COFFER未来可以深入探索的方向。对于任何希望在RISC-V上实践机密计算的开发者来说理解并借鉴COFFER这套“用软件弥补硬件限制”的思想或许比单纯使用COFFER本身更有价值。