Memory Tagging Extension (MTE)
最后更新于
最后更新于
内存标记扩展(MTE)旨在通过检测和防止与内存相关的错误(如缓冲区溢出和使用已释放的漏洞)来增强软件的可靠性和安全性。作为ARM架构的一部分,MTE提供了一种机制,可以为每个内存分配附加一个小标记,并为引用该内存的每个指针附加一个相应的标记。这种方法允许在运行时检测非法内存访问,显著降低利用此类漏洞执行任意代码的风险。
MTE通过将内存划分为小的固定大小块,每个块分配一个标记来运作。
当创建指向该内存的指针时,该指针会获得相同的标记。该标记存储在内存指针的未使用位中,有效地将指针与其对应的内存块关联起来。
当程序通过指针访问内存时,MTE硬件会检查指针的标记是否与内存块的标记匹配。如果标记不匹配,则表示存在非法内存访问。
指针内的标记存储在顶部字节的4位中:
因此,这允许最多16个不同的标记值。
每16B的物理内存对应一个内存标记。
内存标记存储在一个专用的RAM区域中(无法正常访问)。每16B内存标签占用RAM的3%。
ARM引入以下指令来操作专用RAM内存中的这些标记:
CPU 在执行指令期间检查标签,如果不匹配,会引发异常。 这是最慢且最安全的方式。
CPU 异步检查标签,当发现不匹配时,会在系统寄存器中设置异常位。比起同步方式更快,但无法指出导致不匹配的确切指令,并且不会立即引发异常,给攻击者一些时间来完成攻击。
???
称为基于硬件标签的 KASAN、基于 MTE 的 KASAN 或内核 MTE。
内核分配器(如 kmalloc
)将调用此模块,该模块将准备要使用的标签(随机)附加到分配的内核空间和返回的指针上。
请注意,它将仅标记足够的内存粒度(每个 16B)以满足请求的大小。因此,如果请求的大小为 35,给出了一个 60B 的 slab,它将使用此标签标记前 16*3 = 48B,其余部分将用所谓的**无效标签(0xE)**标记。
标签0xF是匹配所有指针。具有此指针的内存允许使用任何标签访问其内存(无不匹配)。如果在受攻击的内存中使用此标签,可能会阻止 MET 检测到攻击。
因此,只有14个值可用于生成标签,因为 0xE 和 0xF 已保留,导致标签重用的概率为 1/17 -> 约7%。
如果内核访问无效标签粒度,将检测到不匹配。如果访问另一个内存位置,如果内存具有不同的标签(或无效标签),将检测到不匹配。如果攻击者幸运地访问具有相同标签的内存,则不会检测到。概率约为 7%。
另一个 bug 出现在分配内存的最后一个粒度中。如果应用程序请求了 35B,它将获得从 32 到 48 的粒度。因此,从 36 到 47 的字节使用相同标签,但未被请求。如果攻击者访问这些额外字节,不会被检测到。
当执行**kfree()
时,内存将重新标记为无效内存标签,因此在释放后再次访问内存时,将检测到不匹配**。
然而,在释放后再次使用相同标记重新分配相同的块时,攻击者将能够使用此访问,而这不会被检测到(约 7% 的机会)。
此外,只有**slab
和 page_alloc
** 使用带标签的内存,但在将来,vmalloc
、stack
和 globals
也将使用(在视频时,这些仍然可能被滥用)。
当检测到不匹配时,内核将恐慌以防止进一步利用和重试利用(MTE 不会产生误报)。