1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * This is for all the tests relating directly to heap memory, including 4 * page allocation and slab allocations. 5 */ 6 #include "lkdtm.h" 7 #include <linux/slab.h> 8 #include <linux/sched.h> 9 10 /* 11 * This tries to stay within the next largest power-of-2 kmalloc cache 12 * to avoid actually overwriting anything important if it's not detected 13 * correctly. 14 */ 15 void lkdtm_OVERWRITE_ALLOCATION(void) 16 { 17 size_t len = 1020; 18 u32 *data = kmalloc(len, GFP_KERNEL); 19 if (!data) 20 return; 21 22 data[1024 / sizeof(u32)] = 0x12345678; 23 kfree(data); 24 } 25 26 void lkdtm_WRITE_AFTER_FREE(void) 27 { 28 int *base, *again; 29 size_t len = 1024; 30 /* 31 * The slub allocator uses the first word to store the free 32 * pointer in some configurations. Use the middle of the 33 * allocation to avoid running into the freelist 34 */ 35 size_t offset = (len / sizeof(*base)) / 2; 36 37 base = kmalloc(len, GFP_KERNEL); 38 if (!base) 39 return; 40 pr_info("Allocated memory %p-%p\n", base, &base[offset * 2]); 41 pr_info("Attempting bad write to freed memory at %p\n", 42 &base[offset]); 43 kfree(base); 44 base[offset] = 0x0abcdef0; 45 /* Attempt to notice the overwrite. */ 46 again = kmalloc(len, GFP_KERNEL); 47 kfree(again); 48 if (again != base) 49 pr_info("Hmm, didn't get the same memory range.\n"); 50 } 51 52 void lkdtm_READ_AFTER_FREE(void) 53 { 54 int *base, *val, saw; 55 size_t len = 1024; 56 /* 57 * The slub allocator uses the first word to store the free 58 * pointer in some configurations. Use the middle of the 59 * allocation to avoid running into the freelist 60 */ 61 size_t offset = (len / sizeof(*base)) / 2; 62 63 base = kmalloc(len, GFP_KERNEL); 64 if (!base) { 65 pr_info("Unable to allocate base memory.\n"); 66 return; 67 } 68 69 val = kmalloc(len, GFP_KERNEL); 70 if (!val) { 71 pr_info("Unable to allocate val memory.\n"); 72 kfree(base); 73 return; 74 } 75 76 *val = 0x12345678; 77 base[offset] = *val; 78 pr_info("Value in memory before free: %x\n", base[offset]); 79 80 kfree(base); 81 82 pr_info("Attempting bad read from freed memory\n"); 83 saw = base[offset]; 84 if (saw != *val) { 85 /* Good! Poisoning happened, so declare a win. */ 86 pr_info("Memory correctly poisoned (%x)\n", saw); 87 BUG(); 88 } 89 pr_info("Memory was not poisoned\n"); 90 91 kfree(val); 92 } 93 94 void lkdtm_WRITE_BUDDY_AFTER_FREE(void) 95 { 96 unsigned long p = __get_free_page(GFP_KERNEL); 97 if (!p) { 98 pr_info("Unable to allocate free page\n"); 99 return; 100 } 101 102 pr_info("Writing to the buddy page before free\n"); 103 memset((void *)p, 0x3, PAGE_SIZE); 104 free_page(p); 105 schedule(); 106 pr_info("Attempting bad write to the buddy page after free\n"); 107 memset((void *)p, 0x78, PAGE_SIZE); 108 /* Attempt to notice the overwrite. */ 109 p = __get_free_page(GFP_KERNEL); 110 free_page(p); 111 schedule(); 112 } 113 114 void lkdtm_READ_BUDDY_AFTER_FREE(void) 115 { 116 unsigned long p = __get_free_page(GFP_KERNEL); 117 int saw, *val; 118 int *base; 119 120 if (!p) { 121 pr_info("Unable to allocate free page\n"); 122 return; 123 } 124 125 val = kmalloc(1024, GFP_KERNEL); 126 if (!val) { 127 pr_info("Unable to allocate val memory.\n"); 128 free_page(p); 129 return; 130 } 131 132 base = (int *)p; 133 134 *val = 0x12345678; 135 base[0] = *val; 136 pr_info("Value in memory before free: %x\n", base[0]); 137 free_page(p); 138 pr_info("Attempting to read from freed memory\n"); 139 saw = base[0]; 140 if (saw != *val) { 141 /* Good! Poisoning happened, so declare a win. */ 142 pr_info("Memory correctly poisoned (%x)\n", saw); 143 BUG(); 144 } 145 pr_info("Buddy page was not poisoned\n"); 146 147 kfree(val); 148 } 149