Files

7.2 KiB
Raw Permalink Blame History

认证 RTOS 的隔离特性:SAFERTOS ESM / CMSIS-RTX5 安全特性

这一族 RTOS 在"功能核 + 认证"之上,额外加了**访问控制与诊断特性**,会产生两类误判:
同一 VA:Task A 能访问、Task B 不能
  → 可能只是 per-task 区域/保护域策略

某 API 调用失败 / 某线程不运行
  → 可能只是调用方安全等级不够

先在"谁能访问什么"这一层解释,再去怀疑对象损坏或逻辑错误。 </CORE RULE>

一、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