How KASAN Detects Kernel Memory Errors: Out‑of‑Bounds, Use‑After‑Free, and Double‑Free Explained
This article explains KASAN (Kernel Address Sanitizer), its integration in the Linux kernel, the shadow‑memory technique it uses, and demonstrates how it catches out‑of‑bounds accesses, use‑after‑free and double‑free bugs with detailed log analysis and GDB debugging steps.
KASAN (Kernel Address Sanitizer) is a dynamic memory‑error detector built into the Linux kernel that can identify out‑of‑bounds accesses, use‑after‑free, and double‑free bugs.
It originates from LLVM’s sanitizers (AddressSanitizer, MemorySanitizer, ThreadSanitizer, LeakSanitizer) but extends their capabilities to kernel space by adding a shadow memory region where each 8 bytes of real memory are represented by one byte indicating its state. This shadow region consumes roughly one‑ninth of total memory (1 : 8 ratio).
The article defines the fill‑value constants used by KASAN (e.g., #define KASAN_FREE_PAGE 0xFF, #define KASAN_GLOBAL_REDZONE 0xFA) and shows the required kernel configuration options ( CONFIG_HAVE_ARCH_KASAN=y, CONFIG_KASAN=y).
Several test functions illustrate typical error types:
Out‑of‑bounds accesses ( kmalloc_oob_right, kmalloc_oob_left, etc.)
Use‑after‑free ( kmalloc_uaf, kmalloc_uaf_memset, kmalloc_uaf2)
Double‑free ( kmalloc_double_free_test)
For each case the kernel log output is shown, highlighting the KASAN BUG line, call trace, memory dump, and the exact buggy address. The logs demonstrate how KASAN reports the type of violation, the offending function, and the surrounding memory state.
Analysis sections explain how to interpret the logs, locate the buggy address, and use GDB with symbol information to view the source line that triggered the error. Example GDB commands ( list *kmalloc_oob_right+0x7c, list *kmalloc_uaf+0x84, etc.) are provided.
#define KASAN_FREE_PAGE 0xFF /* page was freed */
#define KASAN_PAGE_REDZONE 0xFE /* redzone for kmalloc_large allocations */
#define KASAN_KMALLOC_REDZONE 0xFC /* redzone inside slub object */
#define KASAN_KMALLOC_FREE 0xFB /* object was freed (kmem_cache_free/kfree) */
#define KASAN_GLOBAL_REDZONE 0xFA /* redzone for global variable */
static noinline void __init kmalloc_oob_right(void)
{
char *ptr;
size_t size = 123;
pr_info("out-of-bounds to right
");
ptr = kmalloc(size, GFP_KERNEL);
if (!ptr)
return;
ptr[size] = 'x';
kfree(ptr);
}
static noinline void __init kmalloc_uaf(void)
{
char *ptr;
size_t size = 10;
pr_info("use-after-free
");
ptr = kmalloc(size, GFP_KERNEL);
if (!ptr)
return;
kfree(ptr);
*(ptr + 8) = 'x';
}
static noinline void __init kmalloc_double_free_test(void)
{
char *ptr;
size_t size = 123;
pr_info("double-free
");
ptr = kmalloc(size, GFP_KERNEL);
if (!ptr)
return;
kfree(ptr);
kfree(ptr);
}The article also includes a diagram illustrating the shadow memory layout:
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Open Source Linux
Focused on sharing Linux/Unix content, covering fundamentals, system development, network programming, automation/operations, cloud computing, and related professional knowledge.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
