1039a1c42SKees Cook // SPDX-License-Identifier: GPL-2.0 2039a1c42SKees Cook /* 3039a1c42SKees Cook * This is for all the tests relating directly to heap memory, including 4039a1c42SKees Cook * page allocation and slab allocations. 5039a1c42SKees Cook */ 6039a1c42SKees Cook #include "lkdtm.h" 7039a1c42SKees Cook #include <linux/slab.h> 89c4f6ebcSKees Cook #include <linux/vmalloc.h> 9039a1c42SKees Cook #include <linux/sched.h> 10039a1c42SKees Cook 11966fede8SKees Cook static struct kmem_cache *double_free_cache; 12966fede8SKees Cook static struct kmem_cache *a_cache; 13966fede8SKees Cook static struct kmem_cache *b_cache; 14966fede8SKees Cook 15039a1c42SKees Cook /* 16e6d468d3SKees Cook * Using volatile here means the compiler cannot ever make assumptions 17e6d468d3SKees Cook * about this value. This means compile-time length checks involving 18e6d468d3SKees Cook * this variable cannot be performed; only run-time checks. 19e6d468d3SKees Cook */ 20e6d468d3SKees Cook static volatile int __offset = 1; 21e6d468d3SKees Cook 22e6d468d3SKees Cook /* 239c4f6ebcSKees Cook * If there aren't guard pages, it's likely that a consecutive allocation will 249c4f6ebcSKees Cook * let us overflow into the second allocation without overwriting something real. 25*42db2594SKees Cook * 26*42db2594SKees Cook * This should always be caught because there is an unconditional unmapped 27*42db2594SKees Cook * page after vmap allocations. 289c4f6ebcSKees Cook */ 299c4f6ebcSKees Cook void lkdtm_VMALLOC_LINEAR_OVERFLOW(void) 309c4f6ebcSKees Cook { 319c4f6ebcSKees Cook char *one, *two; 329c4f6ebcSKees Cook 339c4f6ebcSKees Cook one = vzalloc(PAGE_SIZE); 349c4f6ebcSKees Cook two = vzalloc(PAGE_SIZE); 359c4f6ebcSKees Cook 369c4f6ebcSKees Cook pr_info("Attempting vmalloc linear overflow ...\n"); 37e6d468d3SKees Cook memset(one, 0xAA, PAGE_SIZE + __offset); 389c4f6ebcSKees Cook 399c4f6ebcSKees Cook vfree(two); 409c4f6ebcSKees Cook vfree(one); 419c4f6ebcSKees Cook } 429c4f6ebcSKees Cook 439c4f6ebcSKees Cook /* 44039a1c42SKees Cook * This tries to stay within the next largest power-of-2 kmalloc cache 45039a1c42SKees Cook * to avoid actually overwriting anything important if it's not detected 46039a1c42SKees Cook * correctly. 47*42db2594SKees Cook * 48*42db2594SKees Cook * This should get caught by either memory tagging, KASan, or by using 49*42db2594SKees Cook * CONFIG_SLUB_DEBUG=y and slub_debug=ZF (or CONFIG_SLUB_DEBUG_ON=y). 50039a1c42SKees Cook */ 519c4f6ebcSKees Cook void lkdtm_SLAB_LINEAR_OVERFLOW(void) 52039a1c42SKees Cook { 53039a1c42SKees Cook size_t len = 1020; 54039a1c42SKees Cook u32 *data = kmalloc(len, GFP_KERNEL); 55039a1c42SKees Cook if (!data) 56039a1c42SKees Cook return; 57039a1c42SKees Cook 589c4f6ebcSKees Cook pr_info("Attempting slab linear overflow ...\n"); 59039a1c42SKees Cook data[1024 / sizeof(u32)] = 0x12345678; 60039a1c42SKees Cook kfree(data); 61039a1c42SKees Cook } 62039a1c42SKees Cook 63039a1c42SKees Cook void lkdtm_WRITE_AFTER_FREE(void) 64039a1c42SKees Cook { 65039a1c42SKees Cook int *base, *again; 66039a1c42SKees Cook size_t len = 1024; 67039a1c42SKees Cook /* 68039a1c42SKees Cook * The slub allocator uses the first word to store the free 69039a1c42SKees Cook * pointer in some configurations. Use the middle of the 70039a1c42SKees Cook * allocation to avoid running into the freelist 71039a1c42SKees Cook */ 72039a1c42SKees Cook size_t offset = (len / sizeof(*base)) / 2; 73039a1c42SKees Cook 74039a1c42SKees Cook base = kmalloc(len, GFP_KERNEL); 75039a1c42SKees Cook if (!base) 76039a1c42SKees Cook return; 77039a1c42SKees Cook pr_info("Allocated memory %p-%p\n", base, &base[offset * 2]); 78039a1c42SKees Cook pr_info("Attempting bad write to freed memory at %p\n", 79039a1c42SKees Cook &base[offset]); 80039a1c42SKees Cook kfree(base); 81039a1c42SKees Cook base[offset] = 0x0abcdef0; 82039a1c42SKees Cook /* Attempt to notice the overwrite. */ 83039a1c42SKees Cook again = kmalloc(len, GFP_KERNEL); 84039a1c42SKees Cook kfree(again); 85039a1c42SKees Cook if (again != base) 86039a1c42SKees Cook pr_info("Hmm, didn't get the same memory range.\n"); 87039a1c42SKees Cook } 88039a1c42SKees Cook 89039a1c42SKees Cook void lkdtm_READ_AFTER_FREE(void) 90039a1c42SKees Cook { 91039a1c42SKees Cook int *base, *val, saw; 92039a1c42SKees Cook size_t len = 1024; 93039a1c42SKees Cook /* 94e12145cfSKees Cook * The slub allocator will use the either the first word or 95e12145cfSKees Cook * the middle of the allocation to store the free pointer, 96e12145cfSKees Cook * depending on configurations. Store in the second word to 97e12145cfSKees Cook * avoid running into the freelist. 98039a1c42SKees Cook */ 99e12145cfSKees Cook size_t offset = sizeof(*base); 100039a1c42SKees Cook 101039a1c42SKees Cook base = kmalloc(len, GFP_KERNEL); 102039a1c42SKees Cook if (!base) { 103039a1c42SKees Cook pr_info("Unable to allocate base memory.\n"); 104039a1c42SKees Cook return; 105039a1c42SKees Cook } 106039a1c42SKees Cook 107039a1c42SKees Cook val = kmalloc(len, GFP_KERNEL); 108039a1c42SKees Cook if (!val) { 109039a1c42SKees Cook pr_info("Unable to allocate val memory.\n"); 110039a1c42SKees Cook kfree(base); 111039a1c42SKees Cook return; 112039a1c42SKees Cook } 113039a1c42SKees Cook 114039a1c42SKees Cook *val = 0x12345678; 115039a1c42SKees Cook base[offset] = *val; 116039a1c42SKees Cook pr_info("Value in memory before free: %x\n", base[offset]); 117039a1c42SKees Cook 118039a1c42SKees Cook kfree(base); 119039a1c42SKees Cook 120039a1c42SKees Cook pr_info("Attempting bad read from freed memory\n"); 121039a1c42SKees Cook saw = base[offset]; 122039a1c42SKees Cook if (saw != *val) { 123039a1c42SKees Cook /* Good! Poisoning happened, so declare a win. */ 124039a1c42SKees Cook pr_info("Memory correctly poisoned (%x)\n", saw); 1255b777131SKees Cook } else { 1265b777131SKees Cook pr_err("FAIL: Memory was not poisoned!\n"); 1275b777131SKees Cook pr_expected_config_param(CONFIG_INIT_ON_FREE_DEFAULT_ON, "init_on_free"); 128039a1c42SKees Cook } 129039a1c42SKees Cook 130039a1c42SKees Cook kfree(val); 131039a1c42SKees Cook } 132039a1c42SKees Cook 133039a1c42SKees Cook void lkdtm_WRITE_BUDDY_AFTER_FREE(void) 134039a1c42SKees Cook { 135039a1c42SKees Cook unsigned long p = __get_free_page(GFP_KERNEL); 136039a1c42SKees Cook if (!p) { 137039a1c42SKees Cook pr_info("Unable to allocate free page\n"); 138039a1c42SKees Cook return; 139039a1c42SKees Cook } 140039a1c42SKees Cook 141039a1c42SKees Cook pr_info("Writing to the buddy page before free\n"); 142039a1c42SKees Cook memset((void *)p, 0x3, PAGE_SIZE); 143039a1c42SKees Cook free_page(p); 144039a1c42SKees Cook schedule(); 145039a1c42SKees Cook pr_info("Attempting bad write to the buddy page after free\n"); 146039a1c42SKees Cook memset((void *)p, 0x78, PAGE_SIZE); 147039a1c42SKees Cook /* Attempt to notice the overwrite. */ 148039a1c42SKees Cook p = __get_free_page(GFP_KERNEL); 149039a1c42SKees Cook free_page(p); 150039a1c42SKees Cook schedule(); 151039a1c42SKees Cook } 152039a1c42SKees Cook 153039a1c42SKees Cook void lkdtm_READ_BUDDY_AFTER_FREE(void) 154039a1c42SKees Cook { 155039a1c42SKees Cook unsigned long p = __get_free_page(GFP_KERNEL); 156039a1c42SKees Cook int saw, *val; 157039a1c42SKees Cook int *base; 158039a1c42SKees Cook 159039a1c42SKees Cook if (!p) { 160039a1c42SKees Cook pr_info("Unable to allocate free page\n"); 161039a1c42SKees Cook return; 162039a1c42SKees Cook } 163039a1c42SKees Cook 164039a1c42SKees Cook val = kmalloc(1024, GFP_KERNEL); 165039a1c42SKees Cook if (!val) { 166039a1c42SKees Cook pr_info("Unable to allocate val memory.\n"); 167039a1c42SKees Cook free_page(p); 168039a1c42SKees Cook return; 169039a1c42SKees Cook } 170039a1c42SKees Cook 171039a1c42SKees Cook base = (int *)p; 172039a1c42SKees Cook 173039a1c42SKees Cook *val = 0x12345678; 174039a1c42SKees Cook base[0] = *val; 175039a1c42SKees Cook pr_info("Value in memory before free: %x\n", base[0]); 176039a1c42SKees Cook free_page(p); 177039a1c42SKees Cook pr_info("Attempting to read from freed memory\n"); 178039a1c42SKees Cook saw = base[0]; 179039a1c42SKees Cook if (saw != *val) { 180039a1c42SKees Cook /* Good! Poisoning happened, so declare a win. */ 181039a1c42SKees Cook pr_info("Memory correctly poisoned (%x)\n", saw); 1825b777131SKees Cook } else { 1835b777131SKees Cook pr_err("FAIL: Buddy page was not poisoned!\n"); 1845b777131SKees Cook pr_expected_config_param(CONFIG_INIT_ON_FREE_DEFAULT_ON, "init_on_free"); 185039a1c42SKees Cook } 186039a1c42SKees Cook 187039a1c42SKees Cook kfree(val); 188039a1c42SKees Cook } 189966fede8SKees Cook 19037a0ca7fSKees Cook void lkdtm_SLAB_INIT_ON_ALLOC(void) 19137a0ca7fSKees Cook { 19237a0ca7fSKees Cook u8 *first; 19337a0ca7fSKees Cook u8 *val; 19437a0ca7fSKees Cook 19537a0ca7fSKees Cook first = kmalloc(512, GFP_KERNEL); 19637a0ca7fSKees Cook if (!first) { 19737a0ca7fSKees Cook pr_info("Unable to allocate 512 bytes the first time.\n"); 19837a0ca7fSKees Cook return; 19937a0ca7fSKees Cook } 20037a0ca7fSKees Cook 20137a0ca7fSKees Cook memset(first, 0xAB, 512); 20237a0ca7fSKees Cook kfree(first); 20337a0ca7fSKees Cook 20437a0ca7fSKees Cook val = kmalloc(512, GFP_KERNEL); 20537a0ca7fSKees Cook if (!val) { 20637a0ca7fSKees Cook pr_info("Unable to allocate 512 bytes the second time.\n"); 20737a0ca7fSKees Cook return; 20837a0ca7fSKees Cook } 20937a0ca7fSKees Cook if (val != first) { 21037a0ca7fSKees Cook pr_warn("Reallocation missed clobbered memory.\n"); 21137a0ca7fSKees Cook } 21237a0ca7fSKees Cook 21337a0ca7fSKees Cook if (memchr(val, 0xAB, 512) == NULL) { 21437a0ca7fSKees Cook pr_info("Memory appears initialized (%x, no earlier values)\n", *val); 21537a0ca7fSKees Cook } else { 21637a0ca7fSKees Cook pr_err("FAIL: Slab was not initialized\n"); 21737a0ca7fSKees Cook pr_expected_config_param(CONFIG_INIT_ON_ALLOC_DEFAULT_ON, "init_on_alloc"); 21837a0ca7fSKees Cook } 21937a0ca7fSKees Cook kfree(val); 22037a0ca7fSKees Cook } 22137a0ca7fSKees Cook 22237a0ca7fSKees Cook void lkdtm_BUDDY_INIT_ON_ALLOC(void) 22337a0ca7fSKees Cook { 22437a0ca7fSKees Cook u8 *first; 22537a0ca7fSKees Cook u8 *val; 22637a0ca7fSKees Cook 22737a0ca7fSKees Cook first = (u8 *)__get_free_page(GFP_KERNEL); 22837a0ca7fSKees Cook if (!first) { 22937a0ca7fSKees Cook pr_info("Unable to allocate first free page\n"); 23037a0ca7fSKees Cook return; 23137a0ca7fSKees Cook } 23237a0ca7fSKees Cook 23337a0ca7fSKees Cook memset(first, 0xAB, PAGE_SIZE); 23437a0ca7fSKees Cook free_page((unsigned long)first); 23537a0ca7fSKees Cook 23637a0ca7fSKees Cook val = (u8 *)__get_free_page(GFP_KERNEL); 23737a0ca7fSKees Cook if (!val) { 23837a0ca7fSKees Cook pr_info("Unable to allocate second free page\n"); 23937a0ca7fSKees Cook return; 24037a0ca7fSKees Cook } 24137a0ca7fSKees Cook 24237a0ca7fSKees Cook if (val != first) { 24337a0ca7fSKees Cook pr_warn("Reallocation missed clobbered memory.\n"); 24437a0ca7fSKees Cook } 24537a0ca7fSKees Cook 24637a0ca7fSKees Cook if (memchr(val, 0xAB, PAGE_SIZE) == NULL) { 24737a0ca7fSKees Cook pr_info("Memory appears initialized (%x, no earlier values)\n", *val); 24837a0ca7fSKees Cook } else { 24937a0ca7fSKees Cook pr_err("FAIL: Slab was not initialized\n"); 25037a0ca7fSKees Cook pr_expected_config_param(CONFIG_INIT_ON_ALLOC_DEFAULT_ON, "init_on_alloc"); 25137a0ca7fSKees Cook } 25237a0ca7fSKees Cook free_page((unsigned long)val); 25337a0ca7fSKees Cook } 25437a0ca7fSKees Cook 255966fede8SKees Cook void lkdtm_SLAB_FREE_DOUBLE(void) 256966fede8SKees Cook { 257966fede8SKees Cook int *val; 258966fede8SKees Cook 259966fede8SKees Cook val = kmem_cache_alloc(double_free_cache, GFP_KERNEL); 260966fede8SKees Cook if (!val) { 261966fede8SKees Cook pr_info("Unable to allocate double_free_cache memory.\n"); 262966fede8SKees Cook return; 263966fede8SKees Cook } 264966fede8SKees Cook 265966fede8SKees Cook /* Just make sure we got real memory. */ 266966fede8SKees Cook *val = 0x12345678; 267966fede8SKees Cook pr_info("Attempting double slab free ...\n"); 268966fede8SKees Cook kmem_cache_free(double_free_cache, val); 269966fede8SKees Cook kmem_cache_free(double_free_cache, val); 270966fede8SKees Cook } 271966fede8SKees Cook 272966fede8SKees Cook void lkdtm_SLAB_FREE_CROSS(void) 273966fede8SKees Cook { 274966fede8SKees Cook int *val; 275966fede8SKees Cook 276966fede8SKees Cook val = kmem_cache_alloc(a_cache, GFP_KERNEL); 277966fede8SKees Cook if (!val) { 278966fede8SKees Cook pr_info("Unable to allocate a_cache memory.\n"); 279966fede8SKees Cook return; 280966fede8SKees Cook } 281966fede8SKees Cook 282966fede8SKees Cook /* Just make sure we got real memory. */ 283966fede8SKees Cook *val = 0x12345679; 284966fede8SKees Cook pr_info("Attempting cross-cache slab free ...\n"); 285966fede8SKees Cook kmem_cache_free(b_cache, val); 286966fede8SKees Cook } 287966fede8SKees Cook 288966fede8SKees Cook void lkdtm_SLAB_FREE_PAGE(void) 289966fede8SKees Cook { 290966fede8SKees Cook unsigned long p = __get_free_page(GFP_KERNEL); 291966fede8SKees Cook 292966fede8SKees Cook pr_info("Attempting non-Slab slab free ...\n"); 293966fede8SKees Cook kmem_cache_free(NULL, (void *)p); 294966fede8SKees Cook free_page(p); 295966fede8SKees Cook } 296966fede8SKees Cook 297966fede8SKees Cook /* 298966fede8SKees Cook * We have constructors to keep the caches distinctly separated without 299966fede8SKees Cook * needing to boot with "slab_nomerge". 300966fede8SKees Cook */ 301966fede8SKees Cook static void ctor_double_free(void *region) 302966fede8SKees Cook { } 303966fede8SKees Cook static void ctor_a(void *region) 304966fede8SKees Cook { } 305966fede8SKees Cook static void ctor_b(void *region) 306966fede8SKees Cook { } 307966fede8SKees Cook 308966fede8SKees Cook void __init lkdtm_heap_init(void) 309966fede8SKees Cook { 310966fede8SKees Cook double_free_cache = kmem_cache_create("lkdtm-heap-double_free", 311966fede8SKees Cook 64, 0, 0, ctor_double_free); 312966fede8SKees Cook a_cache = kmem_cache_create("lkdtm-heap-a", 64, 0, 0, ctor_a); 313966fede8SKees Cook b_cache = kmem_cache_create("lkdtm-heap-b", 64, 0, 0, ctor_b); 314966fede8SKees Cook } 315966fede8SKees Cook 316966fede8SKees Cook void __exit lkdtm_heap_exit(void) 317966fede8SKees Cook { 318966fede8SKees Cook kmem_cache_destroy(double_free_cache); 319966fede8SKees Cook kmem_cache_destroy(a_cache); 320966fede8SKees Cook kmem_cache_destroy(b_cache); 321966fede8SKees Cook } 322