本文共 2189 字,大约阅读时间需要 7 分钟。
KASAN(Kernel Address Sanitizer)是一种动态检测内存错误的工具,专为检测内核中的use-after-free(UAF)和out-of-bounds(OOB)问题而设计。其核心原理是通过在内存访问时插入额外的检查代码,确保每次内存操作都在合法范围内进行。KASAN能够检测全局变量、栈和堆分配的内存越界访问,是一种功能强大的内核安全工具。
KASAN的主要优势包括:
KASAN通过以下机制实现内存检测:
为了启用KASAN,需在内核配置中设置以下参数:
CONFIG_SLUB_DEBUG=yCONFIG_KASAN=y
KASAN最初依赖SLUB_DEBUG,但现在已不再依赖。启用SLUB_DEBUG可提供额外的日志信息,有助于调试和排查错误。建议在开发阶段保留该选项。
启用KASAN后,重新编译内核。编译完成后,内核镜像大小会略微增加,但这只是为了检测内存错误而付出的代价。
在内核运行时,KASAN会记录检测到的错误信息到内核日志中。可以通过查看dmesg输出,分析具体的内存错误类型和位置。
KASAN的核心逻辑主要集中在mm/kasan/kasan.c文件中。
KASAN通过以下步骤检测内存访问:
__asan_load##size()函数,验证对应的shadow memory值。__asan_store##size()函数,验证写入的地址是否合法。KASAN将内核地址空间划分为8部分,每部分用于shadow memory。具体分配方式如下:
shadow_addr = (kaddr >> 3) + KASAN_SHADOW_OFFSET与内核地址映射。KASAN与内存分配器(如SLUB、伙伴系统)紧密配合,确保内存分配和释放过程中的每一步都可检测。
伙伴系统在分配内存时,会记录shadow memory值。例如,分配4页内存时,shadow memory值初始化为0,表示内存可用。
当释放内存时,KASAN将对应的shadow memory值标记为0xFF,表示内存已释放。若继续访问此区域,可检测到use-after-free错误。
全局变量的redzone填充方式类似于内存分配。例如,定义char a[4];时,编译器会自动填充redzone区域,并记录shadow memory值。
栈分配变量的redzone检测与全局变量类似。例如:
void foo() { char a[328]; char rz1[32]; char rz2[56]; int *shadow = (rz1 >> 3) + KASAN_SHADOW_OFFSET; // 编译器会自动填充shadow memory值} KASAN的错误日志通常包含以下信息:
use-after-free或out-of-bounds。0xffff800012345678的值。通过分析这些信息,可以快速定位内存问题的位置和原因。
KASAN为内核开发提供了强有力的内存安全保障。通过配置和使用KASAN,开发者可以快速定位和修复内存相关的安全问题,提升内核系统的稳定性。
转载地址:http://yrnz.baihongyu.com/