Skip to content

[components][asan] Add runtime AddressSanitizer for heap - #11772

Open
Zepp-Hanzj wants to merge 7 commits into
RT-Thread:masterfrom
Zepp-Hanzj:agent/rt-asan
Open

[components][asan] Add runtime AddressSanitizer for heap#11772
Zepp-Hanzj wants to merge 7 commits into
RT-Thread:masterfrom
Zepp-Hanzj:agent/rt-asan

Conversation

@Zepp-Hanzj

Copy link
Copy Markdown
Contributor

Description / 描述

Add a heap-only runtime AddressSanitizer (kernel-address) for RT-Thread. It instruments memory accesses via GCC's -fsanitize=kernel-address and detects heap-buffer-overflow and use-after-free at runtime, with a FinSH asan_info command for interactive diagnosis.

为 RT-Thread 新增仅针对堆的运行时 AddressSanitizer(kernel-address)。通过 GCC 的 -fsanitize=kernel-address 对内存访问插桩,在运行时检测 堆缓冲区越界(heap-buffer-overflow)释放后使用(use-after-free),并提供 FinSH asan_info 命令进行交互式诊断。

Why / 为什么需要

RT-Thread 在 MCU 目标上缺乏运行时内存安全检查(ASan 之前仅存在于 x86 模拟器)。堆越界与 use-after-free 是最常见的嵌入式内存 bug,本组件提供目标机上的运行时检测,且报告包含触发线程名与内存块归属信息。

What / 修改了哪些文件

  • components/asan/Kconfig:注册 RT_USING_ASAN(含 shadow 大小 / track 表大小 / backtrace 开关)
  • components/asan/SConscript:runtime 自身以 -fno-sanitize=kernel-address 编译避免递归
  • components/asan/asan.c:shadow memory + 插桩访问检查 + 报告 + malloc/free/realloc hook
  • components/Kconfigrsource "asan/Kconfig"
  • src/SConscript:将 mem/memheap/slab 分配器移入非插桩编译组
  • tools/building.py:GCC 下注入 -fsanitize=kernel-address

Heap algorithm support / 堆算法支持

堆类型 越界检测 use-after-free
small mem (RT_USING_SMALL_MEM_AS_HEAP)
slab (RT_USING_SLAB_AS_HEAP) ❌(元数据走插桩 rt_memset,避免误报)
memheap (RT_USING_MEMHEAP_AS_HEAP) ❌(同上)
userheap (RT_USING_USERHEAP) 互斥(Kconfig 已排除)

Verification / 验证

  • qemu-vexpress-a9:small mem / slab / memheap 三种堆编译 + 运行验证
  • 真机 STM32F407ZGT6:asan_test_overflow(overflow by 2 bytes)、asan_test_uaf(USE-AFTER-FREE, offset +0)、asan_info 全部命中
  • 编译器兼容性:GCC 8+,ARM(M0/M3/M4/M7/M33/A7/A9/A53)与 RISC-V(rv32/rv64)实测支持 kernel-address

Add a heap-only AddressSanitizer (kernel-address) runtime for RT-Thread.
It instruments memory accesses via GCC's -fsanitize=kernel-address and
detects heap-buffer-overflow and use-after-free at runtime, with a
FinSH 'asan_info' command for interactive diagnosis.

## What
- components/asan/: shadow memory + instrumented-access checks + report
- allocator hooks to poison/unpoison heap blocks (malloc/free/realloc)
- components/Kconfig: register RT_USING_ASAN with shadow/track/backtrace opts
- src/SConscript: build mem/memheap/slab allocators without instrumentation
- tools/building.py: inject -fsanitize=kernel-address on GCC

## Why
RT-Thread lacks runtime memory-safety checking on MCU targets (ASan only
existed on the x86 simulator). Heap overflow and use-after-free are the
most common embedded memory bugs; this gives on-target detection with
thread and block context in the report.

## Heap algorithm support
- small mem: full support (overflow + use-after-free)
- slab / memheap: overflow only (their allocators reuse freed blocks for
  metadata written via instrumented rt_memset, so free-block poisoning is
  disabled to avoid false positives)
- userheap: mutually exclusive (Kconfig)

Verified on qemu-vexpress-a9 (small mem / slab / memheap) and on a real
STM32F407ZGT6 board.
@github-actions

Copy link
Copy Markdown

👋 感谢您对 RT-Thread 的贡献!Thank you for your contribution to RT-Thread!

为确保代码符合 RT-Thread 的编码规范,请在你的仓库中执行以下步骤运行代码格式化工作流(如果格式化CI运行失败)。
To ensure your code complies with RT-Thread's coding style, please run the code formatting workflow by following the steps below (If the formatting of CI fails to run).


🛠 操作步骤 | Steps

  1. 前往 Actions 页面 | Go to the Actions page
    点击进入工作流 → | Click to open workflow →

  2. 点击 Run workflow | Click Run workflow

  • Use workflow from 保持默认分支(通常为 master
    Keep the default branch (usually master) in Use workflow from
  • branch 输入框填写 PR 分支 agent/rt-asan
    Enter PR branch agent/rt-asan in the branch field
  • 设置需排除的文件/目录(目录请以"/"结尾)
    Set files/directories to exclude (directories should end with "/")
  1. 等待工作流完成 | Wait for the workflow to complete
    格式化后的代码将作为独立提交推送至你的分支。
    The formatting changes will be pushed to your branch as a separate commit.

完成后,提交将自动更新至 agent/rt-asan 分支,关联的 Pull Request 也会同步更新。
Once completed, commits will be pushed to the agent/rt-asan branch automatically, and the related Pull Request will be updated.

如有问题欢迎联系我们,再次感谢您的贡献!💐
If you have any questions, feel free to reach out. Thanks again for your contribution!

@github-actions github-actions Bot added Kernel PR has src relate code tools Component labels Aug 30, 2026
@github-actions

github-actions Bot commented Aug 30, 2026

Copy link
Copy Markdown

📌 Code Review Assignment

🏷️ Tag: components

Reviewers: @Maihuanyi

Changed Files (Click to expand)
  • components/utilities/Kconfig
  • components/utilities/asan/Kconfig
  • components/utilities/asan/SConscript
  • components/utilities/asan/asan.c
  • components/utilities/asan/asan.h

🏷️ Tag: kernel

Reviewers: @GorrayLi @ReviewSun @hamburger-os @lianux-mm @wdfk-prog @xu18838022837

Changed Files (Click to expand)
  • src/SConscript
  • src/klibc/kstring.c
  • src/utest/Kconfig
  • src/utest/SConscript
  • src/utest/asan_tc.c

🏷️ Tag: workflow

Reviewers: @Rbb666 @kurisaW @supperthomas

Changed Files (Click to expand)
  • .github/utest/configs/components/asan.cfg
  • .github/workflows/utest_auto_run.yml

📊 Current Review Status (Last Updated: 2026-09-03 11:06 CST)


📝 Review Instructions

  1. 维护者可以通过单击此处来刷新审查状态: 🔄 刷新状态
    Maintainers can refresh the review status by clicking here: 🔄 Refresh Status

  2. 确认审核通过后评论 LGTM/lgtm
    Comment LGTM/lgtm after confirming approval

  3. PR合并前需至少一位维护者确认
    PR must be confirmed by at least one maintainer before merging

ℹ️ 刷新CI状态操作需要具备仓库写入权限。
ℹ️ Refresh CI status operation requires repository Write permission.

@github-actions

github-actions Bot commented Aug 30, 2026

Copy link
Copy Markdown

@BernardXiong

Copy link
Copy Markdown
Member

这部分以什么方式加入?直接加也并不合适,不应该把它做为一个独立的组件放到 components 目录下,可以考虑的方式是 components/utilities 下,或者还有一种是软件包方式。

@Zepp-Hanzj

Copy link
Copy Markdown
Contributor Author

这部分以什么方式加入?直接加也并不合适,不应该把它做为一个独立的组件放到 components 目录下,可以考虑的方式是 components/utilities 下,或者还有一种是软件包方式。

感谢反馈,我理解后觉得放 components/utilities/ 下是合适的,会把它调整为
components/utilities/asan/

关于「软件包方式」,有一点技术约束想说明:ASan 依赖 GCC 的
-fsanitize=kernel-address 插桩,这个编译选项需要注入到整个内核与
BSP 所有 .c 文件的编译流程(tools/building.py),并且需要修改内核
src/SConscript 把 mem/memheap/slab 分配器移出插桩组(否则分配器
元数据访问会被误报)。软件包机制无法修改内核的全局编译选项和构建脚本,
因此纯软件包方式只能做「不插桩、仅靠 hook」的弱化版本,无法实现真正的
AddressSanitizer。

@Rbb666 Rbb666 closed this Sep 3, 2026
@Rbb666 Rbb666 reopened this Sep 3, 2026
@Rbb666

Rbb666 commented Sep 3, 2026

Copy link
Copy Markdown
Member

感谢PR,看到了描述中支持了ARM和RV,作者能否添加下代表性的BSP(qemu-a9)进行编译看护,并添加utest使用utest-auto-run ci看护起来?

@Zepp-Hanzj

Copy link
Copy Markdown
Contributor Author

感谢PR,看到了描述中支持了ARM和RV,作者能否添加下代表性的BSP(qemu-a9)进行编译看护,并添加utest使用utest-auto-run ci看护起来?

好的,我处理一下

Add rt_asan_report_count_get() to let the utest harness verify that a
deliberate violation is actually detected (ASan uses the GCC _noabort
variant, so a hit only prints and does not abort). Also move the
use-after-free capability flag into asan.h as RT_ASAN_HAS_UAF_DETECTION
so both the runtime and tests share a single source of truth.
rt_memcpy/rt_memset/rt_memmove copy word-at-a-time and may legally touch
a few bytes past the requested count (word-aligned bulk loops). Under
-fsanitize=kernel-address those accesses fall into poisoned heap redzones
and raise false positives (notably during rt_realloc block migration).
Mark them no_sanitize_address, mirroring how KASAN treats the same
helpers.
Add a utest testcase (components.asan_tc) that exercises the ASan heap
detection on a real target, plus a CI config that both compiles and runs
it on qemu-vexpress-a9 via utest_auto_run.

Test scenarios:
- heap-buffer-overflow write / read
- in-bounds access (no false positive)
- realloc overflow
- use-after-free read / write (small mem only)
@github-actions github-actions Bot added the action github action yml imporve label Sep 3, 2026
@Zepp-Hanzj

Copy link
Copy Markdown
Contributor Author

感谢建议,已补充 utest 测试用例和 CI 看护。

新增测试用例components.asan_tc,共 6 个测试单元):

测试单元 测试场景
test_asan_overflow_write 堆缓冲区越界(写入 redzone)
test_asan_overflow_read 堆缓冲区越界(读取 redzone)
test_asan_no_false_positive 反例:边界内正常访问不误报
test_asan_realloc_overflow rt_realloc 扩容后的越界写
test_asan_uaf_read use-after-free (仅 small mem 堆)
test_asan_uaf_write use-after-free (仅 small mem 堆)

CI 看护

  • 新增 asan.cfg,在 qemu-vexpress-a9 上开启 RT_USING_ASAN 并运行 components.asan_tc
  • utest_auto_run.yml 的 matrix 中新增 A9 + asan.cfg 条目,同时实现「编译看护 + 运行看护」。

过程中发现并修复的一个问题rt_realloc 搬迁内存块时会触发 rt_memcpy 的插桩误报(rt_memcpy 按字批量拷贝会跨越 redzone),已通过给 rt_memcpy/rt_memset/rt_memmoveno_sanitize_address 修复,处理方式与 Linux KASAN 一致。

已在 qemu-vexpress-a9 上本地验证:6 个测试单元全部 PASSED。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

action github action yml imporve Component Kernel PR has src relate code tools

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants