ARM MTE简介

news/2024/12/28 23:24:14/

一、MTE 介绍(Memory_Tagging_Extension

MTE 是ARM新架构(ARM V8.5 引入)的一个特性,它通过给分配的内存打标记(tag),追踪最常见的非法内存操作。如果密钥的值和锁的值一样,表示访问成功,否则会报告一个错误。

通常内存安全相关的bug,特别是在Android codebase 的native 代码层是常见的异常类型。按照google 的异常统计,超过50%的安全漏洞是内存引起的(如下图所示):

3c86b50cfd6e9cdba5a46970596a8340.png

为了解决和发现内存bug,Android 引入了ASan/HWASan, KASAN, GWP-ASan,KFENCE和MTE内存检测工具,其中MTE是Android 12开始加入支持。

MTE 原理和HWASan类似,下面对比分析下:

1、检测部分HWASan通过编译方式,在内存访问前插入检测代码;tag(key)生成通过软件随机方式生成;tag(lock)存储在shadow memory中(shadow 内存通常提前设定);

2、MTE 检测和tag生成存储有了硬件层面的支持,MTE通过指令生成tag(key);检测也是通过指令完成;tag (lock)存储的部分存放在物理内存特定区域(无需软件参与显示分配或者设置);

重点差异对比表

895a40f3b1d2af806e3fa7f90ccec728.png

以下是三个工具的开销对比,可以直观感受到MTE的提升。

64c8f8a2e8c60d0d31a202876b71f58e.png

二、MTE 原理 

MTE 在实现时就利用的Armv8-A 的TBI(Top Byte Ignore)特性,使用指针的高 4 bits 存储 tag(即 key),使用专用的内存(tagging memory)存储 tag(即 lock)。下图是MTE 工作的原理图

6ccfd8113af1c11aacaea8de24ee4eba.png

MTE 引入的新指令操作标记内存:

e9d5f3ee23dd158860c5bf0b5f3f3a45.png

大部分指令完成带tag的加减等数据操作,核心指令IRG,STG ,LDG完成关键的tag生成,存储和读取。

   打开MTE时,正确的内存访问需要指针的 key 值与该内存的 lock 值保持一致。当 lock 和 key 不匹配时,可选择触发一个同步或异步异常。下面来介绍这两种模式差别:

1、同步模式(Sync

Sync 模式是精确的错误检测工具,对性能有一定损耗,在内存访问(ldr/str)时,同步检测tag是否匹配,如果不匹配异常触发,进程会收到SIGSEGV (code SEGV_MTESERR)信号同时立即结束;

其中:siginfo.si_code = SEGV_MTESERR(SERR中的S表示synchronous),siginfo.si_addr = <fault-address>)

当工作在sync 模式时,android 分配器还会记录分配释放的stack trace,出现问题时还能提供更详细的memory异常分类,如 user-after-free,buffer-overflow 等;

 2、异步模式(ASync

更轻量级的内存检测,Android用来发现内存踩踏bug;在内存访问时,异步检测tag是否匹配,如果不匹配则更新TFSR_EL1寄存器中的TF0 bit。当下一次用户/内核切换时,系统会去检测TFSR_EL1寄存器,然后产生SIGSEGV信号(code = SEGV_MTEAERR);此时的 siginfo.si_code = SEGV_MTEAERR (AERR中的A表示asynchronous),siginfo.si_addr = 0 ,表明系统并不知道是哪一条具体的指令导致的问题。

三、MTE Android S平台使用方法

MTE 检测分为上层native 和kernel 部分,先来看上层native 使能部分

1、使能所有的native code,通过环境变量控制

0f8f932402f4babeca951b5261c54e17.png

2、增加指定路径的project  (BoardConfig.mk中)

PRODUCT_MEMTAG_HEAP_SYNC_INCLUDE_PATHSPRODUCT_MEMTAG_HEAP_ASYNC_INCLUDE_PATHS

3、通过Android bp setting打开

78d7d6bceb30fab64dc59b2d7296e97b.png

4、在版本中还可以通过属性控制:

arm64.memtag.process. <basename>= off| async | sync

比如使能system_server进程mte: arm64.memtag.process.system_server

5、NDK API 控制使能方法

mallopt (NONE or TBI or ASYNC or SYNC)

6、注意默认版本中MTE是关闭的,需要检查对应的rc文件确保MTE打开

[device/XXX/init.target.rc]

on early-init

# export MEMTAG_OPTIONS off

修改成sync 或者async

kernel 侧MTE 使能

1、确认平台本身MTE 已经支持

2、MTE kernel 相关配置

CONFIG_ARM64_MTE       //  using MTE in the userspace

CONFIG_KASAN and CONFIG_KASAN_HW_TAGS  //using MTE in the kernel

3、通过cmdline 控kasan 开关:

e64eb8cb20a02abd694108e4b0fb1a96.png

四、MTEKERNEL Android S中的实现

1.MTE打开方法
 

SCTLR_EL1寄存器用来打开关闭MTE,在TCF0设置MTE模式

227da393b8875c7988859b994d9434d4.png

033828432ae27bb91b67e7649422978a.png

Android 中MTE 打开的流程

f7e7d269ce34315d4b36a10903bbe52a.png

上层scudo malloc分配时流程

7775cef906aba2ad4e31d7ff0d5d2696.png

 

2.MTE工作流程

Tag 检测异常触发流程,data abort时,arm 通过ESR_EL1(Exception SyndromeRegister) 寄存

器ISS部分(低22位)来记录:

162f4fbdd1c6da8c0cd0bb1d086d8371.png

DFSC, bits[5:0]

Data Fault Status Code.

0b010001 WhenFEAT_MTE2 is implemented Synchronous TagCheck Fault.

DFSC为17时表示触发了MTE tag 检查不匹配;

SYNC模式工作流程

5bdd5c767a45a24aa700b8e02ce6defd.png

ASYNC模式工作流程

dcb8c3a70f4e921507fa0a3893618a0c.png

从sync 和async 实现部分看,sync 在触发异常时立刻发送SEGV_MTESERR给进程,

而async在进程系统调用或其他user/kernel切换时,主动检查mte 标记位然后发送

SEGV_MTEAERR。

 

3. MTE检测框图

MTE在tag mismatch时触发异常,消息回传用户程序后,抓取当前调用栈和访问内存及

附近的tag,通过指针tag和内存tag来判断是哪种内存异常。

e0d564ff198aad39233d51490dd90139.png

73b9f2774e71a4455cefb60fe79bbc28.png

MTE Kernel 中的实现如下,关键宏定义:上面的定义可以明显看到MTE Tag size为 4 ,标记16个字节,tag存放在指针偏移56位;
当前kernel中TAG的值范围0xF0~0xFD, 0xFE用来标记未分配或已经释放的内存。上图是kernel 触发tag mismatch的原理图,需要注意的是MTE 的tag lock储存读取也是硬

件实现的。

五、MTE 检测案例

1.userspace踩踏例子

Example1:underflow

std::unique_ptr<int[]> p =std::make_unique<int[]>(4);

 volatile int oob = p[-1];

(void)oob;

执行代码后触发tomstone

6d2354eca2402851ea07dae1d28e4560.png

8f2bc3aabff4724c469f7a9d14bebf20.png

Example2: overflow

std::unique_ptr<int[]> p =std::make_unique<int[]>(4);

 volatile int oob = p[5];

 (void)oob;

执行代码后触发tomstone

606df6c2447cd9c6cb5088cb58f97906.png

b3354e0dad2ad19ada4c107d7aeb0cd9.png

Example3: useafter free

int * p = new int[16];

delete[] p;

p[3] = 9;

b9e0c2cd588e6d67f5867c0c2e1f759f.png

cf6d3167bf2dca5130ffad6b444b7ed1.png

上面的例子中可以看到MTE 能准确的检测到常见的uaf, unferflow, overflow 异常;

整体异常

2. Kernel hwkasan例子

Example : kmalloc overflow

0f250b77eea281b7a4e0cc134918627a.png

582e8bac92c3303a18e6949d4bd2614a.png

00b0324daafc48ae420d260a79c58dfc.png

测试代码sample:

ptr = kmalloc(234, GFP_KERNEL);

ptr[256] = 0;

 从上面的log看kernel mte 检测过程:

分配的指针:fdffff8878a8f500

越界的地方:fdffff8878a8f601    

Pointer tag : [fd],  memory tag: [f4].

ptr指针为0xfdffff8878a8f500,标记的可访问内存是0xffffff8878a8f500 ~ 0xffffff8878a8f5EA, mte是

标记是16字节对齐的,所以实际是标记连续234/16 =14.6= 15个(向上取整)。Ptr

指针只能访问tag为fd标记的区域,实际ptr 访问到了tag为f4标记的内存区域,通过

tag计算我们也能推导出内存访问越界点;

1ec1869f990d3985bc3f36ca3296bb97.png

Under flow 流程类似overflow,tag 打印会在ptr能访问内存的前面;

User after free 的话mem的tag会变成fe(用来表示已经释放或无法访问的内存);

六、总结

当前MTE 在android中需要绑定scudo 分配器使用,相信随着更多平台支撑mte后,传统的

分配器也会引入mte。

MTE 通过4 bit Tag Size 来做key lock 匹配,存在连续两个内存分配相同的tag key情况,

也就是1/16 概率出现无法检测的情况(kernel 中实际只有14个tag可用,实际概率更高)

;如果能保证相邻内存tag 不同的话,miss的概率会大大降低。

MTE 无法检测 16 byte内的内存越界访问;分配大小非16字节对齐,向后踩踏<16字节

对齐的踩踏无法被MTE检测到,比如:

ptr = kmalloc(12, GFP_KERNEL);

ptr[12] = 0;

….

ptr[15] = 0;

ptr[16] = 0; //这里才能触发检测

MTE不依赖编译,低性能损耗,可以考虑将MTE在用户/试用用户侧选择性的打开,发

现内部难以发现的内存类问题。

参考:

https://www.kernel.org/doc/html/latest/arm64/memory-tagging-exte

nsion.html

https://community.arm.com/arm-community-blogs/b/architectures-an

d-processors-blog/posts/enhanced-security-through-mte?_ga=2.4176

8226.1458341132.1636618591-1030760285.1629468403
https://juejin.cn/post/7013595058125406238

https://www.reexpound.com/2021/05/21/%E6%B7%B1%E5%85%A5%E7%90%86

%E8%A7%A3arm%E5%86%85%E5%AD%98%EF%BC%9A%E4%B8%80-memory-tagging-

extension-mte/

https://aijishu.com/a/1060000000006711

https://developer.arm.com/-/media/Arm%20Developer%20Community/PD

F/Arm_Memory_Tagging_Extension_Whitepaper.pdf

74a886a5bcbf2a7271f5ac245854d86e.gif

长按关注

内核工匠微信

Linux 内核黑科技 | 技术文章 | 精选教程


http://www.ppmy.cn/news/207090.html

相关文章

melt函数的参数

melt函数的参数 melt 是溶解/分解的意思&#xff0c; 即拆分数据&#xff1b;melt即是类函数也是实例函数&#xff0c;也就是说既可以用pd.melt(), 也可使用dataframe.melt() 参数类型说明framedataframe必要参数&#xff0c;被 melt 的数据集名称在 pd.melt() 中使用&#x…

MeteoInfo

1.格点数据有时需要插值到另一个范围和分辨率的网格上&#xff0c;可以用 linint2 函数来插值。 http://bbs.06climate.com/forum.php?modviewthread&tid91352 2.格点插值到站点 格点数据插值到站点主要有两种方法&#xff1a;双线性插值和最近距离&#xff0c;算法都很简…

May 7

May 7 相信我,你也可以变成光 字符串函数 字符串的拼接 str1"美丽的" str2"大好河山" resstr1str2str的重复 str"重要的事情说三遍" resstr1 * 3str的跨行拼接 str1"adfaga "\ "asdfaf af" print(str)str的索引 str&…

win7 安装Memcache

win7安装Memcache 测试环境&#xff1a;XAMPP 1.7.0 win7 安装之前确定你是不是以Administrator身份进入系统的,如果不是&#xff0c;在执行memcached.exe -d install命令的时候,会出现install fail or service already install 的问题&#xff1b;Win7下Administrator默认是没…

Emmet

Emmet ###Emmet (前身为 Zen Coding) 是一个能大幅度提高前端开发效率的一个工具Emmet把片段这个概念提高到了一个新的层次&#xff1a;你可以设置CSS形式的能够动态被解析的表达式&#xff0c;然后根据你所输入的缩写来得到相应的内容。Emmet是很成熟的并且非常适用于编写HTM…

7.HMTL7

1. CSS : cascading style sheet(层叠 样式 表) HTML标签&#xff0c;指定元素&#xff0c; CSS让标签更美&#xff0c; javascript: 可动能写在哪&#xff1f;&#xff1f; 外部引入 css文件 用 link标签内部样式&#xff1a; 用style标签内联样式&#xff1a; 标签的style属…

Cortex-A7 MPCore 简介与处理器运行模型

Cortex-A7 MPcore 处理器支持 1~4 核&#xff0c;通常是和 Cortex-A15 组成 big.LITTLE 架构的&#xff0c;Cortex-A15 作为大核负责高性能运算&#xff0c;比如玩游戏啥的&#xff0c;Cortex-A7 负责普通应用&#xff0c;因为 Cortex-A7 省电。Cortex-A7 本身性能也不弱&#…

metaRTC

metaRTC 是一个开源的 WebRTC 服务器。WebRTC (Web Real-Time Communication) 是一项技术标准&#xff0c;它使浏览器和移动应用程序能够进行实时语音、视频和数据通信。metaRTC 可以让开发人员轻松地构建基于浏览器的通信应用程序&#xff0c;无需安装任何插件或软件。