Ubuntu 22.04内核模块编译遇ASan未定义符号错误求助
KASAN相关内核模块编译问题解答
问题背景
我正尝试在**Ubuntu 22.04(Linux内核6.1.25)**环境下编译“Hello, World”内核模块,但执行make命令时,遇到与AddressSanitizer(ASan)相关的错误:
make -C /lib/modules/6.1.25-lkp-kernel/build/ M=$(PWD) modules make[1]: Entering directory '/home/c2kp/kernels/linux-6.1.25' CC [M] /home/c2kp/Linux-Kernel-Programming_2E/ch4/helloworld_lkm/helloworld_lkm.o MODPOST /home/c2kp/Linux-Kernel-Programming_2E/ch4/helloworld_lkm/Module.symvers ERROR: modpost: "__asan_unregister_globals" [/home/c2kp/Linux-Kernel-Programming_2E/ch4/helloworld_lkm/helloworld_lkm.ko] undefined! ERROR: modpost: "__asan_register_globals" [/home/c2kp/Linux-Kernel-Programming_2E/ch4/helloworld_lkm/helloworld_lkm.ko] undefined! make[2]: *** [scripts/Makefile.modpost:126: /home/c2kp/Linux-Kernel-Programming_2E/ch4/helloworld_lkm/Module.symvers] Error 1 make[1]: *** [Makefile:1964: modpost] Error 2 make[1]: Leaving directory '/home/c2kp/kernels/linux-6.1.25' make: *** [Makefile:9: all] Error 2
我的Makefile内容如下:
PWD := $(shell pwd) KDIR := /lib/modules/$(shell uname -r)/build/ obj-m += helloworld_lkm.o ccflags-y += -fsanitize=kernel-address all: make -C $(KDIR) M=$(PWD) modules install: make -C $(KDIR) M=$(PWD) modules_install clean: make -C $(KDIR) M=$(PWD) clean
咨询问题
- 为何这些未定义符号会导致我的内核模块编译失败?
- 当内核已启用KASAN时,确保模块正确编译的最佳方式是什么?
- 在Makefile中添加
ccflags-y += -fsanitize=kernel-address是否为正确修复方案,还是应在内核中禁用KASAN?
问题解答
1. 未定义符号导致编译失败的原因
__asan_register_globals和__asan_unregister_globals是KASAN(内核地址 sanitizer)提供的核心符号,负责在模块加载/卸载时注册、清理内存检测所需的全局元数据。
你手动在Makefile中添加-fsanitize=kernel-address编译选项,强制模块启用KASAN,但当前使用的内核要么未编译KASAN支持,要么KASAN的符号未导出到模块可用范围,导致链接阶段找不到这些必要符号,最终编译失败。
2. 内核已启用KASAN时模块正确编译的最佳方式
如果内核已经启用KASAN(内核配置中CONFIG_KASAN=y或CONFIG_KASAN=m),无需手动在模块Makefile中添加-fsanitize=kernel-address:
- 内核构建系统会自动将全局的KASAN编译选项继承到模块编译流程中,确保模块与内核的KASAN配置一致。
- 确认内核配置:查看
/boot/config-$(uname -r)文件,检查是否存在CONFIG_KASAN=y或CONFIG_KASAN=m;如果是模块化KASAN(CONFIG_KASAN=m),需先加载kasan.ko内核模块。
3. Makefile添加编译选项vs禁用内核KASAN的选择
- 不要手动添加
ccflags-y += -fsanitize=kernel-address:该操作会强制模块启用KASAN,若内核本身无KASAN支持或符号未导出,必然触发未定义符号错误。正确做法是让内核构建系统自动处理KASAN编译选项的继承。 - 是否禁用内核KASAN?取决于你的需求:
- 若无需内存检测功能,且当前内核的KASAN导致模块编译问题,可重新编译内核并关闭
CONFIG_KASAN选项。 - 若需要KASAN的内存检测能力,确保内核已正确启用KASAN(且符号导出),移除Makefile中手动添加的KASAN编译选项后重新编译模块即可。
- 若无需内存检测功能,且当前内核的KASAN导致模块编译问题,可重新编译内核并关闭
内容的提问来源于stack exchange,提问作者skm
相关产品推荐
相关产品推荐

