内核地址消毒剂(KASAN)

KASAN(Kernel Address Sanitizer)是Linux内核的动态内存错误检测工具,用于检测内存越界和使用已释放内存等问题。KASAN有通用、基于软件标签和基于硬件标签三种模式,适用于不同的硬件平台和性能需求。在启用KASAN时,可通过配置选项选择模式,并调整启动参数以控制其行为。KASAN报告详细地提供错误类型、堆栈跟踪和内存状态,帮助开发者定位和修复问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

概述
Kernel Address SANitizer(KASAN)是一种动态内存安全错误检测工具,主要功能是 检查内存越界访问和使用已释放内存的问题。

KASAN有三种模式:

通用KASAN
基于软件标签的KASAN
基于硬件标签的KASAN
用CONFIG_KASAN_GENERIC启用的通用KASAN,是用于调试的模式,类似于用户空 间的ASan。这种模式在许多CPU架构上都被支持,但它有明显的性能和内存开销。

基于软件标签的KASAN或SW_TAGS KASAN,通过CONFIG_KASAN_SW_TAGS启用, 可以用于调试和自我测试,类似于用户空间HWASan。这种模式只支持arm64,但其 适度的内存开销允许在内存受限的设备上用真实的工作负载进行测试。

基于硬件标签的KASAN或HW_TAGS KASAN,用CONFIG_KASAN_HW_TAGS启用,被 用作现场内存错误检测器或作为安全缓解的模式。这种模式只在支持MTE(内存标签 扩展)的arm64 CPU上工作,但它的内存和性能开销很低,因此可以在生产中使用。

关于每种KASAN模式的内存和性能影响的细节,请参见相应的Kconfig选项的描述。

通用模式和基于软件标签的模式通常被称为软件模式。基于软件标签的模式和基于 硬件标签的模式被称为基于标签的模式。

支持
体系架构
在x86_64、arm、arm64、powerpc、riscv、s390、xtensa和loongarch上支持通用KASAN, 而基于标签的KASAN模式只在arm64上支持。

编译器
软件KASAN模式使用编译时工具在每个内存访问之前插入有效性检查,因此需要一个 提供支持的编译器版本。基于硬件标签的模式依靠硬件来执行这些检查,但仍然需要 一个支持内存标签指令的编译器版本。

通用KASAN需要GCC 8.3.0版本或更高版本,或者内核支持的任何Clang版本。

基于软件标签的KASAN需要GCC 11+或者内核支持的任何Clang版本。

基于硬件标签的KASAN需要GCC 10+或Clang 12+。

内存类型
通用KASAN支持在所有的slab、page_alloc、vmap、vmalloc、堆栈和全局内存 中查找错误。

基于软件标签的KASAN支持slab、page_alloc、vmalloc和堆栈内存。

基于硬件标签的KASAN支持slab、page_alloc和不可执行的vmalloc内存。

对于slab,两种软件KASAN模式都支持SLUB和SLAB分配器,而基于硬件标签的 KASAN只支持SLUB。

用法
要启用KASAN,请使用以下命令配置内核:

CONFIG_KASAN=y
同时在 CONFIG_KASAN_GENERIC (启用通用KASAN模式), CONFIG_KASAN_SW_TAGS (启用基于硬件标签的KASAN模式),和 CONFIG_KASAN_HW_TAGS (启用基于硬件标签 的KASAN模式)之间进行选择。

对于软件模式,还可以在 CONFIG_KASAN_OUTLINE 和 CONFIG_KASAN_INLINE 之间进行选择。outline和inline是编译器插桩类型。前者产生较小的二进制文件, 而后者快2倍。

要将受影响的slab对象的alloc和free堆栈跟踪包含到报告中,请启用 CONFIG_STACKTRACE 。要包括受影响物理页面的分配和释放堆栈跟踪的话, 请启用 CONFIG_PAGE_OWNER 并使用 page_owner=on 进行引导。

启动参数
KASAN受到通用 panic_on_warn 命令行参数的影响。当它被启用时,KASAN 在打印出错误报告后会使内核恐慌。

默认情况下,KASAN只对第一个无效的内存访问打印错误报告。使用 kasan_multi_shot,KASAN对每一个无效的访问都打印一份报告。这会禁用 了KASAN报告的 panic_on_warn。

另外,独立于 panic_on_warn 、 kasan.fault= boot参数可以用 来控制恐慌和报告行为。

kasan.fault=report 或 =panic 控制是否只打印KASAN report或 同时使内核恐慌(默认: report )。即使 kasan_multi_shot 被 启用,恐慌也会发生。

基于软件和硬件标签的KASAN模式(见下面关于各种模式的部分)支持改变堆栈跟 踪收集行为:

kasan.stacktrace=off 或 =on 禁用或启用分配和释放堆栈痕 迹的收集(默认: on )。

kasan.stack_ring_size= 指定堆栈环的条 目数(默认: 32768 )。

基于硬件标签的KASAN模式是为了在生产中作为一种安全缓解措施使用。因此,它 支持额外的启动参数,允许完全禁用KASAN或控制其功能。

kasan=off 或 =on 控制KASAN是否被启用(默认: on )。

kasan.mode=

ld.lld: error: undefined symbol: kasan_init_hw_tags >>> referenced by smp.c:471 (/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/arch/arm64/kernel/smp.c:471) >>> vmlinux.o:(smp_prepare_boot_cpu) ld.lld: error: undefined symbol: __kasan_cache_create_kmalloc >>> referenced by kasan.h:143 (/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/include/linux/kasan.h:143) >>> vmlinux.o:(create_kmalloc_cache) ld.lld: error: undefined symbol: kasan_flag_enabled >>> referenced by irqbypass.c >>> vmlinux.o:(__jump_table+0xE58) >>> referenced by irqbypass.c >>> vmlinux.o:(__jump_table+0xE88) >>> referenced by irqbypass.c >>> vmlinux.o:(__jump_table+0x5FD8) >>> referenced 894 more times ld.lld: error: undefined symbol: kasan_init_hw_tags_cpu >>> referenced by cpufeature.c:1877 (/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/arch/arm64/kernel/cpufeature.c:1877) >>> vmlinux.o:(cpu_enable_mte) ld.lld: error: undefined symbol: kasan_report_async >>> referenced by mte.c:187 (/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/arch/arm64/kernel/mte.c:187) >>> vmlinux.o:(mte_check_tfsr_el1) >>> referenced by mte.c:187 (/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/arch/arm64/kernel/mte.c:187) >>> vmlinux.o:(mte_thread_switch) >>> referenced by mte.c:187 (/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/arch/arm64/kernel/mte.c:187) >>> vmlinux.o:(mte_suspend_enter) ld.lld: error: undefined symbol: kasan_report >>> referenced by fault.c:334 (/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/arch/arm64/mm/fault.c:334) >>> vmlinux.o:(__do_kernel_fault) ld.lld: error: undefined symbol: __kasan_unpoison_range >>> referenced by kasan.h:111 (/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/include/linux/kasan.h:111) >>> vmlinux.o:(dup_task_struct) >>> referenced by kasan.h:111 (/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/include/linux/kasan.h:111) >>> vmlinux.o:(mempool_exit) >>> referenced by kasan.h:111 (/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/include/linux/kasan.h:111) >>> vmlinux.o:(remove_element) >>> referenced 3 more times ld.lld: error: undefined symbol: __kasan_unpoison_vmalloc >>> referenced by kasan.h:416 (/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/include/linux/kasan.h:416) >>> vmlinux.o:(scs_alloc) >>> referenced by kasan.h:416 (/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/include/linux/kasan.h:416) >>> vmlinux.o:(scs_free) >>> referenced by kasan.h:416 (/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/include/linux/kasan.h:416) >>> vmlinux.o:(vm_map_ram) >>> referenced 2 more times ld.lld: error: undefined symbol: __kasan_poison_vmalloc >>> referenced by kasan.h:425 (/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/include/linux/kasan.h:425) >>> vmlinux.o:(scs_alloc) >>> referenced by kasan.h:425 (/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/include/linux/kasan.h:425) >>> vmlinux.o:(vm_unmap_ram) >>> referenced by kasan.h:425 (/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/include/linux/kasan.h:425) >>> vmlinux.o:(__vunmap) ld.lld: error: undefined symbol: __kasan_unpoison_pages >>> referenced by kasan.h:127 (/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/include/linux/kasan.h:127) >>> vmlinux.o:(mempool_exit) >>> referenced by kasan.h:127 (/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/include/linux/kasan.h:127) >>> vmlinux.o:(remove_element) >>> referenced by kasan.h:127 (/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/include/linux/kasan.h:127) >>> vmlinux.o:(mempool_resize) >>> referenced 4 more times ld.lld: error: undefined symbol: __kasan_poison_pages >>> referenced by kasan.h:119 (/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/include/linux/kasan.h:119) >>> vmlinux.o:(mempool_init_node) >>> referenced by kasan.h:119 (/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/include/linux/kasan.h:119) >>> vmlinux.o:(mempool_resize) >>> referenced by kasan.h:119 (/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/include/linux/kasan.h:119) >>> vmlinux.o:(mempool_free) >>> referenced 2 more times ld.lld: error: undefined symbol: __kasan_slab_free_mempool >>> referenced by kasan.h:208 (/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/include/linux/kasan.h:208) >>> vmlinux.o:(mempool_init_node) >>> referenced by kasan.h:208 (/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/include/linux/kasan.h:208) >>> vmlinux.o:(mempool_resize) >>> referenced by kasan.h:208 (/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/include/linux/kasan.h:208) >>> vmlinux.o:(mempool_free) ld.lld: error: undefined symbol: __kasan_never_merge >>> referenced by kasan.h:103 (/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/include/linux/kasan.h:103) >>> vmlinux.o:(slab_unmergeable) >>> referenced by kasan.h:103 (/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/include/linux/kasan.h:103) >>> vmlinux.o:(find_mergeable) >>> referenced by kasan.h:103 (/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/include/linux/kasan.h:103) >>> vmlinux.o:(find_mergeable) ld.lld: error: undefined symbol: __kasan_kmalloc_large >>> referenced by kasan.h:237 (/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/include/linux/kasan.h:237) >>> vmlinux.o:(kmalloc_order) ld.lld: error: undefined symbol: __kasan_check_byte >>> referenced by kasan.h:259 (/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/include/linux/kasan.h:259) >>> vmlinux.o:(krealloc) >>> referenced by kasan.h:259 (/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/include/linux/kasan.h:259) >>> vmlinux.o:(kfree_sensitive) >>> referenced by kasan.h:259 (/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/include/linux/kasan.h:259) >>> vmlinux.o:(ksize) ld.lld: error: undefined symbol: __kasan_krealloc >>> referenced by kasan.h:247 (/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/include/linux/kasan.h:247) >>> vmlinux.o:(krealloc) ld.lld: error: undefined symbol: kasan_free_pages >>> referenced by page_alloc.c:1361 (/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/mm/page_alloc.c:1361) >>> vmlinux.o:(__free_pages_ok) >>> referenced by page_alloc.c:1361 (/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/mm/page_alloc.c:1361) >>> vmlinux.o:(free_unref_page_prepare) ld.lld: error: undefined symbol: kasan_alloc_pages >>> referenced by page_alloc.c:2410 (/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/mm/page_alloc.c:2410) >>> vmlinux.o:(post_alloc_hook) >>> referenced by page_alloc.c:2410 (/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/mm/page_alloc.c:2410) >>> vmlinux.o:(prep_new_page) ld.lld: error: undefined symbol: __kasan_metadata_size >>> referenced by kasan.h:150 (/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/include/linux/kasan.h:150) >>> vmlinux.o:(print_trailer) >>> referenced by kasan.h:150 (/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/include/linux/kasan.h:150) >>> vmlinux.o:(check_object) ld.lld: error: undefined symbol: __kasan_kmalloc >>> referenced by kasan.h:227 (/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/include/linux/kasan.h:227) >>> vmlinux.o:(kmem_cache_alloc_trace) >>> referenced by kasan.h:227 (/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/include/linux/kasan.h:227) >>> vmlinux.o:(__kmalloc) >>> referenced by kasan.h:227 (/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/include/linux/kasan.h:227) >>> vmlinux.o:(__kmalloc_track_caller) ld.lld: error: too many errors emitted, stopping now (use --error-limit=0 to see all errors) make[1]: *** [/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/Makefile:1277: vmlinux] Error 1 make[1]: Leaving directory '/home/lhl/ga-4.1/repo_code/out/oriole/kernel/OBJ/linux-5.15' make: *** [Makefile:237: __sub-make] Error 2
最新发布
07-22
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值