# 认证 RTOS 的隔离特性:SAFERTOS ESM / CMSIS-RTX5 安全特性 这一族 RTOS 在"功能核 + 认证"之上,额外加了**访问控制与诊断特性**,会产生两类误判: ``` 同一 VA:Task A 能访问、Task B 不能 → 可能只是 per-task 区域/保护域策略 某 API 调用失败 / 某线程不运行 → 可能只是调用方安全等级不够 ``` **先在"谁能访问什么"这一层解释,再去怀疑对象损坏或逻辑错误。** ## 一、SAFERTOS + Enhanced Security Module(ESM) 基础 SAFERTOS 的空间隔离目标是**非故意的内存访问**(损坏/编程错误);**ESM 把它加固到抵御"蓄意的"越权访问**。 | 机制 | 作用 | |---|---| | **访问控制策略(ACP)** | **限制每个任务可访问的 API 数量**(例如禁止某任务改自己的特权级、改访问权限、创建新资源);任务越受限,被攻陷后的攻击面越小 | | **对象访问控制策略(OACP)** | **限制每个任务可访问的 RTOS 对象**(队列、信号量、事件组等),把任务约束在初始化时分配给它的对象上 | | **间接对象 ID** | 把传统句柄(**本质是 C 指针**)换成**经交叉引用表解析的 Object ID**,使任务无法从句柄推出对象/TCB 的内存位置 | | **per-task MPU/MMU 区域** | 每任务 3 或 5 个可配置区域(随处理器变体);**每次上下文切换都会重新编程**;默认非特权任务只能访问自己的栈 | - 区域要求:**大小必须是 32 字节的倍数,基址必须 32 字节对齐** - 可定义对所有任务可见的全局区域;**绝不应把另一个任务的栈分配给某任务** - 区域在任务创建时配置(可读/可写/可执行、用户或特权),**运行期可以重新配置** - ESM 还包括:数据混淆、安全的用户/内核空间分离层、任务上下文数据隔离(上下文存在 TCB 而不是栈上)、渗透检测监控 **RE 判据**: ``` 句柄不是内存指针(间接对象 ID) → 别把句柄当 TCB/对象地址,也别指望从它推出结构布局 ``` ## 二、CMSIS-RTX5 的安全特性 在 `OS_SAFETY_FEATURES` 等开关下提供: | 特性 | 含义 | |---|---| | **Safety Classes** | 低安全等级的线程**不能修改**高等级线程;提供线程类的查询/挂起/恢复等接口。**动机**:RTOS 对象是经"以数字 ID 为参数、在 handler 模式执行"的系统调用访问的,**单靠 MPU 保护可以被"用别的对象 ID 调 API"绕过**——安全等级给对象访问加了访问控制 | | **MPU Protected Zones** | 空间隔离:一个 zone 是一组带访问权限的内存区/外设,分配给一个或多个线程;**zone ID 就是 MPU 表的行号**,上下文切换时内核比较 zone ID 并调用回调(用户实现,通常是把对应行载入 MPU);**内存违规触发 MemManage 异常**。注意:**中断处理程序绕过 MPU 保护**,因此必须以最高完整性等级验证 | | **Thread Watchdog** | 时间隔离:安全等级线程声明期望的周期/响应时间并"喂狗",未达标时由监督线程升级处理(重启线程/重启应用/受控关停/硬件复位) | | **对象指针检查** | 检查对象指针的**对齐与内存区域** | | **SVC 函数指针检查** | 检查 SVC 函数指针的对齐与内存区域;**要求链接器划出专门的执行区**容纳 SVC veneer 输入段 | **ISR FIFO 队列(延迟处理)**: - **在 ISR 中调用部分 RTX API 不会立即完成**——请求先进入 **ISR FIFO 队列**,等 ISR 结束后由调度器处理 - 所以: ``` IRQ 中调用 osXxx() → 对象的实际状态在 IRQ 退出之后才变化 → 完全正常 ``` - **队列太小会产生 ISR 队列溢出错误**(专门的错误码),**此时系统状态已经不一致**;对策是**增大引起溢出的对象尺寸**,而不是怀疑队列对象损坏 - 另有"无效 SVC 函数"错误码(对象 ID 位置放的是函数) ## 三、权限模型与"拒绝"的语义 - SAFERTOS 的任务模型包含:自己的栈、**被许可的 MPU/MMU 区域**、**特权状态**、可访问的 RTOS 对象;**上下文切换时重新编程任务的存储区域** - 因此三类现象都应先在权限层解释: | 现象 | 优先解释 | |---|---| | 同一地址 Task A 能读、Task B fault | **per-task 区域配置**,不是内存损坏 | | 普通任务不能访问某地址、**ISR 却能** | 用户任务与特权内核/ISR 上下文的权限本就不同 | | API 调用附近出现特权转换 | 正常的 RTOS API 网关,**别当 ROP/trap 异常** | **ESM 下"拒绝"的来源**: - Task A 用某个句柄成功、Task B 用同一个句柄被拒 → 可能是**对象访问策略**拒绝,**不是句柄损坏** - 句柄看起来完全不像指针 → ESM 用**间接/混淆的对象 ID** 取代直接指向控制块的句柄;应恢复 **ID → 查表 → 对象** 的路径,而不是硬套 `句柄 = 内核指针` - **合法 API 返回拒绝** → 也可能是**访问控制策略**:当前任务根本没有调用该 API 的权限,而不是 API 实现坏了 ## 决策树 ``` 拿到 SAFERTOS / RTX5 一类认证 RTOS 目标 ├─ 同一地址的访问权限不一致 │ ├─ 查 per-task 区域配置(SAFERTOS)或 MPU zone 归属(RTX5) │ └─ 区域可能被运行期重新配置 ├─ 句柄看起来不像指针 / 指向奇怪的地方 │ └─ SAFERTOS ESM 用的是间接对象 ID + 交叉引用表 ├─ 某 API 调用被拒 │ ├─ 查调用方的访问控制策略(能否调这个 API)与对象访问策略(能否用这个对象) │ └─ RTX5 下查调用线程的安全等级 ├─ ISR 里调用的 API 没立即生效 │ ├─ 请求进了 ISR FIFO,ISR 退出后才处理 │ └─ 出现队列溢出错误 → 增大对象尺寸,且此时系统已不一致 └─ 出现内存管理异常 ├─ RTX5:MPU zone 违规 └─ 注意中断处理程序绕过 MPU 保护 ``` ## 工具与验证 - 访问控制:ACP/OACP 配置与运行期检查点(SAFERTOS);安全等级与对象属性(RTX5) - 空间:per-task 区域/zone 表、区域对齐与大小约束、运行期重配置调用 - 延迟处理:ISR FIFO 队列的容量与溢出错误码 - 验证:能同时说清「这次访问受哪条策略约束 + 区域/等级当前是什么 + 失败是策略拒绝还是真的坏了」 ## 该平台的坑(汇总) - **把 per-task 区域导致的访问失败当内存损坏**:权限差异可能完全合法 - **假设区域在任务生命周期内不变**:运行期可以重新配置 - **把 SAFERTOS 的句柄当内存指针**:ESM 下是经交叉引用表解析的间接对象 ID - **忘了区域的大小/对齐约束**:必须 32 字节倍数且基址 32 字节对齐 - **以为 MPU 保护覆盖中断处理程序**:中断绕过保护,必须单独验证 - **只在 MPU 层找越权防线**:RTX5 明确说单靠 MPU 可被"用别的对象 ID 调 API"绕过,需要安全等级 - **把 ISR 中调用的 API 未立即生效当 bug**:请求进 ISR FIFO,退出后才处理 - **把 ISR 队列溢出当队列对象损坏**:是容量不足,且此时系统状态已不一致 - **忽略 SVC 函数指针检查对链接布局的要求**:需要专门的执行区容纳 veneer