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_INIT_ON_ALLOC(void) 178 { 179 u8 *first; 180 u8 *val; 181 182 first = kmalloc(512, GFP_KERNEL); 183 if (!first) { 184 pr_info("Unable to allocate 512 bytes the first time.\n"); 185 return; 186 } 187 188 memset(first, 0xAB, 512); 189 kfree(first); 190 191 val = kmalloc(512, GFP_KERNEL); 192 if (!val) { 193 pr_info("Unable to allocate 512 bytes the second time.\n"); 194 return; 195 } 196 if (val != first) { 197 pr_warn("Reallocation missed clobbered memory.\n"); 198 } 199 200 if (memchr(val, 0xAB, 512) == NULL) { 201 pr_info("Memory appears initialized (%x, no earlier values)\n", *val); 202 } else { 203 pr_err("FAIL: Slab was not initialized\n"); 204 pr_expected_config_param(CONFIG_INIT_ON_ALLOC_DEFAULT_ON, "init_on_alloc"); 205 } 206 kfree(val); 207 } 208 209 void lkdtm_BUDDY_INIT_ON_ALLOC(void) 210 { 211 u8 *first; 212 u8 *val; 213 214 first = (u8 *)__get_free_page(GFP_KERNEL); 215 if (!first) { 216 pr_info("Unable to allocate first free page\n"); 217 return; 218 } 219 220 memset(first, 0xAB, PAGE_SIZE); 221 free_page((unsigned long)first); 222 223 val = (u8 *)__get_free_page(GFP_KERNEL); 224 if (!val) { 225 pr_info("Unable to allocate second free page\n"); 226 return; 227 } 228 229 if (val != first) { 230 pr_warn("Reallocation missed clobbered memory.\n"); 231 } 232 233 if (memchr(val, 0xAB, PAGE_SIZE) == NULL) { 234 pr_info("Memory appears initialized (%x, no earlier values)\n", *val); 235 } else { 236 pr_err("FAIL: Slab was not initialized\n"); 237 pr_expected_config_param(CONFIG_INIT_ON_ALLOC_DEFAULT_ON, "init_on_alloc"); 238 } 239 free_page((unsigned long)val); 240 } 241 242 void lkdtm_SLAB_FREE_DOUBLE(void) 243 { 244 int *val; 245 246 val = kmem_cache_alloc(double_free_cache, GFP_KERNEL); 247 if (!val) { 248 pr_info("Unable to allocate double_free_cache memory.\n"); 249 return; 250 } 251 252 /* Just make sure we got real memory. */ 253 *val = 0x12345678; 254 pr_info("Attempting double slab free ...\n"); 255 kmem_cache_free(double_free_cache, val); 256 kmem_cache_free(double_free_cache, val); 257 } 258 259 void lkdtm_SLAB_FREE_CROSS(void) 260 { 261 int *val; 262 263 val = kmem_cache_alloc(a_cache, GFP_KERNEL); 264 if (!val) { 265 pr_info("Unable to allocate a_cache memory.\n"); 266 return; 267 } 268 269 /* Just make sure we got real memory. */ 270 *val = 0x12345679; 271 pr_info("Attempting cross-cache slab free ...\n"); 272 kmem_cache_free(b_cache, val); 273 } 274 275 void lkdtm_SLAB_FREE_PAGE(void) 276 { 277 unsigned long p = __get_free_page(GFP_KERNEL); 278 279 pr_info("Attempting non-Slab slab free ...\n"); 280 kmem_cache_free(NULL, (void *)p); 281 free_page(p); 282 } 283 284 /* 285 * We have constructors to keep the caches distinctly separated without 286 * needing to boot with "slab_nomerge". 287 */ 288 static void ctor_double_free(void *region) 289 { } 290 static void ctor_a(void *region) 291 { } 292 static void ctor_b(void *region) 293 { } 294 295 void __init lkdtm_heap_init(void) 296 { 297 double_free_cache = kmem_cache_create("lkdtm-heap-double_free", 298 64, 0, 0, ctor_double_free); 299 a_cache = kmem_cache_create("lkdtm-heap-a", 64, 0, 0, ctor_a); 300 b_cache = kmem_cache_create("lkdtm-heap-b", 64, 0, 0, ctor_b); 301 } 302 303 void __exit lkdtm_heap_exit(void) 304 { 305 kmem_cache_destroy(double_free_cache); 306 kmem_cache_destroy(a_cache); 307 kmem_cache_destroy(b_cache); 308 } 309