kasan是linux内核运行时内存错误检测工具,可精准捕获use-after-free和out-of-bounds等错误,通过编译插桩与影子内存映射实现实时检测,但存在2–5倍性能开销和1/8内存占用,仅适用于开发调试。

直接查 dmesg 或 /var/log/messages(RHEL/CentOS)或 /var/log/syslog(Debian/Ubuntu)中含 segfault、out of bounds、KASAN、use-after-free 等关键词的日志,就能快速锁定内存越界发生的时间、进程、地址和调用上下文。关键不是找“错误”这个词,而是抓内核主动记录的异常行为痕迹。
重点盯住几类典型日志线索
内核对内存越界有不同层级的检测输出,需分情况识别:
-
普通段错误日志:如
myapp[12345]: segfault at 7f8de69a9e18 ip 00000000004012ab error 4,说明进程访问了非法地址;at是越界地址,ip是崩溃指令位置,error 4表示用户态写失败(常见于数组越界写) -
KASAN 检测日志:若内核启用了 KASAN(常见于开发/测试环境),会输出极详细的越界报告,例如:
==================================================================开头的红字块,明确指出是slab-out-of-bounds还是use-after-free,并附带分配/释放/访问三处的函数栈和源码行号 -
Oops 或 Panic 日志:如果越界破坏了内核关键数据结构(如 task_struct、page 结构),可能触发 Oops 或直接 Panic,日志里会出现
BUG: unable to handle kernel paging request或Kernel panic - not syncing,此时要结合RIP、Call Trace定位内核模块或驱动问题
结合进程与二进制定位具体代码
光看地址没用,得把日志里的信息映射回源码:
- 从日志中提取进程名(如
myapp[12345])和ip值(如00000000004012ab),确认该程序是否带调试符号(file myapp查看是否含debug) - 用
objdump -d myapp | grep "4012ab"反查汇编指令,再对照源码确认对应逻辑;若带-g编译,可用addr2line -e myapp 0x4012ab直接得到文件与行号 - 若
ip落在libc或libstdc++地址段,说明越界发生在标准库调用中(如strcpy写穿缓冲区、std::vector::at()越界访问),需检查传入参数合法性
用 Core Dump 验证现场状态
日志只说“在哪崩”,Core Dump 才能告诉你“为什么崩”:
- 确保已开启 core dump:
ulimit -c unlimited,并设置保存路径,例如:echo "/tmp/core.%e.%p" | sudo tee /proc/sys/kernel/core_pattern - 崩溃后找 core 文件:
find /tmp -name "core.*" -mmin -5 2>/dev/null(查最近 5 分钟) - 用
gdb ./myapp core.xxx加载后执行bt full,查看完整调用栈、局部变量值和寄存器状态,尤其关注崩溃前刚操作的指针、数组索引、容器 size/capacity
借助 ASan 或 KASAN 提前暴露问题
生产环境难复现?建议在开发或预发阶段主动引入检测工具:
- 用户态程序加
-fsanitize=address编译,运行时会打印越界地址、访问类型、堆/栈/全局上下文,且不依赖内核支持 - 内核模块或驱动开发启用
CONFIG_KASAN=y,配合CONFIG_KASAN_OUTLINE=y获取更准确定位;注意 KASAN 仅支持 x86_64 和 arm64,且需 GCC ≥4.9.2 - 对高频越界场景(如解析网络包、处理用户输入),在关键路径插入边界检查断言,或用
valgrind --tool=memcheck做离线扫描(性能开销大,慎用于线上)











