1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Test cases for KMSAN. 4 * For each test case checks the presence (or absence) of generated reports. 5 * Relies on 'console' tracepoint to capture reports as they appear in the 6 * kernel log. 7 * 8 * Copyright (C) 2021-2022, Google LLC. 9 * Author: Alexander Potapenko <glider@google.com> 10 * 11 */ 12 13 #include <kunit/test.h> 14 #include "kmsan.h" 15 16 #include <linux/jiffies.h> 17 #include <linux/kernel.h> 18 #include <linux/kmsan.h> 19 #include <linux/mm.h> 20 #include <linux/random.h> 21 #include <linux/slab.h> 22 #include <linux/spinlock.h> 23 #include <linux/string.h> 24 #include <linux/tracepoint.h> 25 #include <trace/events/printk.h> 26 27 static DEFINE_PER_CPU(int, per_cpu_var); 28 29 /* Report as observed from console. */ 30 static struct { 31 spinlock_t lock; 32 bool available; 33 bool ignore; /* Stop console output collection. */ 34 char header[256]; 35 } observed = { 36 .lock = __SPIN_LOCK_UNLOCKED(observed.lock), 37 }; 38 39 /* Probe for console output: obtains observed lines of interest. */ 40 static void probe_console(void *ignore, const char *buf, size_t len) 41 { 42 unsigned long flags; 43 44 if (observed.ignore) 45 return; 46 spin_lock_irqsave(&observed.lock, flags); 47 48 if (strnstr(buf, "BUG: KMSAN: ", len)) { 49 /* 50 * KMSAN report and related to the test. 51 * 52 * The provided @buf is not NUL-terminated; copy no more than 53 * @len bytes and let strscpy() add the missing NUL-terminator. 54 */ 55 strscpy(observed.header, buf, 56 min(len + 1, sizeof(observed.header))); 57 WRITE_ONCE(observed.available, true); 58 observed.ignore = true; 59 } 60 spin_unlock_irqrestore(&observed.lock, flags); 61 } 62 63 /* Check if a report related to the test exists. */ 64 static bool report_available(void) 65 { 66 return READ_ONCE(observed.available); 67 } 68 69 /* Information we expect in a report. */ 70 struct expect_report { 71 const char *error_type; /* Error type. */ 72 /* 73 * Kernel symbol from the error header, or NULL if no report is 74 * expected. 75 */ 76 const char *symbol; 77 }; 78 79 /* Check observed report matches information in @r. */ 80 static bool report_matches(const struct expect_report *r) 81 { 82 typeof(observed.header) expected_header; 83 unsigned long flags; 84 bool ret = false; 85 const char *end; 86 char *cur; 87 88 /* Doubled-checked locking. */ 89 if (!report_available() || !r->symbol) 90 return (!report_available() && !r->symbol); 91 92 /* Generate expected report contents. */ 93 94 /* Title */ 95 cur = expected_header; 96 end = &expected_header[sizeof(expected_header) - 1]; 97 98 cur += scnprintf(cur, end - cur, "BUG: KMSAN: %s", r->error_type); 99 100 scnprintf(cur, end - cur, " in %s", r->symbol); 101 /* The exact offset won't match, remove it; also strip module name. */ 102 cur = strchr(expected_header, '+'); 103 if (cur) 104 *cur = '\0'; 105 106 spin_lock_irqsave(&observed.lock, flags); 107 if (!report_available()) 108 goto out; /* A new report is being captured. */ 109 110 /* Finally match expected output to what we actually observed. */ 111 ret = strstr(observed.header, expected_header); 112 out: 113 spin_unlock_irqrestore(&observed.lock, flags); 114 115 return ret; 116 } 117 118 /* ===== Test cases ===== */ 119 120 /* Prevent replacing branch with select in LLVM. */ 121 static noinline void check_true(char *arg) 122 { 123 pr_info("%s is true\n", arg); 124 } 125 126 static noinline void check_false(char *arg) 127 { 128 pr_info("%s is false\n", arg); 129 } 130 131 #define USE(x) \ 132 do { \ 133 if (x) \ 134 check_true(#x); \ 135 else \ 136 check_false(#x); \ 137 } while (0) 138 139 #define EXPECTATION_ETYPE_FN(e, reason, fn) \ 140 struct expect_report e = { \ 141 .error_type = reason, \ 142 .symbol = fn, \ 143 } 144 145 #define EXPECTATION_NO_REPORT(e) EXPECTATION_ETYPE_FN(e, NULL, NULL) 146 #define EXPECTATION_UNINIT_VALUE_FN(e, fn) \ 147 EXPECTATION_ETYPE_FN(e, "uninit-value", fn) 148 #define EXPECTATION_UNINIT_VALUE(e) EXPECTATION_UNINIT_VALUE_FN(e, __func__) 149 #define EXPECTATION_USE_AFTER_FREE(e) \ 150 EXPECTATION_ETYPE_FN(e, "use-after-free", __func__) 151 152 /* Test case: ensure that kmalloc() returns uninitialized memory. */ 153 static void test_uninit_kmalloc(struct kunit *test) 154 { 155 EXPECTATION_UNINIT_VALUE(expect); 156 int *ptr; 157 158 kunit_info(test, "uninitialized kmalloc test (UMR report)\n"); 159 ptr = kmalloc(sizeof(*ptr), GFP_KERNEL); 160 USE(*ptr); 161 KUNIT_EXPECT_TRUE(test, report_matches(&expect)); 162 } 163 164 /* 165 * Test case: ensure that kmalloc'ed memory becomes initialized after memset(). 166 */ 167 static void test_init_kmalloc(struct kunit *test) 168 { 169 EXPECTATION_NO_REPORT(expect); 170 int *ptr; 171 172 kunit_info(test, "initialized kmalloc test (no reports)\n"); 173 ptr = kmalloc(sizeof(*ptr), GFP_KERNEL); 174 memset(ptr, 0, sizeof(*ptr)); 175 USE(*ptr); 176 KUNIT_EXPECT_TRUE(test, report_matches(&expect)); 177 } 178 179 /* Test case: ensure that kzalloc() returns initialized memory. */ 180 static void test_init_kzalloc(struct kunit *test) 181 { 182 EXPECTATION_NO_REPORT(expect); 183 int *ptr; 184 185 kunit_info(test, "initialized kzalloc test (no reports)\n"); 186 ptr = kzalloc(sizeof(*ptr), GFP_KERNEL); 187 USE(*ptr); 188 KUNIT_EXPECT_TRUE(test, report_matches(&expect)); 189 } 190 191 /* Test case: ensure that local variables are uninitialized by default. */ 192 static void test_uninit_stack_var(struct kunit *test) 193 { 194 EXPECTATION_UNINIT_VALUE(expect); 195 volatile int cond; 196 197 kunit_info(test, "uninitialized stack variable (UMR report)\n"); 198 USE(cond); 199 KUNIT_EXPECT_TRUE(test, report_matches(&expect)); 200 } 201 202 /* Test case: ensure that local variables with initializers are initialized. */ 203 static void test_init_stack_var(struct kunit *test) 204 { 205 EXPECTATION_NO_REPORT(expect); 206 volatile int cond = 1; 207 208 kunit_info(test, "initialized stack variable (no reports)\n"); 209 USE(cond); 210 KUNIT_EXPECT_TRUE(test, report_matches(&expect)); 211 } 212 213 static noinline void two_param_fn_2(int arg1, int arg2) 214 { 215 USE(arg1); 216 USE(arg2); 217 } 218 219 static noinline void one_param_fn(int arg) 220 { 221 two_param_fn_2(arg, arg); 222 USE(arg); 223 } 224 225 static noinline void two_param_fn(int arg1, int arg2) 226 { 227 int init = 0; 228 229 one_param_fn(init); 230 USE(arg1); 231 USE(arg2); 232 } 233 234 static void test_params(struct kunit *test) 235 { 236 #ifdef CONFIG_KMSAN_CHECK_PARAM_RETVAL 237 /* 238 * With eager param/retval checking enabled, KMSAN will report an error 239 * before the call to two_param_fn(). 240 */ 241 EXPECTATION_UNINIT_VALUE_FN(expect, "test_params"); 242 #else 243 EXPECTATION_UNINIT_VALUE_FN(expect, "two_param_fn"); 244 #endif 245 volatile int uninit, init = 1; 246 247 kunit_info(test, 248 "uninit passed through a function parameter (UMR report)\n"); 249 two_param_fn(uninit, init); 250 KUNIT_EXPECT_TRUE(test, report_matches(&expect)); 251 } 252 253 static int signed_sum3(int a, int b, int c) 254 { 255 return a + b + c; 256 } 257 258 /* 259 * Test case: ensure that uninitialized values are tracked through function 260 * arguments. 261 */ 262 static void test_uninit_multiple_params(struct kunit *test) 263 { 264 EXPECTATION_UNINIT_VALUE(expect); 265 volatile char b = 3, c; 266 volatile int a; 267 268 kunit_info(test, "uninitialized local passed to fn (UMR report)\n"); 269 USE(signed_sum3(a, b, c)); 270 KUNIT_EXPECT_TRUE(test, report_matches(&expect)); 271 } 272 273 /* Helper function to make an array uninitialized. */ 274 static noinline void do_uninit_local_array(char *array, int start, int stop) 275 { 276 volatile char uninit; 277 278 for (int i = start; i < stop; i++) 279 array[i] = uninit; 280 } 281 282 /* 283 * Test case: ensure kmsan_check_memory() reports an error when checking 284 * uninitialized memory. 285 */ 286 static void test_uninit_kmsan_check_memory(struct kunit *test) 287 { 288 EXPECTATION_UNINIT_VALUE_FN(expect, "test_uninit_kmsan_check_memory"); 289 volatile char local_array[8]; 290 291 kunit_info( 292 test, 293 "kmsan_check_memory() called on uninit local (UMR report)\n"); 294 do_uninit_local_array((char *)local_array, 5, 7); 295 296 kmsan_check_memory((char *)local_array, 8); 297 KUNIT_EXPECT_TRUE(test, report_matches(&expect)); 298 } 299 300 /* 301 * Test case: check that a virtual memory range created with vmap() from 302 * initialized pages is still considered as initialized. 303 */ 304 static void test_init_kmsan_vmap_vunmap(struct kunit *test) 305 { 306 EXPECTATION_NO_REPORT(expect); 307 const int npages = 2; 308 struct page **pages; 309 void *vbuf; 310 311 kunit_info(test, "pages initialized via vmap (no reports)\n"); 312 313 pages = kmalloc_array(npages, sizeof(*pages), GFP_KERNEL); 314 for (int i = 0; i < npages; i++) 315 pages[i] = alloc_page(GFP_KERNEL); 316 vbuf = vmap(pages, npages, VM_MAP, PAGE_KERNEL); 317 memset(vbuf, 0xfe, npages * PAGE_SIZE); 318 for (int i = 0; i < npages; i++) 319 kmsan_check_memory(page_address(pages[i]), PAGE_SIZE); 320 321 if (vbuf) 322 vunmap(vbuf); 323 for (int i = 0; i < npages; i++) { 324 if (pages[i]) 325 __free_page(pages[i]); 326 } 327 kfree(pages); 328 KUNIT_EXPECT_TRUE(test, report_matches(&expect)); 329 } 330 331 /* 332 * Test case: ensure that memset() can initialize a buffer allocated via 333 * vmalloc(). 334 */ 335 static void test_init_vmalloc(struct kunit *test) 336 { 337 EXPECTATION_NO_REPORT(expect); 338 int npages = 8; 339 char *buf; 340 341 kunit_info(test, "vmalloc buffer can be initialized (no reports)\n"); 342 buf = vmalloc(PAGE_SIZE * npages); 343 buf[0] = 1; 344 memset(buf, 0xfe, PAGE_SIZE * npages); 345 USE(buf[0]); 346 for (int i = 0; i < npages; i++) 347 kmsan_check_memory(&buf[PAGE_SIZE * i], PAGE_SIZE); 348 vfree(buf); 349 KUNIT_EXPECT_TRUE(test, report_matches(&expect)); 350 } 351 352 /* Test case: ensure that use-after-free reporting works. */ 353 static void test_uaf(struct kunit *test) 354 { 355 EXPECTATION_USE_AFTER_FREE(expect); 356 volatile int value; 357 volatile int *var; 358 359 kunit_info(test, "use-after-free in kmalloc-ed buffer (UMR report)\n"); 360 var = kmalloc(80, GFP_KERNEL); 361 var[3] = 0xfeedface; 362 kfree((int *)var); 363 /* Copy the invalid value before checking it. */ 364 value = var[3]; 365 USE(value); 366 KUNIT_EXPECT_TRUE(test, report_matches(&expect)); 367 } 368 369 /* 370 * Test case: ensure that uninitialized values are propagated through per-CPU 371 * memory. 372 */ 373 static void test_percpu_propagate(struct kunit *test) 374 { 375 EXPECTATION_UNINIT_VALUE(expect); 376 volatile int uninit, check; 377 378 kunit_info(test, 379 "uninit local stored to per_cpu memory (UMR report)\n"); 380 381 this_cpu_write(per_cpu_var, uninit); 382 check = this_cpu_read(per_cpu_var); 383 USE(check); 384 KUNIT_EXPECT_TRUE(test, report_matches(&expect)); 385 } 386 387 /* 388 * Test case: ensure that passing uninitialized values to printk() leads to an 389 * error report. 390 */ 391 static void test_printk(struct kunit *test) 392 { 393 #ifdef CONFIG_KMSAN_CHECK_PARAM_RETVAL 394 /* 395 * With eager param/retval checking enabled, KMSAN will report an error 396 * before the call to pr_info(). 397 */ 398 EXPECTATION_UNINIT_VALUE_FN(expect, "test_printk"); 399 #else 400 EXPECTATION_UNINIT_VALUE_FN(expect, "number"); 401 #endif 402 volatile int uninit; 403 404 kunit_info(test, "uninit local passed to pr_info() (UMR report)\n"); 405 pr_info("%px contains %d\n", &uninit, uninit); 406 KUNIT_EXPECT_TRUE(test, report_matches(&expect)); 407 } 408 409 /* 410 * Test case: ensure that memcpy() correctly copies uninitialized values between 411 * aligned `src` and `dst`. 412 */ 413 static void test_memcpy_aligned_to_aligned(struct kunit *test) 414 { 415 EXPECTATION_UNINIT_VALUE_FN(expect, "test_memcpy_aligned_to_aligned"); 416 volatile int uninit_src; 417 volatile int dst = 0; 418 419 kunit_info( 420 test, 421 "memcpy()ing aligned uninit src to aligned dst (UMR report)\n"); 422 OPTIMIZER_HIDE_VAR(uninit_src); 423 memcpy((void *)&dst, (void *)&uninit_src, sizeof(uninit_src)); 424 kmsan_check_memory((void *)&dst, sizeof(dst)); 425 KUNIT_EXPECT_TRUE(test, report_matches(&expect)); 426 } 427 428 /* 429 * Test case: ensure that memcpy() correctly copies uninitialized values between 430 * aligned `src` and unaligned `dst`. 431 * 432 * Copying aligned 4-byte value to an unaligned one leads to touching two 433 * aligned 4-byte values. This test case checks that KMSAN correctly reports an 434 * error on the first of the two values. 435 */ 436 static void test_memcpy_aligned_to_unaligned(struct kunit *test) 437 { 438 EXPECTATION_UNINIT_VALUE_FN(expect, "test_memcpy_aligned_to_unaligned"); 439 volatile int uninit_src; 440 volatile char dst[8] = { 0 }; 441 442 kunit_info( 443 test, 444 "memcpy()ing aligned uninit src to unaligned dst (UMR report)\n"); 445 OPTIMIZER_HIDE_VAR(uninit_src); 446 memcpy((void *)&dst[1], (void *)&uninit_src, sizeof(uninit_src)); 447 kmsan_check_memory((void *)dst, 4); 448 KUNIT_EXPECT_TRUE(test, report_matches(&expect)); 449 } 450 451 /* 452 * Test case: ensure that memcpy() correctly copies uninitialized values between 453 * aligned `src` and unaligned `dst`. 454 * 455 * Copying aligned 4-byte value to an unaligned one leads to touching two 456 * aligned 4-byte values. This test case checks that KMSAN correctly reports an 457 * error on the second of the two values. 458 */ 459 static void test_memcpy_aligned_to_unaligned2(struct kunit *test) 460 { 461 EXPECTATION_UNINIT_VALUE_FN(expect, 462 "test_memcpy_aligned_to_unaligned2"); 463 volatile int uninit_src; 464 volatile char dst[8] = { 0 }; 465 466 kunit_info( 467 test, 468 "memcpy()ing aligned uninit src to unaligned dst - part 2 (UMR report)\n"); 469 OPTIMIZER_HIDE_VAR(uninit_src); 470 memcpy((void *)&dst[1], (void *)&uninit_src, sizeof(uninit_src)); 471 kmsan_check_memory((void *)&dst[4], sizeof(uninit_src)); 472 KUNIT_EXPECT_TRUE(test, report_matches(&expect)); 473 } 474 475 static noinline void fibonacci(int *array, int size, int start) { 476 if (start < 2 || (start == size)) 477 return; 478 array[start] = array[start - 1] + array[start - 2]; 479 fibonacci(array, size, start + 1); 480 } 481 482 static void test_long_origin_chain(struct kunit *test) 483 { 484 EXPECTATION_UNINIT_VALUE_FN(expect, 485 "test_long_origin_chain"); 486 /* (KMSAN_MAX_ORIGIN_DEPTH * 2) recursive calls to fibonacci(). */ 487 volatile int accum[KMSAN_MAX_ORIGIN_DEPTH * 2 + 2]; 488 int last = ARRAY_SIZE(accum) - 1; 489 490 kunit_info( 491 test, 492 "origin chain exceeding KMSAN_MAX_ORIGIN_DEPTH (UMR report)\n"); 493 /* 494 * We do not set accum[1] to 0, so the uninitializedness will be carried 495 * over to accum[2..last]. 496 */ 497 accum[0] = 1; 498 fibonacci((int *)accum, ARRAY_SIZE(accum), 2); 499 kmsan_check_memory((void *)&accum[last], sizeof(int)); 500 KUNIT_EXPECT_TRUE(test, report_matches(&expect)); 501 } 502 503 static struct kunit_case kmsan_test_cases[] = { 504 KUNIT_CASE(test_uninit_kmalloc), 505 KUNIT_CASE(test_init_kmalloc), 506 KUNIT_CASE(test_init_kzalloc), 507 KUNIT_CASE(test_uninit_stack_var), 508 KUNIT_CASE(test_init_stack_var), 509 KUNIT_CASE(test_params), 510 KUNIT_CASE(test_uninit_multiple_params), 511 KUNIT_CASE(test_uninit_kmsan_check_memory), 512 KUNIT_CASE(test_init_kmsan_vmap_vunmap), 513 KUNIT_CASE(test_init_vmalloc), 514 KUNIT_CASE(test_uaf), 515 KUNIT_CASE(test_percpu_propagate), 516 KUNIT_CASE(test_printk), 517 KUNIT_CASE(test_memcpy_aligned_to_aligned), 518 KUNIT_CASE(test_memcpy_aligned_to_unaligned), 519 KUNIT_CASE(test_memcpy_aligned_to_unaligned2), 520 KUNIT_CASE(test_long_origin_chain), 521 {}, 522 }; 523 524 /* ===== End test cases ===== */ 525 526 static int test_init(struct kunit *test) 527 { 528 unsigned long flags; 529 530 spin_lock_irqsave(&observed.lock, flags); 531 observed.header[0] = '\0'; 532 observed.ignore = false; 533 observed.available = false; 534 spin_unlock_irqrestore(&observed.lock, flags); 535 536 return 0; 537 } 538 539 static void test_exit(struct kunit *test) 540 { 541 } 542 543 static void register_tracepoints(struct tracepoint *tp, void *ignore) 544 { 545 check_trace_callback_type_console(probe_console); 546 if (!strcmp(tp->name, "console")) 547 WARN_ON(tracepoint_probe_register(tp, probe_console, NULL)); 548 } 549 550 static void unregister_tracepoints(struct tracepoint *tp, void *ignore) 551 { 552 if (!strcmp(tp->name, "console")) 553 tracepoint_probe_unregister(tp, probe_console, NULL); 554 } 555 556 static int kmsan_suite_init(struct kunit_suite *suite) 557 { 558 /* 559 * Because we want to be able to build the test as a module, we need to 560 * iterate through all known tracepoints, since the static registration 561 * won't work here. 562 */ 563 for_each_kernel_tracepoint(register_tracepoints, NULL); 564 return 0; 565 } 566 567 static void kmsan_suite_exit(struct kunit_suite *suite) 568 { 569 for_each_kernel_tracepoint(unregister_tracepoints, NULL); 570 tracepoint_synchronize_unregister(); 571 } 572 573 static struct kunit_suite kmsan_test_suite = { 574 .name = "kmsan", 575 .test_cases = kmsan_test_cases, 576 .init = test_init, 577 .exit = test_exit, 578 .suite_init = kmsan_suite_init, 579 .suite_exit = kmsan_suite_exit, 580 }; 581 kunit_test_suites(&kmsan_test_suite); 582 583 MODULE_LICENSE("GPL"); 584 MODULE_AUTHOR("Alexander Potapenko <glider@google.com>"); 585