Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .github/utest/configs/components/asan.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# dependencies
CONFIG_RT_CONSOLEBUF_SIZE=1024
CONFIG_RT_USING_CI_ACTION=y

CONFIG_RT_USING_ASAN=y
CONFIG_RT_ASAN_SHADOW_SIZE=65536
CONFIG_RT_ASAN_TRACK_MAX=512
CONFIG_RT_UTEST_ASAN=y
2 changes: 2 additions & 0 deletions .github/workflows/utest_auto_run.yml
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,8 @@ jobs:
config_file: "components/dfs.cfg"
- platform: { UTEST: "A9", RTT_BSP: "bsp/qemu-vexpress-a9", QEMU_ARCH: "arm", QEMU_MACHINE: "vexpress-a9", SD_FILE: "sd.bin", KERNEL: "standard", "SMP_RUN":"" }
config_file: "components/libc.cfg"
- platform: { UTEST: "A9", RTT_BSP: "bsp/qemu-vexpress-a9", QEMU_ARCH: "arm", QEMU_MACHINE: "vexpress-a9", SD_FILE: "sd.bin", KERNEL: "standard", "SMP_RUN":"" }
config_file: "components/asan.cfg"

env:
TEST_QEMU_ARCH: ${{ matrix.platform.QEMU_ARCH }}
Expand Down
1 change: 1 addition & 0 deletions components/utilities/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -244,5 +244,6 @@ config RT_USING_RESOURCE_ID

rsource "libadt/Kconfig"
rsource "rt-link/Kconfig"
rsource "asan/Kconfig"

endmenu
56 changes: 56 additions & 0 deletions components/utilities/asan/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
menuconfig RT_USING_ASAN
bool "Enable AddressSanitizer (heap overflow & use-after-free check)"
default n
depends on RT_USING_HOOK && RT_HOOK_USING_FUNC_PTR && !RT_USING_USERHEAP
help
Enable runtime AddressSanitizer (kernel-address) support. It
instruments memory accesses to detect heap buffer overflow and
use-after-free at runtime.

It requires the toolchain to support '-fsanitize=kernel-address'
(GCC 8+, verified on ARM and RISC-V).

The shadow memory is a static array of RT_ASAN_SHADOW_SIZE bytes
and covers the first RT_ASAN_SHADOW_SIZE * 8 bytes of the heap.
Accesses beyond that range are not checked.

Heap algorithm support:
- small mem (RT_USING_SMALL_MEM_AS_HEAP): full support, detects
both heap-buffer-overflow and use-after-free.
- slab (RT_USING_SLAB_AS_HEAP) and memheap
(RT_USING_MEMHEAP_AS_HEAP): detects heap-buffer-overflow only.
Their allocators reuse freed blocks for internal metadata written
through instrumented rt_memset/rt_memcpy, so poisoning a whole
freed block would raise false positives; use-after-free is
therefore disabled for these two.
- userheap (RT_USING_USERHEAP): not supported (mutually exclusive).

if RT_USING_ASAN
config RT_ASAN_SHADOW_SIZE
int "ASan shadow memory size (bytes)"
default 65536
help
Size of the static shadow memory array. Each byte maps 8
bytes of the heap, so the checked heap range is
RT_ASAN_SHADOW_SIZE * 8 bytes.

config RT_ASAN_TRACK_MAX
int "Max number of tracked active allocations"
default 512
help
Size of the allocation tracking table. Each entry records
one live block (ptr, size, owner thread). Reduce this on
memory-constrained MCUs (e.g. 128 or 64). When the table
is full, further allocations are not tracked (and thus not
diagnosed) but are still unpoisoned for correctness.

config RT_ASAN_BACKTRACE
bool "Print full backtrace on report"
default y
help
When a violation is reported, also dump the full call stack
of the faulting thread via rt_backtrace(). This requires the
target architecture to implement a backtrace backend (unwind
table or frame pointer chain). Architectures without one
print nothing extra.
endif
13 changes: 13 additions & 0 deletions components/utilities/asan/SConscript
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from building import *

cwd = GetCurrentDir()
src = Glob('*.c')
CPPPATH = [cwd]

# The ASan runtime itself must not be instrumented, otherwise it would
# recurse infinitely. '-fno-sanitize=kernel-address' is appended after the
# global '-fsanitize=kernel-address' and therefore overrides it.
group = DefineGroup('asan', src, depend=['RT_USING_ASAN'], CPPPATH=CPPPATH,
LOCAL_CFLAGS=' -fno-sanitize=kernel-address')

Return('group')
Loading
Loading