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