at v5.7 491 lines 12 kB view raw
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * This is for all the tests related to logic bugs (e.g. bad dereferences, 4 * bad alignment, bad loops, bad locking, bad scheduling, deep stacks, and 5 * lockups) along with other things that don't fit well into existing LKDTM 6 * test source files. 7 */ 8#include "lkdtm.h" 9#include <linux/list.h> 10#include <linux/sched.h> 11#include <linux/sched/signal.h> 12#include <linux/sched/task_stack.h> 13#include <linux/uaccess.h> 14#include <linux/slab.h> 15 16#ifdef CONFIG_X86_32 17#include <asm/desc.h> 18#endif 19 20struct lkdtm_list { 21 struct list_head node; 22}; 23 24/* 25 * Make sure our attempts to over run the kernel stack doesn't trigger 26 * a compiler warning when CONFIG_FRAME_WARN is set. Then make sure we 27 * recurse past the end of THREAD_SIZE by default. 28 */ 29#if defined(CONFIG_FRAME_WARN) && (CONFIG_FRAME_WARN > 0) 30#define REC_STACK_SIZE (_AC(CONFIG_FRAME_WARN, UL) / 2) 31#else 32#define REC_STACK_SIZE (THREAD_SIZE / 8) 33#endif 34#define REC_NUM_DEFAULT ((THREAD_SIZE / REC_STACK_SIZE) * 2) 35 36static int recur_count = REC_NUM_DEFAULT; 37 38static DEFINE_SPINLOCK(lock_me_up); 39 40/* 41 * Make sure compiler does not optimize this function or stack frame away: 42 * - function marked noinline 43 * - stack variables are marked volatile 44 * - stack variables are written (memset()) and read (pr_info()) 45 * - function has external effects (pr_info()) 46 * */ 47static int noinline recursive_loop(int remaining) 48{ 49 volatile char buf[REC_STACK_SIZE]; 50 51 memset((void *)buf, remaining & 0xFF, sizeof(buf)); 52 pr_info("loop %d/%d ...\n", (int)buf[remaining % sizeof(buf)], 53 recur_count); 54 if (!remaining) 55 return 0; 56 else 57 return recursive_loop(remaining - 1); 58} 59 60/* If the depth is negative, use the default, otherwise keep parameter. */ 61void __init lkdtm_bugs_init(int *recur_param) 62{ 63 if (*recur_param < 0) 64 *recur_param = recur_count; 65 else 66 recur_count = *recur_param; 67} 68 69void lkdtm_PANIC(void) 70{ 71 panic("dumptest"); 72} 73 74void lkdtm_BUG(void) 75{ 76 BUG(); 77} 78 79static int warn_counter; 80 81void lkdtm_WARNING(void) 82{ 83 WARN_ON(++warn_counter); 84} 85 86void lkdtm_WARNING_MESSAGE(void) 87{ 88 WARN(1, "Warning message trigger count: %d\n", ++warn_counter); 89} 90 91void lkdtm_EXCEPTION(void) 92{ 93 *((volatile int *) 0) = 0; 94} 95 96void lkdtm_LOOP(void) 97{ 98 for (;;) 99 ; 100} 101 102void lkdtm_EXHAUST_STACK(void) 103{ 104 pr_info("Calling function with %lu frame size to depth %d ...\n", 105 REC_STACK_SIZE, recur_count); 106 recursive_loop(recur_count); 107 pr_info("FAIL: survived without exhausting stack?!\n"); 108} 109 110static noinline void __lkdtm_CORRUPT_STACK(void *stack) 111{ 112 memset(stack, '\xff', 64); 113} 114 115/* This should trip the stack canary, not corrupt the return address. */ 116noinline void lkdtm_CORRUPT_STACK(void) 117{ 118 /* Use default char array length that triggers stack protection. */ 119 char data[8] __aligned(sizeof(void *)); 120 121 __lkdtm_CORRUPT_STACK(&data); 122 123 pr_info("Corrupted stack containing char array ...\n"); 124} 125 126/* Same as above but will only get a canary with -fstack-protector-strong */ 127noinline void lkdtm_CORRUPT_STACK_STRONG(void) 128{ 129 union { 130 unsigned short shorts[4]; 131 unsigned long *ptr; 132 } data __aligned(sizeof(void *)); 133 134 __lkdtm_CORRUPT_STACK(&data); 135 136 pr_info("Corrupted stack containing union ...\n"); 137} 138 139void lkdtm_UNALIGNED_LOAD_STORE_WRITE(void) 140{ 141 static u8 data[5] __attribute__((aligned(4))) = {1, 2, 3, 4, 5}; 142 u32 *p; 143 u32 val = 0x12345678; 144 145 p = (u32 *)(data + 1); 146 if (*p == 0) 147 val = 0x87654321; 148 *p = val; 149} 150 151void lkdtm_SOFTLOCKUP(void) 152{ 153 preempt_disable(); 154 for (;;) 155 cpu_relax(); 156} 157 158void lkdtm_HARDLOCKUP(void) 159{ 160 local_irq_disable(); 161 for (;;) 162 cpu_relax(); 163} 164 165void lkdtm_SPINLOCKUP(void) 166{ 167 /* Must be called twice to trigger. */ 168 spin_lock(&lock_me_up); 169 /* Let sparse know we intended to exit holding the lock. */ 170 __release(&lock_me_up); 171} 172 173void lkdtm_HUNG_TASK(void) 174{ 175 set_current_state(TASK_UNINTERRUPTIBLE); 176 schedule(); 177} 178 179volatile unsigned int huge = INT_MAX - 2; 180volatile unsigned int ignored; 181 182void lkdtm_OVERFLOW_SIGNED(void) 183{ 184 int value; 185 186 value = huge; 187 pr_info("Normal signed addition ...\n"); 188 value += 1; 189 ignored = value; 190 191 pr_info("Overflowing signed addition ...\n"); 192 value += 4; 193 ignored = value; 194} 195 196 197void lkdtm_OVERFLOW_UNSIGNED(void) 198{ 199 unsigned int value; 200 201 value = huge; 202 pr_info("Normal unsigned addition ...\n"); 203 value += 1; 204 ignored = value; 205 206 pr_info("Overflowing unsigned addition ...\n"); 207 value += 4; 208 ignored = value; 209} 210 211/* Intentially using old-style flex array definition of 1 byte. */ 212struct array_bounds_flex_array { 213 int one; 214 int two; 215 char data[1]; 216}; 217 218struct array_bounds { 219 int one; 220 int two; 221 char data[8]; 222 int three; 223}; 224 225void lkdtm_ARRAY_BOUNDS(void) 226{ 227 struct array_bounds_flex_array *not_checked; 228 struct array_bounds *checked; 229 volatile int i; 230 231 not_checked = kmalloc(sizeof(*not_checked) * 2, GFP_KERNEL); 232 checked = kmalloc(sizeof(*checked) * 2, GFP_KERNEL); 233 234 pr_info("Array access within bounds ...\n"); 235 /* For both, touch all bytes in the actual member size. */ 236 for (i = 0; i < sizeof(checked->data); i++) 237 checked->data[i] = 'A'; 238 /* 239 * For the uninstrumented flex array member, also touch 1 byte 240 * beyond to verify it is correctly uninstrumented. 241 */ 242 for (i = 0; i < sizeof(not_checked->data) + 1; i++) 243 not_checked->data[i] = 'A'; 244 245 pr_info("Array access beyond bounds ...\n"); 246 for (i = 0; i < sizeof(checked->data) + 1; i++) 247 checked->data[i] = 'B'; 248 249 kfree(not_checked); 250 kfree(checked); 251} 252 253void lkdtm_CORRUPT_LIST_ADD(void) 254{ 255 /* 256 * Initially, an empty list via LIST_HEAD: 257 * test_head.next = &test_head 258 * test_head.prev = &test_head 259 */ 260 LIST_HEAD(test_head); 261 struct lkdtm_list good, bad; 262 void *target[2] = { }; 263 void *redirection = &target; 264 265 pr_info("attempting good list addition\n"); 266 267 /* 268 * Adding to the list performs these actions: 269 * test_head.next->prev = &good.node 270 * good.node.next = test_head.next 271 * good.node.prev = test_head 272 * test_head.next = good.node 273 */ 274 list_add(&good.node, &test_head); 275 276 pr_info("attempting corrupted list addition\n"); 277 /* 278 * In simulating this "write what where" primitive, the "what" is 279 * the address of &bad.node, and the "where" is the address held 280 * by "redirection". 281 */ 282 test_head.next = redirection; 283 list_add(&bad.node, &test_head); 284 285 if (target[0] == NULL && target[1] == NULL) 286 pr_err("Overwrite did not happen, but no BUG?!\n"); 287 else 288 pr_err("list_add() corruption not detected!\n"); 289} 290 291void lkdtm_CORRUPT_LIST_DEL(void) 292{ 293 LIST_HEAD(test_head); 294 struct lkdtm_list item; 295 void *target[2] = { }; 296 void *redirection = &target; 297 298 list_add(&item.node, &test_head); 299 300 pr_info("attempting good list removal\n"); 301 list_del(&item.node); 302 303 pr_info("attempting corrupted list removal\n"); 304 list_add(&item.node, &test_head); 305 306 /* As with the list_add() test above, this corrupts "next". */ 307 item.node.next = redirection; 308 list_del(&item.node); 309 310 if (target[0] == NULL && target[1] == NULL) 311 pr_err("Overwrite did not happen, but no BUG?!\n"); 312 else 313 pr_err("list_del() corruption not detected!\n"); 314} 315 316/* Test if unbalanced set_fs(KERNEL_DS)/set_fs(USER_DS) check exists. */ 317void lkdtm_CORRUPT_USER_DS(void) 318{ 319 pr_info("setting bad task size limit\n"); 320 set_fs(KERNEL_DS); 321 322 /* Make sure we do not keep running with a KERNEL_DS! */ 323 force_sig(SIGKILL); 324} 325 326/* Test that VMAP_STACK is actually allocating with a leading guard page */ 327void lkdtm_STACK_GUARD_PAGE_LEADING(void) 328{ 329 const unsigned char *stack = task_stack_page(current); 330 const unsigned char *ptr = stack - 1; 331 volatile unsigned char byte; 332 333 pr_info("attempting bad read from page below current stack\n"); 334 335 byte = *ptr; 336 337 pr_err("FAIL: accessed page before stack!\n"); 338} 339 340/* Test that VMAP_STACK is actually allocating with a trailing guard page */ 341void lkdtm_STACK_GUARD_PAGE_TRAILING(void) 342{ 343 const unsigned char *stack = task_stack_page(current); 344 const unsigned char *ptr = stack + THREAD_SIZE; 345 volatile unsigned char byte; 346 347 pr_info("attempting bad read from page above current stack\n"); 348 349 byte = *ptr; 350 351 pr_err("FAIL: accessed page after stack!\n"); 352} 353 354void lkdtm_UNSET_SMEP(void) 355{ 356#if IS_ENABLED(CONFIG_X86_64) && !IS_ENABLED(CONFIG_UML) 357#define MOV_CR4_DEPTH 64 358 void (*direct_write_cr4)(unsigned long val); 359 unsigned char *insn; 360 unsigned long cr4; 361 int i; 362 363 cr4 = native_read_cr4(); 364 365 if ((cr4 & X86_CR4_SMEP) != X86_CR4_SMEP) { 366 pr_err("FAIL: SMEP not in use\n"); 367 return; 368 } 369 cr4 &= ~(X86_CR4_SMEP); 370 371 pr_info("trying to clear SMEP normally\n"); 372 native_write_cr4(cr4); 373 if (cr4 == native_read_cr4()) { 374 pr_err("FAIL: pinning SMEP failed!\n"); 375 cr4 |= X86_CR4_SMEP; 376 pr_info("restoring SMEP\n"); 377 native_write_cr4(cr4); 378 return; 379 } 380 pr_info("ok: SMEP did not get cleared\n"); 381 382 /* 383 * To test the post-write pinning verification we need to call 384 * directly into the middle of native_write_cr4() where the 385 * cr4 write happens, skipping any pinning. This searches for 386 * the cr4 writing instruction. 387 */ 388 insn = (unsigned char *)native_write_cr4; 389 for (i = 0; i < MOV_CR4_DEPTH; i++) { 390 /* mov %rdi, %cr4 */ 391 if (insn[i] == 0x0f && insn[i+1] == 0x22 && insn[i+2] == 0xe7) 392 break; 393 /* mov %rdi,%rax; mov %rax, %cr4 */ 394 if (insn[i] == 0x48 && insn[i+1] == 0x89 && 395 insn[i+2] == 0xf8 && insn[i+3] == 0x0f && 396 insn[i+4] == 0x22 && insn[i+5] == 0xe0) 397 break; 398 } 399 if (i >= MOV_CR4_DEPTH) { 400 pr_info("ok: cannot locate cr4 writing call gadget\n"); 401 return; 402 } 403 direct_write_cr4 = (void *)(insn + i); 404 405 pr_info("trying to clear SMEP with call gadget\n"); 406 direct_write_cr4(cr4); 407 if (native_read_cr4() & X86_CR4_SMEP) { 408 pr_info("ok: SMEP removal was reverted\n"); 409 } else { 410 pr_err("FAIL: cleared SMEP not detected!\n"); 411 cr4 |= X86_CR4_SMEP; 412 pr_info("restoring SMEP\n"); 413 native_write_cr4(cr4); 414 } 415#else 416 pr_err("XFAIL: this test is x86_64-only\n"); 417#endif 418} 419 420void lkdtm_DOUBLE_FAULT(void) 421{ 422#ifdef CONFIG_X86_32 423 /* 424 * Trigger #DF by setting the stack limit to zero. This clobbers 425 * a GDT TLS slot, which is okay because the current task will die 426 * anyway due to the double fault. 427 */ 428 struct desc_struct d = { 429 .type = 3, /* expand-up, writable, accessed data */ 430 .p = 1, /* present */ 431 .d = 1, /* 32-bit */ 432 .g = 0, /* limit in bytes */ 433 .s = 1, /* not system */ 434 }; 435 436 local_irq_disable(); 437 write_gdt_entry(get_cpu_gdt_rw(smp_processor_id()), 438 GDT_ENTRY_TLS_MIN, &d, DESCTYPE_S); 439 440 /* 441 * Put our zero-limit segment in SS and then trigger a fault. The 442 * 4-byte access to (%esp) will fault with #SS, and the attempt to 443 * deliver the fault will recursively cause #SS and result in #DF. 444 * This whole process happens while NMIs and MCEs are blocked by the 445 * MOV SS window. This is nice because an NMI with an invalid SS 446 * would also double-fault, resulting in the NMI or MCE being lost. 447 */ 448 asm volatile ("movw %0, %%ss; addl $0, (%%esp)" :: 449 "r" ((unsigned short)(GDT_ENTRY_TLS_MIN << 3))); 450 451 pr_err("FAIL: tried to double fault but didn't die\n"); 452#else 453 pr_err("XFAIL: this test is ia32-only\n"); 454#endif 455} 456 457#ifdef CONFIG_ARM64_PTR_AUTH 458static noinline void change_pac_parameters(void) 459{ 460 /* Reset the keys of current task */ 461 ptrauth_thread_init_kernel(current); 462 ptrauth_thread_switch_kernel(current); 463} 464 465#define CORRUPT_PAC_ITERATE 10 466noinline void lkdtm_CORRUPT_PAC(void) 467{ 468 int i; 469 470 if (!system_supports_address_auth()) { 471 pr_err("FAIL: arm64 pointer authentication feature not present\n"); 472 return; 473 } 474 475 pr_info("Change the PAC parameters to force function return failure\n"); 476 /* 477 * Pac is a hash value computed from input keys, return address and 478 * stack pointer. As pac has fewer bits so there is a chance of 479 * collision, so iterate few times to reduce the collision probability. 480 */ 481 for (i = 0; i < CORRUPT_PAC_ITERATE; i++) 482 change_pac_parameters(); 483 484 pr_err("FAIL: %s test failed. Kernel may be unstable from here\n", __func__); 485} 486#else /* !CONFIG_ARM64_PTR_AUTH */ 487noinline void lkdtm_CORRUPT_PAC(void) 488{ 489 pr_err("FAIL: arm64 pointer authentication config disabled\n"); 490} 491#endif