MPU安全性的分区和基本操作

描述

这是四部分系列文章的第二部分,介绍了独特的产品 MPU-Plus 和使用 Cortex-M 内存保护单元 (MPU) 来提高微控制器单元 (MCU) 安全性的方法。第 1部分介绍了一些介绍性概念:MMU 与 MPU、对安全性、保护目标、MPU-Plus 快照、Cortex-v7M 和 v8M 以及 MPU 操作的日益增长的需求。

MPU

图 1:分区

图 1 说明了我们为安全而努力实现的软件结构。在此图中,椭圆表示隔离的分区。粗线以上的分区以umode(非特权或用户模式)运行,粗线以下的分区以pmode(特权或保护模式)运行。粗线表示非特权操作和特权操作之间的界限。这种隔离由 Cortex-M 处理器架构强制执行。它是安全可靠的,除非我们做错了什么。

粗线上方是两个应用程序分区和一个中间件分区。当然,实际系统可能有更多的 umode 分区。这里的目标是实现一个 umode 分区与另一个分区的完全隔离。然后穿透一个分区不会使黑客能够穿透其他分区,因此可以控制违规行为。每个 umode 分区是一组一个或多个 utask。utask 构成了与其他分区中的任务隔离的基础,但不是与自己分区中的任务隔离的基础。umode 分区具有强隔离能力。因此,应尽可能将易受攻击的代码(如驱动程序、中间件和应用程序代码)放入 umode 分区。

粗线以下是安全启动、pcode、smx、SMX RTOS 内核和安全分区。这些由 pcode 组成。当然,实际系统可能有更多的 pmode 分区。目标是也将 pmode 分区彼此隔离。但是,这种隔离不如 umode 隔离那么强,后面会讨论。

安全启动

当系统启动或重新启动时,处理器以 pmode 启动,并且位于 Secure Boot 分区中。

MPU

图 2:安全启动

如图 2 所示,安全启动软件进行基本的硬件和软件初始化,加载代码,如有必要,创建启动操作所需的任务,然后启动调度程序。在启动调度程序之前,没有任何任务正在运行。启动调度器后,系统以任务模式运行,第一个以最高优先级调度的任务正在运行。其他分区进行自己的初始化。出于结构和安全原因,最好将安全引导分区中的代码最小化。在图 2 中,安全引导加载程序以黄色显示。这些可以从许多来源获得,并且超出了本文的范围。绿色显示的代码是系统和应用程序代码。

smx

SMX RTOS由smx 内核和中间件组成。SMX 被拆分,因此 smx 内核在 pmode 下运行,而 SMX 中间件在 umode 下运行。MPU-Plus 与 SMX、eheap ™ 和某些其他产品捆绑在一起时,构成SecureSMX ™。

smx分区包含smx内核和SVC Handler、PendSV Handler等相关软件。它以 pmode 运行,以便将其与可能已损坏的 umode 分区强烈隔离。MPU-Plus 扩展了 smx 以添加安全功能。有关这些的更多信息,请参阅:

smx 用户指南, Ralph Moore,Micro Digital, Inc.

smx 参考手册, Ralph Moore, Micro Digital, Inc.

我们发现,除了添加 MPU-Plus 之外,还需要对 smx 本身进行大量修改,尽管 smx 已作为嵌入式内核使用了 30 年!中间件产品也需要进行重大修改。安全似乎正在给嵌入式系统软件带来范式转变。

安全

最后是安全分区和保险库。Vault 是我们存储珠宝(加密密钥、密码、验证码、证书等)和现金(私人数据)的地方。如果 pmode 被破坏,避难所就会弹开,王国就会消失。因此,保护 Vault 至关重要,只有包含加密、身份验证和其他安全任务的安全分区才能访问 Vault。

加密和身份验证软件已从 SMX 中间件产品中移出到安全分区中。因此,只有安全软件才能访问 Vault。

代码

pcode 分区包含中断服务例程 (ISR)、链接服务例程 (LSR) 和其他必须处于 pmode 的代码。这是系统、中间件和应用程序代码的混合体。在实际系统中,这可能会分为系统分区和应用程序分区。它可能包含一些 ptask 以及 ISR 和 LSR。同样, smx 错误

Manager、smx_EM() 和错误恢复代码不是任务。因此,此分区中的大部分代码都在当前任务的上下文中运行。

处理中断会带来特殊的安全问题,这将在第 3 部分中讨论。

任务

utasks 可以提供高级别的隔离。这主要是因为他们无法访问 MPU。MPU 加载了允许任务访问的区域,包括访问权限(例如只读、从不执行等),但任务无法更改它们。如果背景区域打开,它在 umode 中无效。然而,一切都不是桃子和奶油——还有堆问题和函数调用问题,这些将在后面讨论。

任务

与 utasks 相比,ptasks 提供的隔离性较弱。这是因为一旦 ptask 被破坏,恶意软件只需一个步骤即可关闭 MPU 或打开其背景区域 (BR)。然后 MPU 区域没有效果。MPU 在 pmode 中毫无防备,而在 umode 中则坚不可摧。

但是,ptasks 可以通过捕获许多黑客技术(例如堆栈或缓冲区溢出、尝试从堆栈或缓冲区执行等)并在黑客获得实际控制权之前触发 MMF 来帮助挫败攻击者。然后,MMF 处理程序可以删除渗透的任务并重新创建它,希望系统操作中只有一个小问题。它还可以报告事件,这有助于发现和减少代码漏洞。

ptasks 对于捕获编程错误也很有用,并且可以成为通向 utasks 的有用步骤。

基本操作

MPU 控制

内存保护阵列 (MPA) 是一组要在任务切换上加载到 MPU 中的区域;每个任务都有一个 MPA。任务的索引用于在内存保护表中查找其 MPA,mpt[indexsmx_TaskCreate() 将当前(父)任务的 MPA 复制到正在创建的任务。如果 ct 是 ptask,它可以通过以下方式更改任务的 MPA:

smx_TaskSet(任务,SMX_ST_MPA,tp);

其中 tp 指向任务的 MPA 模板。

前述如图3所示。在该图中,MPA0、1和2共享模板mpa_tmplta。因此,三个对应的任务共享相同的区域。因此,它们很可能在同一个分区中。请注意,MPA3 使用模板 mpa_tmpltb。因此,相应的任务很可能在一个单独的区域中。第五个任务尚未创建,其 MPA 也未加载。

MPU

图 3:模板、MPA 和 TCB

MPA 中的插槽与 MPU 中的动态插槽一样多。大多数插槽都充满了链接器命令文件中定义的静态区域(一个乏味的过程)。但是,某些插槽具有指向在运行时动态创建的区域数组的指针。这些将在第 4 部分中详细讨论。具有最高优先级的顶部 MPU 正在使用的插槽是为任务堆栈区域保留的。任务栈是在创建任务时从主堆动态创建的,或者在调度任务时从栈池中获取。在任务运行时,对 MPU 的任何更新也会对其 MPA 进行,因此在任务切换期间无需保存 MPU 内容。

创建静态区域是一个费力的过程。例如,对于代码区域,有必要识别特定分区或特定任务所需的所有功能,包括子例程。Pragma 被插入到代码中,以将所有这些放入一个唯一的代码部分,例如:

#pragma default_function_attributes = @“.ut1a_text”

无效 tm05_ut1a(无效)

{

smx_SemSignal(sbr1);

}

#pragma default_function_attributes =

然后在链接器命令文件中定义一个块来保存此部分和相关部分,例如:

定义块 ut1a_code,大小 = 1024,对齐 = 1024 {ro section .ut1a_text,ro section .ut1a_rodata};

区域在链接器命令文件中定义,并在其中放置块,例如:

定义区域 ROM = mem:[从 0x00200000 到 0x002FFFFF];

放入 ROM {block t2a_code, ro section .tmplt, block ut1a_code, block ut2a_code, block ut2b_code};

回到代码中,定义了 MPA 中的一个槽:

#pragma section = “ut1a_code”

MPA mpa_tmplt_ut1a =

{

。..

RGN(3 | RA(“ut1a_code”) | V, 代码 | RSI(“ut1a_code”) | EN, “ut1a_code”),

。..

};

所有这些都是针对一个模板中的一个 MPU 区域完成的——显然是一个费力的过程。上面显示的模板宏(例如 RGN())可以减少工作并有助于减少错误。因为有些语句在代码中,有些在链接器命令文件中,所以该过程容易出错。不仅如此,很容易为代码区域遗漏一个晦涩的子程序或为数据区域遗漏变量,从而在调试期间导致烦人的 MMF(在调试的早期阶段关闭 MMF 的一个很好的理由)。

系统调用

ptasks 可以直接调用所有的 smx 和 system 函数,但是 utasks 不能直接调用它们,因为它们必须在 pmode 中执行。而是使用 SVC N 指令。对于 umode 代码,将包含 smx 和系统原型函数的 xapi.h 头文件替换为 xapiu.h 头文件。后者将 smx_ 调用映射到 smxu_ 调用,这些调用是调用 SVC N 的 shell 函数,其中 N 是系统调用 ID。但是,限制通话,对于 umode 是禁止的,会产生 Privilege Violation 错误。受限调用只能通过 pcode 进行。例如,utasks 不需要 smx_HeapInit(),如果从恶意软件调用,可能会导致系统损坏,因此没有 smxu_HeapInit()。定义了一组合理的受限调用。然而,该集合可以根据需要针对特定应用进行扩展或收缩。

MPU

图 4:系统调用

图 4 说明了 utasks 和 ptasks 的系统调用机制。SVC Handler 使用 N 作为索引,通过 SSR 跳转表到 smx 系统服务例程(SSR)。SSR 在 pmode 中执行,然后将结果返回给 SVC Handler。SVC 处理程序将此结果返回给 smxu shell 函数,后者将其返回给 utask。所有这些细节对调用者都是隐藏的,看起来就像是进行了正常的函数调用。umode 中不允许的系统调用会导致分支到特权冲突错误管理器 (PVEM),而后者又会调用 smx 错误管理器 (EM)。

请注意,来自 ptask 的 smx 调用直接转到 SSR,并且没有不允许的服务调用。

本系列的下一部分将讨论分区问题,包括堆使用、函数调用 API、中断、父子任务和任务本地存储。

审核编辑:郭婷

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分