Linux内核机制总结内存管理之内存错误检测工具KASAN(二十九)

文章目录

1 内存错误检测工具KASAN

内核地址消毒剂(Kernel Address SANitizer,KASAN)是一个动态的内存错误检查工具,为发现“释放后使用”和“越界访问”这两类缺陷提供了快速和综合的解决方案。
KASAN使用编译时插桩(compile-time instrumentation)检查每个内存访问,要求GCC编译器的版本至少是4.9.2,检查栈或全局变量的越界访问需要GCC编译器的版本至少是5.0。

内核支持KASAN的进展如下:
(1)4.0版本引入KASAN,仅x86_64架构支持,只有SLUB分配器支持KASAN。
(2)4.4版本的ARM64架构支持KASAN。
(3)4.6版本的SLAB分配器支持KASAN。

1.1 使用方法

编译内核时需要开启以下配置宏:
(1)有些版本要求先开启SLUB分配器的调试配置宏CONFIG_SLUB_DEBUG,才能看到KASAN的配置菜单项。最新版本已经不需要了,但是建议开启,因为可以打印更多有用的信息。
(2)开启配置宏CONFIG_KASAN。
(3)选择编译时插桩类型:配置宏CONFIG_KASAN_OUTLINE启用外联插桩,配置宏CONFIG_KASAN_INLINE启用内联插桩。外联插桩编译生成的程序小,内联插桩编译生成的程序运行速度快。内联手段需要GCC编译器的版本至少是5.0。
(4)为了更好地缺陷检查和报告,开启配置宏CONFIG_STACKTRACE。
如果需要为特定文件或目录禁止编译时插桩,在内核的Makefile文件中添加。
(1)为单个文件,例如main.o:KASAN_SANITIZE_main.o := n。
(2)为某个目录里面的所有文件:KASAN_SANITIZE := n。

1.2 技术原理

KASAN使用影子内存(shadow memory)记录内存的每个字节是否可以安全访问,使用编译时插桩在每次访问内存时检查影子内存。

KASAN使用内核地址空间的1/8作为影子内存,影子内存的每个字节记录内存连续8字节的状态。

(1)如果8字节都可以访问,那么影子内存的值是0。
(2)如果连续n(1n7)字节可以访问,那么影子内存的值是n。
(3)如果8字节都不能访问,那么影子内存的值是负数,使用不同的负数区分不同类型的不可访问内存,其代码如下:

#define KASAN_FREE_PAGE          0xFF  /* 页已被释放 */
#define KASAN_PAGE_REDZONE       0xFE  /* kmalloc_large()分配的红色区域 */
#define KASAN_KMALLOC_REDZONE    0xFC  /* SLAB对象里面的红色区域 */
#define KASAN_KMALLOC_FREE       0xFB  /* SLAB对象已被释放 */
#define KASAN_GLOBAL_REDZONE     0xFA  /* 全局变量的红色区域 */

把内存的内核虚拟地址转换成影子地址的方法如下:

static inline void *kasan_mem_to_shadow(const void *addr)
{
     return (void *)((unsigned long)addr >> KASAN_SHADOW_SCALE_SHIFT)
          + KASAN_SHADOW_OFFSET;
}

其中KASAN_SHADOW_SCALE_SHIFT的值是3。

KASAN使用编译时插桩检查内存访问,编译内核时需要指定编译选项“-fsanitize=kernel- address”。编译器在加载指令的前面插入函数调用“__asan_loadN(addr)”来检查内存访问是否合法,在存储指令的前面插入函数调用“__asan_storeN(addr)”来检查内存访问是否合法,N是字节数,可能是1、2、4、8或16。如果加载指令从内存加载1字节,那么编译器在加载指令的前面插入函数调用“__asan_load1(addr)”。如果存储指令存储1字节到内存中,那么编译器在存储指令的前面插入函数调用“__asan_store1(addr)”。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值