@@ -10,13 +10,9 @@ report an error if the accessed address is poisoned. See Clang's
1010[ AddressSanitizer documentation] ( https://clang.llvm.org/docs/AddressSanitizer.html )
1111for more detail on the sanitizer model.
1212
13- The Makefile reserves the last 2 KiB of RAM for shadow memory. It uses Python
14- to calculate the shadow start, end, size, and offset from the RAM origin, total
15- RAM size, and KASan shadow scale. It passes the calculated offset to Clang's
16- ` -asan-mapping-offset ` and the KASan runtime, and passes the full memory map to
17- the linker with ` -Wl,--defsym ` , so the application RAM maps into the reserved
18- shadow region without moving the normal RAM origin. The remaining RAM is
19- exposed to the selected C library for data, heap, and stack.
13+ The Makefile reserves the last 2 KB of RAM for shadow memory. It calculates the
14+ shadow memory layout based on provided target memory map. The remaining RAM is
15+ exposed to the C library for data, heap, and stack.
2016
2117## Build and run
2218
@@ -31,58 +27,70 @@ exposed to the selected C library for data, heap, and stack.
3127
3228## Customizing the runtime
3329
30+ ### Shadow memory
31+
3432The shadow memory runtime is sensitive to the target memory map. If the RAM
3533origin or RAM size changes, override ` RAM_ORIGIN ` or ` HW_RAM_SIZE ` when
3634invoking ` make ` , for example:
37- ` make run RAM_ORIGIN=<origin> HW_RAM_SIZE=<size> ` . The Makefile
38- recalculates ` KASAN_SHADOW_OFFSET ` from those values. If the shadow placement
39- policy changes, update the Makefile calculation and ` KASAN_MEMORY_MAP ` symbols
40- together, because Clang's instrumentation, the runtime, and the linker must all
41- use the same ` shadow = (address >> 3) + offset ` mapping. Keep the Makefile
42- memory-map variables as the source of truth for which application regions are
43- actually covered.
44-
45- Tune heap checking by changing ` KASAN_HEAP_REDZONE_SIZE ` and the quarantine
46- policy. The sample keeps freed blocks poisoned forever so use-after-free is
47- reliable in a demo; a practical runtime should use a bounded quarantine or
48- return old blocks to the allocator once the diagnostic value is no longer worth
49- the RAM cost. Keep the runtime and allocator wrappers unsanitized, otherwise the
50- reporting path can recursively instrument itself.
51-
52- The reporting path avoids ` printf ` and formats messages through weak output
35+ ` make run RAM_ORIGIN=<origin> HW_RAM_SIZE=<size> ` .
36+ The Makefile calculates ` KASAN_SHADOW_OFFSET ` from those values.
37+
38+ ### Heap
39+
40+ The sample keeps recently freed blocks in a bounded quarantine queue so
41+ use-after-free remains detectable. When the quarantine is full, the oldest
42+ poisoned block is returned to the real allocator.
43+
44+ Use ` make KASAN_HEAP_QUARANTINE_SIZE=<n> ` to change the
45+ number of retained freed blocks, or ` 0 ` to disable quarantine and free blocks
46+ immediately.
47+
48+ ### Redirecting messages
49+
50+ Error reporting avoids ` printf ` and formats messages through weak output
5351hooks. The default ` kasan_rt_putc ` implementation uses libc ` putc ` , while
54- ` kasan_rt_puts ` and ` kasan_rt_putaddr ` build on top of it. A target can redirect
55- reports by defining its own non-weak hooks, usually just ` kasan_rt_putc ` :
52+ ` kasan_rt_puts ` , ` kasan_rt_putaddr ` , and ` kasan_rt_putsize ` build on top of it.
53+
54+ A target can redirect reports by defining its own non-weak hooks, usually just
55+ ` kasan_rt_putc ` :
5656
5757``` cpp
58+ #include " kasan_shadow_runtime.h"
59+
5860extern "C" void kasan_rt_putc(char c) {
5961 // Write c to UART, ITM/SWO, retained RAM, or another target-specific sink.
6062}
6163```
6264
63- The runtime provides weak report handlers, `kasan_rt_report_access` and
64- `kasan_rt_report_alloc_error`. The default handlers print a report and abort.
65- This sample overrides them in `hello.cpp` with unsanitized handlers (to avoid
66- infinite recursion) that print `(recovered)` and return, so every demo can run
67- in one process:
65+ ### Error reporting and recovery
66+
67+ The runtime provides weak report handlers: `kasan_rt_report_access`,
68+ `kasan_rt_report_alloc_error`, and `kasan_rt_report_shadow_update_error`. The
69+ default handlers print a report and abort.
70+
71+ This sample overrides the access and allocator handlers in `hello.cpp` to print
72+ `(recovered)` and return, so every demo can run in one process:
6873
6974```cpp
75+ #include "kasan_shadow_runtime.h"
76+
77+ // Handlers must be unsanitized to avoid infinite recursion
7078extern "C" __attribute__((no_sanitize("kernel-address"))) void
71- kasan_rt_report_access(const char *kind, uintptr_t addr, uintptr_t size) {
79+ kasan_rt_report_access(const char *kind, uintptr_t addr, size_t size,
80+ size_t offset) {
7281 // Report the access and return to recover, or abort to stop.
7382}
7483```
7584
76- C code does not need the `extern "C"` wrapper. Keep these hooks small and avoid
77- allocating memory from them, because they run after KASan has found memory
78- corruption. Returning from a report handler allows the invalid access to
79- continue , so recovery is useful for diagnostics but is not a safe production
80- policy. Add symbolization only if the target has enough storage and the extra
81- report detail is worth the code-size cost.
85+ Avoid allocating memory in these hooks, because they run after KASan has found
86+ memory corruption.
87+
88+ Returning from a report handler allows the invalid access to continue : recovery
89+ is useful for diagnostics but is not a safe in production.
8290
8391## Limitations
8492
85- Dynamic stack allocations remain disabled with
93+ Dynamic stack allocations are disabled with
8694`-mllvm -asan-instrument-dynamic-allocas=0 ` to keep the runtime small.
8795
8896The reserved shadow memory covers the application RAM range only. Stack, heap,
0 commit comments