稳定性专项分享-KASan
简介 KASAN 是 Kernel Address Sanitizer 的缩写,它是一个动态检测内存错误的工具,主要功能是检查内存越界访问和使用已释放的内存等问题。KASAN 集成在 Linux 内核中,随 Linux 内核代码一起发布,并由内核社区维护和发展。 原理 KASAN的原理是利用额外的内存标记可用内存的状态。这部分额外的内存被称作shadow memory(影子区)。 KASAN将1/
简介
KASAN 是 Kernel Address Sanitizer 的缩写,它是一个动态检测内存错误的工具,主要功能是检查内存越界访问和使用已释放的内存等问题。KASAN 集成在 Linux 内核中,随 Linux 内核代码一起发布,并由内核社区维护和发展。
原理
KASAN的原理是利用额外的内存标记可用内存的状态。这部分额外的内存被称作shadow memory(影子区)。
KASAN将1/8的内存用作shadow memory。使用特殊的magic num填充shadow memory,在每一次load/store(load/store检查指令由编译器插入)内存的时候检测对应的shadow memory确定操作是否valid。连续8 bytes内存(8 bytes align)使用1 byte shadow memory标记。
如果8 bytes内存都可以访问,则shadow memory的值为0;如果连续N(1 =< N <= 7) bytes可以访问,则shadow memory的值为N;如果8 bytes内存访问都是invalid,则shadow memory的值为负数。
在代码运行时,每一次memory access都会检测对应的shawdow memory的值是否valid。这就需要编译器为我们做些工作。编译的时候,在每一次memory access前编译器会帮我们插入__asan_load##size()或者__asan_store##size()函数调用(size是访问内存字节的数量)。这也是要求更新版本gcc的原因,只有更新的版本才支持自动插入。
mov x0, #0x5678
movk x0, #0x1234, lsl #16
movk x0, #0x8000, lsl #32
movk x0, #0xffff, lsl #48
mov w1, #0x5
bl __asan_store1
strb w1, [x0]
上面一段汇编指令是往0xffff800012345678地址写5。在KASAN打开的情况下,编译器会帮我们自动插入bl __asan_store1指令,__asan_store1函数就是检测一个地址对应的shadow memory的值是否允许写1 byte。蓝色汇编指令就是真正的内存访问。因此KASAN可以在out-of-bounds的时候及时检测。__asan_load##size()和__asan_store##size()的代码在mm/kasan/kasan.c文件实现。
KASan相关配置
CONFIG_HAVE_ARCH_KASAN=y
CONFIG_HAVE_ARCH_KASAN_SW_TAGS=y
CONFIG_HAVE_ARCH_KASAN_HW_TAGS=y
CONFIG_HAVE_ARCH_KASAN_VMALLOC=y
CONFIG_CC_HAS_KASAN_GENERIC=y
CONFIG_CC_HAS_KASAN_SW_TAGS=y
CONFIG_CC_HAS_WORKING_NOSANITIZE_ADDRESS=y
CONFIG_KASAN=y
# CONFIG_KASAN_GENERIC is not set
# CONFIG_KASAN_SW_TAGS is not set
CONFIG_KASAN_HW_TAGS=y
# CONFIG_KASAN_TAGS_IDENTIFY is not set
CONFIG_KASAN_VMALLOC=y
单独关闭读或写检查
默认Kasan对读写都做检查,会显著降低系统的性能、增大image大小。
当确定发生的问题是内存写导致的错误时,可以关闭读检查,提高系统性能和运行速度,进而间接提高问题的复现度。
关闭读检查后,flash占用空间overhead也将大幅降低,对于穿戴设备,关闭读检查后,flash空间减小约1MB。
# 开启改选项将会关闭Kasan读检查
CONFIG_MM_KASAN_DISABLE_READS_CHECK=y
# 开启该选项将关闭Kasan写检查
CONFIG_MM_KASAN_DISABLE_WRITES_CHECK=y
影响及注意事项
使能KASAN后,会让程序明显变慢,如果这时使能了看门狗,很可能导致看门狗复位,实际使用中建议同时关闭看门狗。
使用ASAN会增加额外1/8的内存消耗用于shadow memory。
ASAN通过每8字节对应1字节的映射的方式建立影子内存区。
相同功能下,开启asan后,代码rom大小多了约20%-30%(每个对内存访问的指令前都会增加一个跳转指令),data没有变化,因为heap大小是自适应的,实际应该多消耗1/32的heap空间。如果以后功能增强,资源占用会变化。
更多推荐
所有评论(0)