ARM中的MPU (M0+/M3/M4/M7/等)经常被宣传为允许设置防止取消引用空指针的保护。但如何在实践中做到这一点呢?(一些在线讨论( 比如在Zephyr项目中 )表明,这个问题并不是微不足道的。)
我正在寻找最简单的MPU代码,它在裸金属臂的Cortex-M上以“特权模式”运行。请注意,“防止取消引用空指针”对我来说意味着对读写的保护。而且,它不仅涉及地址0x0,而且还与地址之间的小偏移量有关。例如,通过空指针访问struct成员也会导致MPU异常:
struct foo {
. . .
uint8_t x;
};
. . .
uint8_t x = (*(struct foo volatile *)NULL)->x; // should fail!发布于 2022-12-04 15:52:27
经过一些实验,我已经提出了MPU设置,似乎适用于大多数ARM Cortex-M MCU。下面是代码(使用CMSIS):
/* Configure the MPU to prevent NULL-pointer dereferencing ... */
MPU->RBAR = 0x0U /* base address (NULL) */
| MPU_RBAR_VALID_Msk /* valid region */
| (MPU_RBAR_REGION_Msk & 7U); /* region #7 */
MPU->RASR = (7U << MPU_RASR_SIZE_Pos) /* 2^(7+1) region, see NOTE0 */
| (0x0U << MPU_RASR_AP_Pos) /* no-access region */
| MPU_RASR_ENABLE_Msk; /* region enable */
MPU->CTRL = MPU_CTRL_PRIVDEFENA_Msk /* enable background region */
| MPU_CTRL_ENABLE_Msk; /* enable the MPU */
__ISB();
__DSB();此代码在地址0x0 (任何其他MPU区域也可以)周围设置一个不访问MPU区域#7。这甚至对MCU也适用,因为Vector也驻留在地址0x0。显然,MPU不通过LDR/STR以外的指令检查对该区域的访问,例如在Cortex-M异常项期间读取向量地址。
但是,如果向量表驻留在0,则非访问区域的大小不能包含任何数据,这些数据将由CPU合法地用LDR指令读取。这意味着无访问区域的大小应该是向量表的大小。在上面的代码中,大小被设置为2^(7+1)==256字节,即使对于相对较小的向量表也应该是很好的。
上面的代码也适用于自动重新定位向量表(如STM32 )的MCU。对于这些MCU,非访问区域的大小可以一直增加到重新定位的向量表,就像STM32中的0x0800'0000一样。(可以将大小设置为2^(26+1)=0x0800‘0000)。
对空指针去引用的保护是提高系统鲁棒性甚至防止恶意攻击的重要工具。我希望这个答案能帮助嵌入式开发人员。
https://stackoverflow.com/questions/74549991
复制相似问题