kasan排查kernel内存越界示例(linux5.18.11)
参考资料:
1,内核源码目录中的Documentation\dev-tools\kasan.rst
2,KASAN - Kernel Address Sanitizer | Naveen Naidu (naveenaidu.dev)
一、kasan实现原理
KASAN(Kernel Address SANitizer)是一个动态内存非法访问检测工具. 可以检测 use-after-free 和out-of-bounds两类错误。
KASAN将内存按8字节分一组,每组用一个额外的字节(shadow mem)来记录可访问的字节数。

shadow mem的值:
1)0,8 bytes内存都是可以访问的。
2)N (1 <= N <= 7) ,8 bytes内存的前N个字节可以访问。
3)为负数,8 bytes内存都不可访问,原因见mm/kasan/kasan.h。
mm/kasan/kasan.h
#define KASAN_FREE_PAGE 0xFF /* page was freed */
#define KASAN_PAGE_REDZONE 0xFE /* redzone for kmalloc_large allocations */
#define KASAN_KMALLOC_REDZONE 0xFC /* redzone inside slub object */
#define KASAN_KMALLOC_FREE 0xFB /* object was freed (kmem_cache_free/kfree) */
#define KASAN_VMALLOC_INVALID 0xF8 /* unallocated space in vmapped page */

二、内存越界示例
代码片段:
1197 static long do_sys_openat2(int dfd, const char __user *filename,
1198 struct open_how *how)
1199 {
1200 struct open_flags op;
1201 int fd = build_open_flags(how, &op);
1202 struct filename *tmp;
1203 int *kasan;
1204 int i;
1205
1206 if (fd)
1207 return fd;
1208
1209 tmp = getname(filename);
1210 if (IS_ERR(tmp))
1211 return PTR_ERR(tmp);
1212
1213 if (!strcmp(tmp->name, "a")) {
1214 kasan = kmalloc(100, GFP_KERNEL);
1215 if (kasan) {
1216 for (i=0; i < 200; i++)
1217 *kasan++ = 'a';
1218 printk("%s %d: kasan test finish\n", __func__, __LINE__);
1219 }
1220 }
1221
代码触发的异常log:
|
cat进程(pid=158),往地址ffff888000949d64写4个字节时,发生内存越界。 调用栈: pid=158的进程分配被越界的内存 do_sys_open --> kmalloc分配了这块内存 越界的内存块区间为 [ffff888000949d00, ffff888000949d80),该内存块含128个字节(0x49d80 - 0x49d00 = 128)。kmalloc申请100个字节,从kmalloc-128 cache中分配。 [ 103.311961] The buggy address belongs to the object at ffff888000949d00 从1开始计数,ffff888000949d64在这个区间的第100个byte地址处(0x49d64 - 0x49d00 = 100) [ 103.314742] The buggy address belongs to the physical page: kasan将内存按8 bytes分为一组,额外用1 byte内存(称作shadow memory)记录每组内存的可访问字节数,下面log中看到的每个字节就是shadow memory的值。第1个位置是00,表示第1组中8字节都可以访问;第13个位置是04,表示13组中前4个字节可以访问。 第100个byte属于第13组的第4个(100 / 8 = 12...4),log中^指向的04表示改组中前4个字节可以访问。 而我们代码1216行,通过for循环会访问到第5个字节,所以触发异常。 ================================================================== |
三、解析出异常对应的代码行号
如果编译的内核带有debug信息,CONFIG_DEBUG_KERNEL=y 或者选中Kernel hacking --->Kernel debugging,则可用kernel自带的decode_stacktrace.sh脚本解析出行号信息。
命令格式:
decode_stacktrace.sh vmlinux路径 kernel源码路径 < crash文件路径 > output.log
|
root@linux:/home/gsf/debug/kernel/linux-5.18.11# ./scripts/decode_stacktrace.sh /home/gsf/debug/kernel/linux-5.18.11/vmlinux < /home/gsf/kernel.crash …… …… |
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐


所有评论(0)