当前位置:首页 > 嵌入式 > 嵌入式分享
[导读]打开内存保护单元后,程序仍可能越界写坏相邻对象。嵌入式隔离是否成立,既取决于硬件保护区与实际对象边界是否吻合,也取决于进入特权代码后,调用者是否被允许借用更大的访问权限。

打开内存保护单元后,程序仍可能越界写坏相邻对象。嵌入式隔离是否成立,既取决于硬件保护区与实际对象边界是否吻合,也取决于进入特权代码后,调用者是否被允许借用更大的访问权限。

以采用传统区域模型的ARMv7-M处理器为例,保护区大小受二次幂和基地址对齐要求约束。若一个任务只需要六千字节空间,直接覆盖它的合法区域可能还会包含额外地址。越界写若仍落在允许写入的区域内,硬件不会因为它越过了某个C数组末端就报错。保护单元检查的是地址访问属性,并不了解对象长度。因此链接脚本必须参与隔离设计,把不同信任主体的数据放进能够独立设权的地址范围,而不是等程序链接完成后再随意套上区域。

部分区域可借助子区禁用缩小有效覆盖,但这种能力有最小区域尺寸等适用条件,不能当作任意字节粒度的裁剪工具。多个区域重叠时,还应核对目标内核规定的优先关系,避免较高优先区域重新开放本想禁止的地址。代码区可读且可执行,数据区通常应设置禁止执行;这两种属性不能只用一个读写开关代替。对于允许特权背景映射的配置,特权代码可能访问未显式列出的地址,而非特权代码的结果不同,测试必须区分两种执行权限。

布局验收应从最终链接映射文件提取区域起止位置,再与保护寄存器的实际值比较。测试地址至少覆盖合法区首尾、相邻区域和对齐产生的空隙,并分别执行读、写和取指验证。只测试一个明显非法的远端地址,会漏掉最常见的边界泄漏。还应明确保护能力针对哪些总线主设备:处理器自身的保护单元通常不能直接约束独立外设主设备的访问。这里讨论的区域规则也不能照搬到采用基址与限址模型的其他架构版本。

硬件布局正确之后,第二个缺口往往出现在特权服务入口。非特权任务把缓冲指针交给系统服务,服务代码随后用自身权限复制数据;如果入口只检查服务编号,就可能替调用者写入本来禁止访问的内核对象。越权并非调用者直接突破了保护单元,而是高权限代理接受了错误的工作请求。服务应依据调用任务的身份,验证完整读写区间及操作方向,读缓冲合法不等于同一地址也允许写入。

区间验证不能简单计算起始地址加长度后再比较上界,因为整数回绕可能让超长请求伪装成很短的地址范围。应先确认起点处于允许范围,再用允许上界减去起点,与长度比较;零长度和末端地址的定义也要一致。跨越两个不同权限区域的请求,即使首尾地址单独看似合法,中间也未必连续可访问。若请求中还含有指向其他对象的嵌套指针,检查外层结构并不能自动证明内层指针合法,服务接口最好减少这种难以审查的间接层次。

当调用者可能并发修改请求内容时,校验后重新读取字段还会形成检查与使用之间的差异。可在边界处复制必要元数据并使用同一快照完成后续处理;对于可能变化的数据区,则需另行定义稳定性契约。嵌入式服务也不应因为进入了特权态就无限信任外设寄存器编号或长度字段。验证应使用越界指针、溢出长度和权限相反的请求逐一注入,观察服务是否在真正访问目标之前拒绝请求,而不是等异常发生后再补救。

内存保护的有效边界来自布局和服务接口的共同约束。区域应贴合信任边界,特权代理应重新验证调用意图;只有两者同时成立,开启保护单元才真正转化为可验证的隔离。

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除( 邮箱:macysun@21ic.com )。
关闭