一、简介:

Kasan 是 Kernel Address Sanitizer 的缩写,它是一个动态检测内存错误的工具,主要功能是检查内存越界访问和使用已释放的内存等问题。KASAN可以检测的内存异常包括:slab-out-of-bounds/user-after-free/stack-out-of-bounds/global-out-of-bounds等。

(1)环境要求:
GCC 5.0或者以上的编译器;

(2)打开方法:

CONFIG_KASAN=y
CONFIG_KASAN_OUTLINE=y(性能会变差)或CONFIG_KASAN_INLINE=y

如某些文件或者目录不想加入KASAN的检测,可以做如下处理:

在对应的Makefile里添加(文件:xxx.c):

KASAN_SANITIZE_xxx.o := n

在对应的Makefile里添加:

KASAN_SANITIZE := n

(3)相关概念
如下图是8个字节内存映射1个字节shadow memory,(部分内核可能是16:1的关系,后面的例程就是16:1),这样8字节的内存就会牺牲1字节的用于标记readzone,这样会导致性能的部分下降,造成系统卡顿。下图中,当8个字节全部可用时,这块shadow memory会标记位0x00,7个字节可用时会标记位0x07 …;

部分其他的值代表如下:

在内存相关的操作时,当打开KASAN时,编译器自动插入检查代码:

*address = ...; // or: ... = *address;// 操作某块地址
shadow_address = MemToShadow(address);
if (ShadowIsPoisoned(shadow_address)) { //对该块地址进行检查ReportError(address, kAccessSize, kIsWrite); //越界或者其他异常报错
}
*address = ...; // or: ... = *address;//无异常继续进行操作

二、实例:

(1)slab-out-of-bounds越界检测:

在前文创建sys节点的基础上,对cat调用的的show函数修改如下:

static ssize_t hello_test_show(struct device *dev, struct device_attribute *attr, char *buf)
{size_t size = 21;char *ptr = NULL;printk("hello_test %s,%d\n",__FUNCTION__,__LINE__);ptr = kmalloc(size, GFP_KERNEL); //申请21bit字节可用的内存if(!ptr){pr_err("Allocation failed! \n");return -1;}ptr[size + 1] = 'X';//给30 + 1大小的内存写X,实际越界2字节kfree(ptr);return 0;
}

当cat /sys/bus/platform/drivers/hello_test/odm:hello_test/hello_test,会产生越界异常,这是KASAN的机制会捕捉到,并产生KE异常,解析KE的DB文件,如下看到如下堆栈异常:

[  101.291091]  (3)[5074:cat]hello_test hello_test_show,16
[  101.291131] -(3)[5074:cat]==================================================================
[  101.291163] -(3)[5074:cat]BUG: KASAN: slab-out-of-bounds in hello_test_show+0x58/0x88 at addr ffffffdabc0a2a96
[  101.291175] -(3)[5074:cat]Write of size 1 by task cat/5074
[  101.291195] -(3)[5074:cat]CPU: 3 PID: 5074 Comm: cat Tainted: G        W  O    4.9.77+ #16
[  101.291206] -(3)[5074:cat]Hardware name: MT6761V/WBB (DT)
[  101.291218] -(3)[5074:cat]Call trace:
[  101.291239] -(3)[5074:cat][<ffffff8fa848b4e8>] dump_backtrace+0x0/0x358
[  101.291254] -(3)[5074:cat][<ffffff8fa848b8dc>] show_stack+0x14/0x20
[  101.291273] -(3)[5074:cat][<ffffff8fa88de118>] dump_stack+0xa8/0xd0
[  101.291293] -(3)[5074:cat][<ffffff8fa86933c4>] kasan_object_err+0x24/0x80
[  101.291308] -(3)[5074:cat][<ffffff8fa8693654>] kasan_report.part.1+0x1dc/0x498
[  101.291323] -(3)[5074:cat][<ffffff8fa8693b98>] qlist_move_cache+0x0/0xc0
[  101.291338] -(3)[5074:cat][<ffffff8fa8691fe4>] __asan_store1+0x4c/0x58
[  101.291354] -(3)[5074:cat][<ffffff8fa8ec13a8>] hello_test_show+0x58/0x88
[  101.291371] -(3)[5074:cat][<ffffff8fa8a12678>] dev_attr_show+0x40/0x88
[  101.291389] -(3)[5074:cat][<ffffff8fa87549b8>] sysfs_kf_seq_show+0x128/0x1c8
[  101.291404] -(3)[5074:cat][<ffffff8fa8752720>] kernfs_seq_show+0x80/0x98
[  101.291421] -(3)[5074:cat][<ffffff8fa86d6fd4>] seq_read+0x14c/0x720
[  101.291436] -(3)[5074:cat][<ffffff8fa8753774>] kernfs_fop_read+0x1e4/0x280
[  101.291452] -(3)[5074:cat][<ffffff8fa86a074c>] __vfs_read+0x74/0x1d0
[  101.291466] -(3)[5074:cat][<ffffff8fa86a1ac0>] vfs_read+0x98/0x188
[  101.291480] -(3)[5074:cat][<ffffff8fa86a35b0>] SyS_read+0x68/0xe0
[  101.291496] -(3)[5074:cat][<ffffff8fa8482f70>] el0_svc_naked+0x24/0x28
[  101.291508] -(3)[5074:cat]Object at ffffffdabc0a2a80, in cache kmalloc-64 size: 64
[  101.291517] -(3)[5074:cat]Allocated:
......
[  101.291989] -(3)[5074:cat] ffffffdabc0a2800: fb fb fb fb fc fc fc fc fb fb fb fb fc fc fc fc
[  101.292003] -(3)[5074:cat] ffffffdabc0a2900: 00 00 00 fc fc fc fc fc 00 00 00 00 fc fc fc fc
[  101.292016] -(3)[5074:cat]>ffffffdabc0a2a00: fb fb fb fb fc fc fc fc 00 05 fc fc fc fc fc fc^
[  101.292026] -(3)[5074:cat]

其中:
0xFC是Redzone标记,如果访问了Redzone区域KASAN就会检测out-of-bounds的发生;
0xFB标记内存是释放的状态。但是不是可用状态;
0x00是可用内存;
此处的shadow memory和可用内存是16:1的 关系,故0x00代表16字节可用,0x05代码5字节可用,故和申请的21字节匹配上。

(2)user-after-free释放后使用:

将代码修改如下,然后cat对应的节点,同样会产生KE的DB文件,

static ssize_t hello_test_show(struct device *dev, struct device_attribute *attr, char *buf)
{size_t size = 21;char *ptr = NULL;printk("hello_test %s,%d\n",__FUNCTION__,__LINE__);ptr = kmalloc(size, GFP_KERNEL);if(!ptr){pr_err("Allocation failed! \n");return -1;}//ptr[size + 1] = 'X';kfree(ptr); //提前释放ptr[size - 1] = 'X'; //释放后对此内存进程赋值写入数据return 0;
}

log显示如下:

[   98.979214]  (1)[4982:cat]hello_test hello_test_show,16
[   98.979256] -(1)[4982:cat]==================================================================
[   98.979284] -(1)[4982:cat]BUG: KASAN: use-after-free in hello_test_show+0x5c/0x88 at addr ffffffe777c16f94
[   98.979296] -(1)[4982:cat]Write of size 1 by task cat/4982
[   98.979313] -(1)[4982:cat]CPU: 1 PID: 4982 Comm: cat Tainted: G        W  O    4.9.77+ #18
[   98.979324] -(1)[4982:cat]Hardware name: MT6761V/WBB (DT)
[   98.979334] -(1)[4982:cat]Call trace:
[   98.979354] -(1)[4982:cat][<ffffffa7baa8b4e8>] dump_backtrace+0x0/0x358
[   98.979368] -(1)[4982:cat][<ffffffa7baa8b8dc>] show_stack+0x14/0x20
[   98.979385] -(1)[4982:cat][<ffffffa7baede118>] dump_stack+0xa8/0xd0
[   98.979402] -(1)[4982:cat][<ffffffa7bac933c4>] kasan_object_err+0x24/0x80
[   98.979417] -(1)[4982:cat][<ffffffa7bac93654>] kasan_report.part.1+0x1dc/0x498
[   98.979431] -(1)[4982:cat][<ffffffa7bac93b98>] qlist_move_cache+0x0/0xc0
[   98.979444] -(1)[4982:cat][<ffffffa7bac91fe4>] __asan_store1+0x4c/0x58
[   98.979459] -(1)[4982:cat][<ffffffa7bb4c13ac>] hello_test_show+0x5c/0x88
[   98.979475] -(1)[4982:cat][<ffffffa7bb012678>] dev_attr_show+0x40/0x88
[   98.979491] -(1)[4982:cat][<ffffffa7bad549b8>] sysfs_kf_seq_show+0x128/0x1c8
[   98.979506] -(1)[4982:cat][<ffffffa7bad52720>] kernfs_seq_show+0x80/0x98
[   98.979521] -(1)[4982:cat][<ffffffa7bacd6fd4>] seq_read+0x14c/0x720
[   98.979534] -(1)[4982:cat][<ffffffa7bad53774>] kernfs_fop_read+0x1e4/0x280
[   98.979549] -(1)[4982:cat][<ffffffa7baca074c>] __vfs_read+0x74/0x1d0
[   98.979562] -(1)[4982:cat][<ffffffa7baca1ac0>] vfs_read+0x98/0x188
[   98.979575] -(1)[4982:cat][<ffffffa7baca35b0>] SyS_read+0x68/0xe0
[   98.979999] -(1)[4982:cat] ffffffe777c16d00: 00 00 00 00 fc fc fc fc fb fb fb fb fc fc fc fc
[   98.980012] -(1)[4982:cat] ffffffe777c16e00: fb fb fb fb fc fc fc fc 00 00 00 00 fc fc fc fc
[   98.980025] -(1)[4982:cat]>ffffffe777c16f00: fb fb fb fb fc fc fc fc fb fb fb fb fc fc fc fc^
[   98.980034] -(1)[4982:cat]

如上0xFB标记内存是释放的状态。但对其进行写入,故出现报错。

内存管理 内核内存检测KASAN相关推荐

  1. 【Linux 内核 内存管理】内存管理架构 ④ ( 内存分配系统调用过程 | 用户层 malloc free | 系统调用层 brk mmap | 内核层 kmalloc | 内存管理流程 )

    文章目录 一.内存分配系统调用过程 ( 用户层 | 系统调用 | 内核层 ) 二.内存管理流程 一.内存分配系统调用过程 ( 用户层 | 系统调用 | 内核层 ) " 堆内存 " ...

  2. 【Linux 内核 内存管理】内存管理架构 ① ( 内存管理架构组成 | 用户空间 | 内核空间 | MMU 硬件 | Linux 内核架构层次 | Linux 系统调用接口 )

    文章目录 一.内存管理架构组成 ( 用户空间 | 内核空间 | MMU 硬件 ) 二.Linux 内核架构层次 三.Linux 系统调用接口 一.内存管理架构组成 ( 用户空间 | 内核空间 | MM ...

  3. 【Linux 内核 内存管理】内存映射相关数据结构 ③ ( vm_area_struct 结构体成员分析 | shared 成员 | anon_vma_chain 成员 | anon_vma 成员 )

    文章目录 一.vm_area_struct 结构体成员分析 1.shared 成员 2.anon_vma_chain 成员 3.anon_vma 成员 二.vm_area_struct 结构体完整源码 ...

  4. Linux内存管理:内存分配:slab分配器

    <linux内核之slob.slab.slub> <Linux内核:kmalloc()和SLOB.SLAB.SLUB内存分配器> <Linux内存管理:内存分配:slab ...

  5. 内存分配器 mysql_聊MySQL内存管理,内存分配器,操作系统

    推荐(免费):mysql视频教程 当用户在使用任何软件(包括MySQL)时遇到内存问题,我们的第一反应就是内存泄漏.正如本文所示,情况并非总是如此. 本文描述了一个关于内存的bug. 所有Percon ...

  6. 内存分配器 mysql_MySQL内存管理,内存分配器和操作系统的示例分析

    MySQL内存管理,内存分配器和操作系统的示例分析 发布时间:2021-01-08 14:06:39 来源:亿速云 阅读:79 作者:小新 这篇文章主要介绍MySQL内存管理,内存分配器和操作系统的示 ...

  7. Linux内存管理之内存管理单元(MMU)(二)

    Linux内存管理之内存管理单元(二) 1.1.什么是MMU 在CPU内部,有一个专门的硬件单元来负责这个虚拟页面到物理页面的转换,它被被称为内存管理单元(Memory Management Unit ...

  8. Linux内存管理:内存寻址之分段机制与分页机制

    目录 Linux 内存寻址之分段机制 前言 分段到底是怎么回事? 实模式的诞生(16位处理器及寻址) 保护模式的诞生(32位处理器及寻址) IA32的内存寻址机制 寻址硬件 IA32的三种地址 MMU ...

  9. Linux内存管理:内存描述之高端内存

    <Linux内存管理:内存描述之内存节点node> <Linux内存管理:内存描述之内存区域zone> <Linux内存管理:内存描述之内存页面page> < ...

最新文章

  1. java ee开发技术 上海大学_学院介绍
  2. fatal error C1900: Il mismatch between 'P1' version '20060201' and 'P2' version '20050411'
  3. 水晶报表乱码中文乱码问题(收藏)
  4. C#的类,构造函数以及Array阵列的数据填充与绑定
  5. AngularJs 基础教程 —— 控制器
  6. 初中信息技术python教案_初中信息技术优质课教案 python程序设计开发第二课 第5课变量 教案...
  7. model数据库orm操作
  8. java json 修改字段_我们如何使用Java中的Jackson来更改JSON中的字段名称?
  9. C程序设计 4顺序程序设计
  10. ftell函数使用注意事项
  11. C盘扩容_解决过程记录
  12. 天载配资关注这个转折点机会
  13. vue知识(四)生命周期、钩子函数、路由
  14. 电磁波极化原理及仿真
  15. 华为云弹性云服务器有哪些优势?
  16. 《深入理解JAVA虚拟机》周志明 第三版 - 第二章 JAVA内存区域与内存溢出异常
  17. 我的物联网项目(二十六) 商家微信充值流程优化
  18. 12 个在线学习 Linux 技能网站
  19. CRM下午茶(七)-潜在客户流失排查
  20. 固态硬盘:NVME 命令队列 SQ/CQ 的奥秘

热门文章

  1. pay 和 put的用法
  2. 污水处理程序 工厂污水处理控制系统
  3. 关于如何通过IE浏览器获取客户端的IP地址和Mac地址
  4. java毕业设计茶园认养管理系统Mybatis+系统+数据库+调试部署
  5. 【暴力枚举】【JAVA】P3654First Step
  6. 三极管基极串联一个电阻 和并联一个到地电阻的意义
  7. 深度学习图像超分辨率开山之作SRCNN——原理分析及代码(效果基本可以达到论文中的效果)
  8. IoT入门:拆解物联网全栈开发工作
  9. AndroidManifest权限声明中英文对照完整列表
  10. android studio发邮件功能,Android发送电子邮件