106 lines
4.4 KiB
ReStructuredText
106 lines
4.4 KiB
ReStructuredText
|
====================================
|
||
|
The Kernel Address Sanitizer (KASAN)
|
||
|
====================================
|
||
|
|
||
|
Overview
|
||
|
--------
|
||
|
|
||
|
Kernel Address Sanitizer (KASAN) is a dynamic memory safety error detector
|
||
|
designed to find out-of-bounds and use-after-free bugs.
|
||
|
|
||
|
The current version of NuttX has one modes:
|
||
|
|
||
|
1. Generic KASAN
|
||
|
|
||
|
Generic KASAN, enabled with CONFIG_MM_KASAN, is the mode intended for
|
||
|
debugging, similar to linux user level ASan. This mode is supported on many CPU
|
||
|
architectures, but it has significant performance and memory overheads.
|
||
|
The current NuttX Generic KASAN can support memory out of bounds detection
|
||
|
allocated by the default NuttX heap allocator,which depends on CONFIG_MM_DEFAULT_MANAGER
|
||
|
or CONFIG_MM_TLSF_MANAGER, and detection of out of bounds with global variables.
|
||
|
|
||
|
Support
|
||
|
-------
|
||
|
|
||
|
Architectures
|
||
|
~~~~~~~~~~~~~
|
||
|
|
||
|
Generic KASAN is supported on x86_64, arm, arm64, riscv, xtensa and so on.
|
||
|
|
||
|
Usage
|
||
|
-----
|
||
|
|
||
|
To enable Generic KASAN, configure the kernel with::
|
||
|
CONFIG_MM_KASAN=y
|
||
|
CONFIG_MM_KASAN_ALL=y
|
||
|
|
||
|
If you want to enable global variable out of bounds detection,
|
||
|
you can add configurations based on the above::
|
||
|
CONFIG_MM_KASAN_GLOBAL=y
|
||
|
|
||
|
Implementation details
|
||
|
----------------------
|
||
|
|
||
|
Compile with param -fsanitize=kernel-address,
|
||
|
Compile-time instrumentation is used to insert memory access checks. Compiler
|
||
|
inserts function calls (``__asan_load*(addr)``, ``__asan_store*(addr)``) before
|
||
|
each memory access of size 1, 2, 4, 8, or 16. These functions check whether
|
||
|
memory accesses are valid or not by checking corresponding shadow memory.
|
||
|
|
||
|
It is slightly different from Linux.
|
||
|
On the one hand, in terms of the source of the shadow area;
|
||
|
NuttX's shadow area comes from the end of each heap. During heap initialization,
|
||
|
it is offset and a kasan region is shaped at the end.
|
||
|
Regions between multiple heaps are concatenated using a linked list.
|
||
|
|
||
|
Secondly, in order to save more memory consumption,
|
||
|
the implementation of NuttX adopts a bitmap detection method;
|
||
|
For example, in the case of a 32-bit machine,
|
||
|
if the NuttX heap allocator allocates four bytes of memory to it,
|
||
|
the kasan module will allocate a shadow area of one bit per unit of
|
||
|
memory group on a four byte basis. If the shadow area is 0,
|
||
|
the memory group can be accessed, otherwise 1 is inaccessible
|
||
|
|
||
|
Thirdly, the implementation of global variable out of bounds detection
|
||
|
for this NuttX is also different from Linux.
|
||
|
Due to the particularity of the shadow region, NuttX needs to construct kasan regions
|
||
|
separately for the data and bss segments where the global variable is located.
|
||
|
Before compiling, add the compile option '--param asan-globals=1'.
|
||
|
In this way, the compiler will store all global variable information in this special sections,
|
||
|
'.data..LASAN0', These two segments store information about all global variables
|
||
|
and can be parsed using the following structure::
|
||
|
|
||
|
struct kasan_global {
|
||
|
const void *beg; /* Address of the beginning of the global variable. */
|
||
|
size_t size; /* Size of the global variable. */
|
||
|
size_t size_with_redzone; /* Size of the variable + size of the redzone. 32 bytes aligned. */
|
||
|
const void *name;
|
||
|
const void *module_name; /* Name of the module where the global variable is declared. */
|
||
|
unsigned long has_dynamic_init; /* This is needed for C++. */
|
||
|
|
||
|
/* It will point to a location that stores the file row,
|
||
|
* column, and file name information of each global variable */
|
||
|
|
||
|
struct kasan_source_location *location;
|
||
|
char *odr_indicator;
|
||
|
};
|
||
|
|
||
|
In order to reduce the amount of data generated by the compiler occupying the already precious flash space.
|
||
|
NuttX's approach is to use multiple links to extract the global variable information in elf through scripts,
|
||
|
construct the region and shadow of the global variables according to the rules of kasan region,
|
||
|
form an array, and finally link it to the program. The program concatenates the array to kasan's region linked list.
|
||
|
|
||
|
The data generated by the compiler will be placed in a non-existent memory block.
|
||
|
After the compilation is completed, this segment will be deleted
|
||
|
and will not be copied to the bin file of the final burned board.
|
||
|
|
||
|
For developers
|
||
|
--------------
|
||
|
|
||
|
Ignoring accesses
|
||
|
~~~~~~~~~~~~~~~~~
|
||
|
|
||
|
If you want the module you are writing to not be inserted by the compiler,
|
||
|
you can add the option 'CFLAGS += -fno-sanitize=kernel-address' to a single module.
|
||
|
If it is a file, you can write it this way, special_file.o: CFLAGS = -fno-sanitize=kernel-address
|