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 15 struct lkdtm_list { 16 struct list_head node; 17 }; 18 19 /* 20 * Make sure our attempts to over run the kernel stack doesn't trigger 21 * a compiler warning when CONFIG_FRAME_WARN is set. Then make sure we 22 * recurse past the end of THREAD_SIZE by default. 23 */ 24 #if defined(CONFIG_FRAME_WARN) && (CONFIG_FRAME_WARN > 0) 25 #define REC_STACK_SIZE (CONFIG_FRAME_WARN / 2) 26 #else 27 #define REC_STACK_SIZE (THREAD_SIZE / 8) 28 #endif 29 #define REC_NUM_DEFAULT ((THREAD_SIZE / REC_STACK_SIZE) * 2) 30 31 static int recur_count = REC_NUM_DEFAULT; 32 33 static DEFINE_SPINLOCK(lock_me_up); 34 35 static int recursive_loop(int remaining) 36 { 37 char buf[REC_STACK_SIZE]; 38 39 /* Make sure compiler does not optimize this away. */ 40 memset(buf, (remaining & 0xff) | 0x1, REC_STACK_SIZE); 41 if (!remaining) 42 return 0; 43 else 44 return recursive_loop(remaining - 1); 45 } 46 47 /* If the depth is negative, use the default, otherwise keep parameter. */ 48 void __init lkdtm_bugs_init(int *recur_param) 49 { 50 if (*recur_param < 0) 51 *recur_param = recur_count; 52 else 53 recur_count = *recur_param; 54 } 55 56 void lkdtm_PANIC(void) 57 { 58 panic("dumptest"); 59 } 60 61 void lkdtm_BUG(void) 62 { 63 BUG(); 64 } 65 66 static int warn_counter; 67 68 void lkdtm_WARNING(void) 69 { 70 WARN(1, "Warning message trigger count: %d\n", warn_counter++); 71 } 72 73 void lkdtm_EXCEPTION(void) 74 { 75 *((volatile int *) 0) = 0; 76 } 77 78 void lkdtm_LOOP(void) 79 { 80 for (;;) 81 ; 82 } 83 84 void lkdtm_OVERFLOW(void) 85 { 86 (void) recursive_loop(recur_count); 87 } 88 89 static noinline void __lkdtm_CORRUPT_STACK(void *stack) 90 { 91 memset(stack, '\xff', 64); 92 } 93 94 /* This should trip the stack canary, not corrupt the return address. */ 95 noinline void lkdtm_CORRUPT_STACK(void) 96 { 97 /* Use default char array length that triggers stack protection. */ 98 char data[8] __aligned(sizeof(void *)); 99 100 __lkdtm_CORRUPT_STACK(&data); 101 102 pr_info("Corrupted stack containing char array ...\n"); 103 } 104 105 /* Same as above but will only get a canary with -fstack-protector-strong */ 106 noinline void lkdtm_CORRUPT_STACK_STRONG(void) 107 { 108 union { 109 unsigned short shorts[4]; 110 unsigned long *ptr; 111 } data __aligned(sizeof(void *)); 112 113 __lkdtm_CORRUPT_STACK(&data); 114 115 pr_info("Corrupted stack containing union ...\n"); 116 } 117 118 void lkdtm_UNALIGNED_LOAD_STORE_WRITE(void) 119 { 120 static u8 data[5] __attribute__((aligned(4))) = {1, 2, 3, 4, 5}; 121 u32 *p; 122 u32 val = 0x12345678; 123 124 p = (u32 *)(data + 1); 125 if (*p == 0) 126 val = 0x87654321; 127 *p = val; 128 } 129 130 void lkdtm_SOFTLOCKUP(void) 131 { 132 preempt_disable(); 133 for (;;) 134 cpu_relax(); 135 } 136 137 void lkdtm_HARDLOCKUP(void) 138 { 139 local_irq_disable(); 140 for (;;) 141 cpu_relax(); 142 } 143 144 void lkdtm_SPINLOCKUP(void) 145 { 146 /* Must be called twice to trigger. */ 147 spin_lock(&lock_me_up); 148 /* Let sparse know we intended to exit holding the lock. */ 149 __release(&lock_me_up); 150 } 151 152 void lkdtm_HUNG_TASK(void) 153 { 154 set_current_state(TASK_UNINTERRUPTIBLE); 155 schedule(); 156 } 157 158 void lkdtm_CORRUPT_LIST_ADD(void) 159 { 160 /* 161 * Initially, an empty list via LIST_HEAD: 162 * test_head.next = &test_head 163 * test_head.prev = &test_head 164 */ 165 LIST_HEAD(test_head); 166 struct lkdtm_list good, bad; 167 void *target[2] = { }; 168 void *redirection = ⌖ 169 170 pr_info("attempting good list addition\n"); 171 172 /* 173 * Adding to the list performs these actions: 174 * test_head.next->prev = &good.node 175 * good.node.next = test_head.next 176 * good.node.prev = test_head 177 * test_head.next = good.node 178 */ 179 list_add(&good.node, &test_head); 180 181 pr_info("attempting corrupted list addition\n"); 182 /* 183 * In simulating this "write what where" primitive, the "what" is 184 * the address of &bad.node, and the "where" is the address held 185 * by "redirection". 186 */ 187 test_head.next = redirection; 188 list_add(&bad.node, &test_head); 189 190 if (target[0] == NULL && target[1] == NULL) 191 pr_err("Overwrite did not happen, but no BUG?!\n"); 192 else 193 pr_err("list_add() corruption not detected!\n"); 194 } 195 196 void lkdtm_CORRUPT_LIST_DEL(void) 197 { 198 LIST_HEAD(test_head); 199 struct lkdtm_list item; 200 void *target[2] = { }; 201 void *redirection = ⌖ 202 203 list_add(&item.node, &test_head); 204 205 pr_info("attempting good list removal\n"); 206 list_del(&item.node); 207 208 pr_info("attempting corrupted list removal\n"); 209 list_add(&item.node, &test_head); 210 211 /* As with the list_add() test above, this corrupts "next". */ 212 item.node.next = redirection; 213 list_del(&item.node); 214 215 if (target[0] == NULL && target[1] == NULL) 216 pr_err("Overwrite did not happen, but no BUG?!\n"); 217 else 218 pr_err("list_del() corruption not detected!\n"); 219 } 220 221 /* Test if unbalanced set_fs(KERNEL_DS)/set_fs(USER_DS) check exists. */ 222 void lkdtm_CORRUPT_USER_DS(void) 223 { 224 pr_info("setting bad task size limit\n"); 225 set_fs(KERNEL_DS); 226 227 /* Make sure we do not keep running with a KERNEL_DS! */ 228 force_sig(SIGKILL, current); 229 } 230 231 /* Test that VMAP_STACK is actually allocating with a leading guard page */ 232 void lkdtm_STACK_GUARD_PAGE_LEADING(void) 233 { 234 const unsigned char *stack = task_stack_page(current); 235 const unsigned char *ptr = stack - 1; 236 volatile unsigned char byte; 237 238 pr_info("attempting bad read from page below current stack\n"); 239 240 byte = *ptr; 241 242 pr_err("FAIL: accessed page before stack!\n"); 243 } 244 245 /* Test that VMAP_STACK is actually allocating with a trailing guard page */ 246 void lkdtm_STACK_GUARD_PAGE_TRAILING(void) 247 { 248 const unsigned char *stack = task_stack_page(current); 249 const unsigned char *ptr = stack + THREAD_SIZE; 250 volatile unsigned char byte; 251 252 pr_info("attempting bad read from page above current stack\n"); 253 254 byte = *ptr; 255 256 pr_err("FAIL: accessed page after stack!\n"); 257 } 258