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/vmalloc.h> 9 #include <linux/sched.h> 10 11 static struct kmem_cache *double_free_cache; 12 static struct kmem_cache *a_cache; 13 static struct kmem_cache *b_cache; 14 15 /* 16 * If there aren't guard pages, it's likely that a consecutive allocation will 17 * let us overflow into the second allocation without overwriting something real. 18 */ 19 void lkdtm_VMALLOC_LINEAR_OVERFLOW(void) 20 { 21 char *one, *two; 22 23 one = vzalloc(PAGE_SIZE); 24 two = vzalloc(PAGE_SIZE); 25 26 pr_info("Attempting vmalloc linear overflow ...\n"); 27 memset(one, 0xAA, PAGE_SIZE + 1); 28 29 vfree(two); 30 vfree(one); 31 } 32 33 /* 34 * This tries to stay within the next largest power-of-2 kmalloc cache 35 * to avoid actually overwriting anything important if it's not detected 36 * correctly. 37 */ 38 void lkdtm_SLAB_LINEAR_OVERFLOW(void) 39 { 40 size_t len = 1020; 41 u32 *data = kmalloc(len, GFP_KERNEL); 42 if (!data) 43 return; 44 45 pr_info("Attempting slab linear overflow ...\n"); 46 data[1024 / sizeof(u32)] = 0x12345678; 47 kfree(data); 48 } 49 50 void lkdtm_WRITE_AFTER_FREE(void) 51 { 52 int *base, *again; 53 size_t len = 1024; 54 /* 55 * The slub allocator uses the first word to store the free 56 * pointer in some configurations. Use the middle of the 57 * allocation to avoid running into the freelist 58 */ 59 size_t offset = (len / sizeof(*base)) / 2; 60 61 base = kmalloc(len, GFP_KERNEL); 62 if (!base) 63 return; 64 pr_info("Allocated memory %p-%p\n", base, &base[offset * 2]); 65 pr_info("Attempting bad write to freed memory at %p\n", 66 &base[offset]); 67 kfree(base); 68 base[offset] = 0x0abcdef0; 69 /* Attempt to notice the overwrite. */ 70 again = kmalloc(len, GFP_KERNEL); 71 kfree(again); 72 if (again != base) 73 pr_info("Hmm, didn't get the same memory range.\n"); 74 } 75 76 void lkdtm_READ_AFTER_FREE(void) 77 { 78 int *base, *val, saw; 79 size_t len = 1024; 80 /* 81 * The slub allocator will use the either the first word or 82 * the middle of the allocation to store the free pointer, 83 * depending on configurations. Store in the second word to 84 * avoid running into the freelist. 85 */ 86 size_t offset = sizeof(*base); 87 88 base = kmalloc(len, GFP_KERNEL); 89 if (!base) { 90 pr_info("Unable to allocate base memory.\n"); 91 return; 92 } 93 94 val = kmalloc(len, GFP_KERNEL); 95 if (!val) { 96 pr_info("Unable to allocate val memory.\n"); 97 kfree(base); 98 return; 99 } 100 101 *val = 0x12345678; 102 base[offset] = *val; 103 pr_info("Value in memory before free: %x\n", base[offset]); 104 105 kfree(base); 106 107 pr_info("Attempting bad read from freed memory\n"); 108 saw = base[offset]; 109 if (saw != *val) { 110 /* Good! Poisoning happened, so declare a win. */ 111 pr_info("Memory correctly poisoned (%x)\n", saw); 112 } else { 113 pr_err("FAIL: Memory was not poisoned!\n"); 114 pr_expected_config_param(CONFIG_INIT_ON_FREE_DEFAULT_ON, "init_on_free"); 115 } 116 117 kfree(val); 118 } 119 120 void lkdtm_WRITE_BUDDY_AFTER_FREE(void) 121 { 122 unsigned long p = __get_free_page(GFP_KERNEL); 123 if (!p) { 124 pr_info("Unable to allocate free page\n"); 125 return; 126 } 127 128 pr_info("Writing to the buddy page before free\n"); 129 memset((void *)p, 0x3, PAGE_SIZE); 130 free_page(p); 131 schedule(); 132 pr_info("Attempting bad write to the buddy page after free\n"); 133 memset((void *)p, 0x78, PAGE_SIZE); 134 /* Attempt to notice the overwrite. */ 135 p = __get_free_page(GFP_KERNEL); 136 free_page(p); 137 schedule(); 138 } 139 140 void lkdtm_READ_BUDDY_AFTER_FREE(void) 141 { 142 unsigned long p = __get_free_page(GFP_KERNEL); 143 int saw, *val; 144 int *base; 145 146 if (!p) { 147 pr_info("Unable to allocate free page\n"); 148 return; 149 } 150 151 val = kmalloc(1024, GFP_KERNEL); 152 if (!val) { 153 pr_info("Unable to allocate val memory.\n"); 154 free_page(p); 155 return; 156 } 157 158 base = (int *)p; 159 160 *val = 0x12345678; 161 base[0] = *val; 162 pr_info("Value in memory before free: %x\n", base[0]); 163 free_page(p); 164 pr_info("Attempting to read from freed memory\n"); 165 saw = base[0]; 166 if (saw != *val) { 167 /* Good! Poisoning happened, so declare a win. */ 168 pr_info("Memory correctly poisoned (%x)\n", saw); 169 } else { 170 pr_err("FAIL: Buddy page was not poisoned!\n"); 171 pr_expected_config_param(CONFIG_INIT_ON_FREE_DEFAULT_ON, "init_on_free"); 172 } 173 174 kfree(val); 175 } 176 177 void lkdtm_SLAB_FREE_DOUBLE(void) 178 { 179 int *val; 180 181 val = kmem_cache_alloc(double_free_cache, GFP_KERNEL); 182 if (!val) { 183 pr_info("Unable to allocate double_free_cache memory.\n"); 184 return; 185 } 186 187 /* Just make sure we got real memory. */ 188 *val = 0x12345678; 189 pr_info("Attempting double slab free ...\n"); 190 kmem_cache_free(double_free_cache, val); 191 kmem_cache_free(double_free_cache, val); 192 } 193 194 void lkdtm_SLAB_FREE_CROSS(void) 195 { 196 int *val; 197 198 val = kmem_cache_alloc(a_cache, GFP_KERNEL); 199 if (!val) { 200 pr_info("Unable to allocate a_cache memory.\n"); 201 return; 202 } 203 204 /* Just make sure we got real memory. */ 205 *val = 0x12345679; 206 pr_info("Attempting cross-cache slab free ...\n"); 207 kmem_cache_free(b_cache, val); 208 } 209 210 void lkdtm_SLAB_FREE_PAGE(void) 211 { 212 unsigned long p = __get_free_page(GFP_KERNEL); 213 214 pr_info("Attempting non-Slab slab free ...\n"); 215 kmem_cache_free(NULL, (void *)p); 216 free_page(p); 217 } 218 219 /* 220 * We have constructors to keep the caches distinctly separated without 221 * needing to boot with "slab_nomerge". 222 */ 223 static void ctor_double_free(void *region) 224 { } 225 static void ctor_a(void *region) 226 { } 227 static void ctor_b(void *region) 228 { } 229 230 void __init lkdtm_heap_init(void) 231 { 232 double_free_cache = kmem_cache_create("lkdtm-heap-double_free", 233 64, 0, 0, ctor_double_free); 234 a_cache = kmem_cache_create("lkdtm-heap-a", 64, 0, 0, ctor_a); 235 b_cache = kmem_cache_create("lkdtm-heap-b", 64, 0, 0, ctor_b); 236 } 237 238 void __exit lkdtm_heap_exit(void) 239 { 240 kmem_cache_destroy(double_free_cache); 241 kmem_cache_destroy(a_cache); 242 kmem_cache_destroy(b_cache); 243 } 244