Commit | Line | Data |
---|---|---|
d2912cb1 | 1 | // SPDX-License-Identifier: GPL-2.0-only |
3f15801c AR |
2 | /* |
3 | * | |
4 | * Copyright (c) 2014 Samsung Electronics Co., Ltd. | |
5 | * Author: Andrey Ryabinin <a.ryabinin@samsung.com> | |
3f15801c AR |
6 | */ |
7 | ||
19a33ca6 | 8 | #include <linux/bitops.h> |
0386bf38 | 9 | #include <linux/delay.h> |
19a33ca6 | 10 | #include <linux/kasan.h> |
3f15801c | 11 | #include <linux/kernel.h> |
eae08dca | 12 | #include <linux/mm.h> |
19a33ca6 ME |
13 | #include <linux/mman.h> |
14 | #include <linux/module.h> | |
3f15801c | 15 | #include <linux/printk.h> |
573a4809 | 16 | #include <linux/random.h> |
3f15801c AR |
17 | #include <linux/slab.h> |
18 | #include <linux/string.h> | |
eae08dca | 19 | #include <linux/uaccess.h> |
b92a953c | 20 | #include <linux/io.h> |
06513916 | 21 | #include <linux/vmalloc.h> |
b92a953c MR |
22 | |
23 | #include <asm/page.h> | |
3f15801c | 24 | |
83c4e7a0 PA |
25 | #include <kunit/test.h> |
26 | ||
f33a0149 WW |
27 | #include "../mm/kasan/kasan.h" |
28 | ||
1f600626 | 29 | #define OOB_TAG_OFF (IS_ENABLED(CONFIG_KASAN_GENERIC) ? 0 : KASAN_GRANULE_SIZE) |
f33a0149 | 30 | |
adb72ae1 | 31 | /* |
0fd37925 AK |
32 | * Some tests use these global variables to store return values from function |
33 | * calls that could otherwise be eliminated by the compiler as dead code. | |
adb72ae1 | 34 | */ |
adb72ae1 | 35 | void *kasan_ptr_result; |
83c4e7a0 PA |
36 | int kasan_int_result; |
37 | ||
38 | static struct kunit_resource resource; | |
39 | static struct kunit_kasan_expectation fail_data; | |
40 | static bool multishot; | |
41 | ||
0fd37925 AK |
42 | /* |
43 | * Temporarily enable multi-shot mode. Otherwise, KASAN would only report the | |
f05842cf AK |
44 | * first detected bug and panic the kernel if panic_on_warn is enabled. For |
45 | * hardware tag-based KASAN also allow tag checking to be reenabled for each | |
46 | * test, see the comment for KUNIT_EXPECT_KASAN_FAIL(). | |
0fd37925 | 47 | */ |
83c4e7a0 PA |
48 | static int kasan_test_init(struct kunit *test) |
49 | { | |
d82dc3a4 AK |
50 | if (!kasan_enabled()) { |
51 | kunit_err(test, "can't run KASAN tests with KASAN disabled"); | |
52 | return -1; | |
53 | } | |
54 | ||
83c4e7a0 | 55 | multishot = kasan_save_enable_multi_shot(); |
99734b53 | 56 | fail_data.report_found = false; |
99734b53 AK |
57 | kunit_add_named_resource(test, NULL, NULL, &resource, |
58 | "kasan_data", &fail_data); | |
83c4e7a0 PA |
59 | return 0; |
60 | } | |
61 | ||
62 | static void kasan_test_exit(struct kunit *test) | |
63 | { | |
64 | kasan_restore_multi_shot(multishot); | |
99734b53 | 65 | KUNIT_EXPECT_FALSE(test, fail_data.report_found); |
83c4e7a0 PA |
66 | } |
67 | ||
68 | /** | |
0fd37925 AK |
69 | * KUNIT_EXPECT_KASAN_FAIL() - check that the executed expression produces a |
70 | * KASAN report; causes a test failure otherwise. This relies on a KUnit | |
71 | * resource named "kasan_data". Do not use this name for KUnit resources | |
72 | * outside of KASAN tests. | |
f05842cf | 73 | * |
e80a76aa AK |
74 | * For hardware tag-based KASAN in sync mode, when a tag fault happens, tag |
75 | * checking is auto-disabled. When this happens, this test handler reenables | |
76 | * tag checking. As tag checking can be only disabled or enabled per CPU, | |
77 | * this handler disables migration (preemption). | |
2e4bde6a AK |
78 | * |
79 | * Since the compiler doesn't see that the expression can change the fail_data | |
80 | * fields, it can reorder or optimize away the accesses to those fields. | |
81 | * Use READ/WRITE_ONCE() for the accesses and compiler barriers around the | |
82 | * expression to prevent that. | |
99734b53 AK |
83 | * |
84 | * In between KUNIT_EXPECT_KASAN_FAIL checks, fail_data.report_found is kept as | |
85 | * false. This allows detecting KASAN reports that happen outside of the checks | |
86 | * by asserting !fail_data.report_found at the start of KUNIT_EXPECT_KASAN_FAIL | |
87 | * and in kasan_test_exit. | |
83c4e7a0 | 88 | */ |
99734b53 AK |
89 | #define KUNIT_EXPECT_KASAN_FAIL(test, expression) do { \ |
90 | if (IS_ENABLED(CONFIG_KASAN_HW_TAGS) && \ | |
2d27e585 | 91 | kasan_sync_fault_possible()) \ |
99734b53 AK |
92 | migrate_disable(); \ |
93 | KUNIT_EXPECT_FALSE(test, READ_ONCE(fail_data.report_found)); \ | |
99734b53 AK |
94 | barrier(); \ |
95 | expression; \ | |
96 | barrier(); \ | |
3ff16d30 DG |
97 | if (!READ_ONCE(fail_data.report_found)) { \ |
98 | KUNIT_FAIL(test, KUNIT_SUBTEST_INDENT "KASAN failure " \ | |
99 | "expected in \"" #expression \ | |
100 | "\", but none occurred"); \ | |
101 | } \ | |
99734b53 AK |
102 | if (IS_ENABLED(CONFIG_KASAN_HW_TAGS)) { \ |
103 | if (READ_ONCE(fail_data.report_found)) \ | |
104 | kasan_enable_tagging_sync(); \ | |
105 | migrate_enable(); \ | |
106 | } \ | |
107 | WRITE_ONCE(fail_data.report_found, false); \ | |
83c4e7a0 PA |
108 | } while (0) |
109 | ||
da17e377 | 110 | #define KASAN_TEST_NEEDS_CONFIG_ON(test, config) do { \ |
40eb5cf4 ME |
111 | if (!IS_ENABLED(config)) \ |
112 | kunit_skip((test), "Test requires " #config "=y"); \ | |
da17e377 AK |
113 | } while (0) |
114 | ||
115 | #define KASAN_TEST_NEEDS_CONFIG_OFF(test, config) do { \ | |
40eb5cf4 ME |
116 | if (IS_ENABLED(config)) \ |
117 | kunit_skip((test), "Test requires " #config "=n"); \ | |
da17e377 AK |
118 | } while (0) |
119 | ||
73228c7e | 120 | static void kmalloc_oob_right(struct kunit *test) |
3f15801c AR |
121 | { |
122 | char *ptr; | |
ab512805 | 123 | size_t size = 128 - KASAN_GRANULE_SIZE - 5; |
3f15801c | 124 | |
3f15801c | 125 | ptr = kmalloc(size, GFP_KERNEL); |
73228c7e | 126 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr); |
f33a0149 | 127 | |
ab512805 AK |
128 | /* |
129 | * An unaligned access past the requested kmalloc size. | |
130 | * Only generic KASAN can precisely detect these. | |
131 | */ | |
132 | if (IS_ENABLED(CONFIG_KASAN_GENERIC)) | |
133 | KUNIT_EXPECT_KASAN_FAIL(test, ptr[size] = 'x'); | |
134 | ||
135 | /* | |
136 | * An aligned access into the first out-of-bounds granule that falls | |
137 | * within the aligned kmalloc object. | |
138 | */ | |
139 | KUNIT_EXPECT_KASAN_FAIL(test, ptr[size + 5] = 'y'); | |
140 | ||
141 | /* Out-of-bounds access past the aligned kmalloc object. */ | |
142 | KUNIT_EXPECT_KASAN_FAIL(test, ptr[0] = | |
143 | ptr[size + KASAN_GRANULE_SIZE + 5]); | |
144 | ||
3f15801c AR |
145 | kfree(ptr); |
146 | } | |
147 | ||
73228c7e | 148 | static void kmalloc_oob_left(struct kunit *test) |
3f15801c AR |
149 | { |
150 | char *ptr; | |
151 | size_t size = 15; | |
152 | ||
3f15801c | 153 | ptr = kmalloc(size, GFP_KERNEL); |
73228c7e | 154 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr); |
3f15801c | 155 | |
73228c7e | 156 | KUNIT_EXPECT_KASAN_FAIL(test, *ptr = *(ptr - 1)); |
3f15801c AR |
157 | kfree(ptr); |
158 | } | |
159 | ||
73228c7e | 160 | static void kmalloc_node_oob_right(struct kunit *test) |
3f15801c AR |
161 | { |
162 | char *ptr; | |
163 | size_t size = 4096; | |
164 | ||
3f15801c | 165 | ptr = kmalloc_node(size, GFP_KERNEL, 0); |
73228c7e | 166 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr); |
3f15801c | 167 | |
8fbad19b | 168 | KUNIT_EXPECT_KASAN_FAIL(test, ptr[0] = ptr[size]); |
3f15801c AR |
169 | kfree(ptr); |
170 | } | |
171 | ||
858bdeb0 AK |
172 | /* |
173 | * These kmalloc_pagealloc_* tests try allocating a memory chunk that doesn't | |
174 | * fit into a slab cache and therefore is allocated via the page allocator | |
175 | * fallback. Since this kind of fallback is only implemented for SLUB, these | |
176 | * tests are limited to that allocator. | |
177 | */ | |
73228c7e | 178 | static void kmalloc_pagealloc_oob_right(struct kunit *test) |
3f15801c AR |
179 | { |
180 | char *ptr; | |
181 | size_t size = KMALLOC_MAX_CACHE_SIZE + 10; | |
182 | ||
da17e377 | 183 | KASAN_TEST_NEEDS_CONFIG_ON(test, CONFIG_SLUB); |
73228c7e | 184 | |
e6e8379c | 185 | ptr = kmalloc(size, GFP_KERNEL); |
73228c7e | 186 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr); |
f33a0149 | 187 | |
73228c7e | 188 | KUNIT_EXPECT_KASAN_FAIL(test, ptr[size + OOB_TAG_OFF] = 0); |
858bdeb0 | 189 | |
e6e8379c AP |
190 | kfree(ptr); |
191 | } | |
47adccce | 192 | |
73228c7e | 193 | static void kmalloc_pagealloc_uaf(struct kunit *test) |
47adccce DV |
194 | { |
195 | char *ptr; | |
196 | size_t size = KMALLOC_MAX_CACHE_SIZE + 10; | |
197 | ||
da17e377 | 198 | KASAN_TEST_NEEDS_CONFIG_ON(test, CONFIG_SLUB); |
47adccce | 199 | |
73228c7e PA |
200 | ptr = kmalloc(size, GFP_KERNEL); |
201 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr); | |
47adccce | 202 | kfree(ptr); |
858bdeb0 | 203 | |
8fbad19b | 204 | KUNIT_EXPECT_KASAN_FAIL(test, ((volatile char *)ptr)[0]); |
47adccce DV |
205 | } |
206 | ||
73228c7e | 207 | static void kmalloc_pagealloc_invalid_free(struct kunit *test) |
47adccce DV |
208 | { |
209 | char *ptr; | |
210 | size_t size = KMALLOC_MAX_CACHE_SIZE + 10; | |
211 | ||
da17e377 | 212 | KASAN_TEST_NEEDS_CONFIG_ON(test, CONFIG_SLUB); |
47adccce | 213 | |
73228c7e PA |
214 | ptr = kmalloc(size, GFP_KERNEL); |
215 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr); | |
216 | ||
217 | KUNIT_EXPECT_KASAN_FAIL(test, kfree(ptr + 1)); | |
47adccce | 218 | } |
e6e8379c | 219 | |
858bdeb0 AK |
220 | static void pagealloc_oob_right(struct kunit *test) |
221 | { | |
222 | char *ptr; | |
223 | struct page *pages; | |
224 | size_t order = 4; | |
225 | size_t size = (1UL << (PAGE_SHIFT + order)); | |
226 | ||
227 | /* | |
228 | * With generic KASAN page allocations have no redzones, thus | |
229 | * out-of-bounds detection is not guaranteed. | |
230 | * See https://bugzilla.kernel.org/show_bug.cgi?id=210503. | |
231 | */ | |
232 | KASAN_TEST_NEEDS_CONFIG_OFF(test, CONFIG_KASAN_GENERIC); | |
233 | ||
234 | pages = alloc_pages(GFP_KERNEL, order); | |
235 | ptr = page_address(pages); | |
236 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr); | |
237 | ||
8fbad19b | 238 | KUNIT_EXPECT_KASAN_FAIL(test, ptr[0] = ptr[size]); |
858bdeb0 AK |
239 | free_pages((unsigned long)ptr, order); |
240 | } | |
241 | ||
242 | static void pagealloc_uaf(struct kunit *test) | |
243 | { | |
244 | char *ptr; | |
245 | struct page *pages; | |
246 | size_t order = 4; | |
247 | ||
248 | pages = alloc_pages(GFP_KERNEL, order); | |
249 | ptr = page_address(pages); | |
250 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr); | |
251 | free_pages((unsigned long)ptr, order); | |
252 | ||
8fbad19b | 253 | KUNIT_EXPECT_KASAN_FAIL(test, ((volatile char *)ptr)[0]); |
858bdeb0 AK |
254 | } |
255 | ||
73228c7e | 256 | static void kmalloc_large_oob_right(struct kunit *test) |
e6e8379c AP |
257 | { |
258 | char *ptr; | |
259 | size_t size = KMALLOC_MAX_CACHE_SIZE - 256; | |
0fd37925 AK |
260 | |
261 | /* | |
262 | * Allocate a chunk that is large enough, but still fits into a slab | |
e6e8379c AP |
263 | * and does not trigger the page allocator fallback in SLUB. |
264 | */ | |
3f15801c | 265 | ptr = kmalloc(size, GFP_KERNEL); |
73228c7e | 266 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr); |
3f15801c | 267 | |
73228c7e | 268 | KUNIT_EXPECT_KASAN_FAIL(test, ptr[size] = 0); |
3f15801c AR |
269 | kfree(ptr); |
270 | } | |
271 | ||
b87c28b9 AK |
272 | static void krealloc_more_oob_helper(struct kunit *test, |
273 | size_t size1, size_t size2) | |
3f15801c AR |
274 | { |
275 | char *ptr1, *ptr2; | |
b87c28b9 AK |
276 | size_t middle; |
277 | ||
278 | KUNIT_ASSERT_LT(test, size1, size2); | |
279 | middle = size1 + (size2 - size1) / 2; | |
3f15801c | 280 | |
3f15801c | 281 | ptr1 = kmalloc(size1, GFP_KERNEL); |
73228c7e | 282 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr1); |
3f15801c | 283 | |
73228c7e PA |
284 | ptr2 = krealloc(ptr1, size2, GFP_KERNEL); |
285 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr2); | |
f33a0149 | 286 | |
b87c28b9 AK |
287 | /* All offsets up to size2 must be accessible. */ |
288 | ptr2[size1 - 1] = 'x'; | |
289 | ptr2[size1] = 'x'; | |
290 | ptr2[middle] = 'x'; | |
291 | ptr2[size2 - 1] = 'x'; | |
292 | ||
293 | /* Generic mode is precise, so unaligned size2 must be inaccessible. */ | |
294 | if (IS_ENABLED(CONFIG_KASAN_GENERIC)) | |
295 | KUNIT_EXPECT_KASAN_FAIL(test, ptr2[size2] = 'x'); | |
296 | ||
297 | /* For all modes first aligned offset after size2 must be inaccessible. */ | |
298 | KUNIT_EXPECT_KASAN_FAIL(test, | |
299 | ptr2[round_up(size2, KASAN_GRANULE_SIZE)] = 'x'); | |
300 | ||
3f15801c AR |
301 | kfree(ptr2); |
302 | } | |
303 | ||
b87c28b9 AK |
304 | static void krealloc_less_oob_helper(struct kunit *test, |
305 | size_t size1, size_t size2) | |
3f15801c AR |
306 | { |
307 | char *ptr1, *ptr2; | |
b87c28b9 AK |
308 | size_t middle; |
309 | ||
310 | KUNIT_ASSERT_LT(test, size2, size1); | |
311 | middle = size2 + (size1 - size2) / 2; | |
3f15801c | 312 | |
3f15801c | 313 | ptr1 = kmalloc(size1, GFP_KERNEL); |
73228c7e | 314 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr1); |
f33a0149 | 315 | |
73228c7e PA |
316 | ptr2 = krealloc(ptr1, size2, GFP_KERNEL); |
317 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr2); | |
f33a0149 | 318 | |
b87c28b9 AK |
319 | /* Must be accessible for all modes. */ |
320 | ptr2[size2 - 1] = 'x'; | |
321 | ||
322 | /* Generic mode is precise, so unaligned size2 must be inaccessible. */ | |
323 | if (IS_ENABLED(CONFIG_KASAN_GENERIC)) | |
324 | KUNIT_EXPECT_KASAN_FAIL(test, ptr2[size2] = 'x'); | |
325 | ||
326 | /* For all modes first aligned offset after size2 must be inaccessible. */ | |
327 | KUNIT_EXPECT_KASAN_FAIL(test, | |
328 | ptr2[round_up(size2, KASAN_GRANULE_SIZE)] = 'x'); | |
329 | ||
330 | /* | |
331 | * For all modes all size2, middle, and size1 should land in separate | |
332 | * granules and thus the latter two offsets should be inaccessible. | |
333 | */ | |
334 | KUNIT_EXPECT_LE(test, round_up(size2, KASAN_GRANULE_SIZE), | |
335 | round_down(middle, KASAN_GRANULE_SIZE)); | |
336 | KUNIT_EXPECT_LE(test, round_up(middle, KASAN_GRANULE_SIZE), | |
337 | round_down(size1, KASAN_GRANULE_SIZE)); | |
338 | KUNIT_EXPECT_KASAN_FAIL(test, ptr2[middle] = 'x'); | |
339 | KUNIT_EXPECT_KASAN_FAIL(test, ptr2[size1 - 1] = 'x'); | |
340 | KUNIT_EXPECT_KASAN_FAIL(test, ptr2[size1] = 'x'); | |
341 | ||
3f15801c AR |
342 | kfree(ptr2); |
343 | } | |
344 | ||
b87c28b9 AK |
345 | static void krealloc_more_oob(struct kunit *test) |
346 | { | |
347 | krealloc_more_oob_helper(test, 201, 235); | |
348 | } | |
349 | ||
350 | static void krealloc_less_oob(struct kunit *test) | |
351 | { | |
352 | krealloc_less_oob_helper(test, 235, 201); | |
353 | } | |
354 | ||
355 | static void krealloc_pagealloc_more_oob(struct kunit *test) | |
356 | { | |
357 | /* page_alloc fallback in only implemented for SLUB. */ | |
358 | KASAN_TEST_NEEDS_CONFIG_ON(test, CONFIG_SLUB); | |
359 | ||
360 | krealloc_more_oob_helper(test, KMALLOC_MAX_CACHE_SIZE + 201, | |
361 | KMALLOC_MAX_CACHE_SIZE + 235); | |
362 | } | |
363 | ||
364 | static void krealloc_pagealloc_less_oob(struct kunit *test) | |
365 | { | |
366 | /* page_alloc fallback in only implemented for SLUB. */ | |
367 | KASAN_TEST_NEEDS_CONFIG_ON(test, CONFIG_SLUB); | |
368 | ||
369 | krealloc_less_oob_helper(test, KMALLOC_MAX_CACHE_SIZE + 235, | |
370 | KMALLOC_MAX_CACHE_SIZE + 201); | |
371 | } | |
372 | ||
26a5ca7a AK |
373 | /* |
374 | * Check that krealloc() detects a use-after-free, returns NULL, | |
375 | * and doesn't unpoison the freed object. | |
376 | */ | |
377 | static void krealloc_uaf(struct kunit *test) | |
378 | { | |
379 | char *ptr1, *ptr2; | |
380 | int size1 = 201; | |
381 | int size2 = 235; | |
382 | ||
383 | ptr1 = kmalloc(size1, GFP_KERNEL); | |
384 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr1); | |
385 | kfree(ptr1); | |
386 | ||
387 | KUNIT_EXPECT_KASAN_FAIL(test, ptr2 = krealloc(ptr1, size2, GFP_KERNEL)); | |
388 | KUNIT_ASSERT_PTR_EQ(test, (void *)ptr2, NULL); | |
389 | KUNIT_EXPECT_KASAN_FAIL(test, *(volatile char *)ptr1); | |
390 | } | |
391 | ||
73228c7e | 392 | static void kmalloc_oob_16(struct kunit *test) |
3f15801c AR |
393 | { |
394 | struct { | |
395 | u64 words[2]; | |
396 | } *ptr1, *ptr2; | |
397 | ||
58b999d7 | 398 | /* This test is specifically crafted for the generic mode. */ |
da17e377 | 399 | KASAN_TEST_NEEDS_CONFIG_ON(test, CONFIG_KASAN_GENERIC); |
58b999d7 | 400 | |
3f15801c | 401 | ptr1 = kmalloc(sizeof(*ptr1) - 3, GFP_KERNEL); |
73228c7e PA |
402 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr1); |
403 | ||
3f15801c | 404 | ptr2 = kmalloc(sizeof(*ptr2), GFP_KERNEL); |
73228c7e PA |
405 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr2); |
406 | ||
407 | KUNIT_EXPECT_KASAN_FAIL(test, *ptr1 = *ptr2); | |
3f15801c AR |
408 | kfree(ptr1); |
409 | kfree(ptr2); | |
410 | } | |
411 | ||
58b999d7 AK |
412 | static void kmalloc_uaf_16(struct kunit *test) |
413 | { | |
414 | struct { | |
415 | u64 words[2]; | |
416 | } *ptr1, *ptr2; | |
417 | ||
418 | ptr1 = kmalloc(sizeof(*ptr1), GFP_KERNEL); | |
419 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr1); | |
420 | ||
421 | ptr2 = kmalloc(sizeof(*ptr2), GFP_KERNEL); | |
422 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr2); | |
423 | kfree(ptr2); | |
424 | ||
425 | KUNIT_EXPECT_KASAN_FAIL(test, *ptr1 = *ptr2); | |
426 | kfree(ptr1); | |
427 | } | |
428 | ||
555999a0 AK |
429 | /* |
430 | * Note: in the memset tests below, the written range touches both valid and | |
431 | * invalid memory. This makes sure that the instrumentation does not only check | |
432 | * the starting address but the whole range. | |
433 | */ | |
434 | ||
73228c7e | 435 | static void kmalloc_oob_memset_2(struct kunit *test) |
f523e737 WL |
436 | { |
437 | char *ptr; | |
555999a0 | 438 | size_t size = 128 - KASAN_GRANULE_SIZE; |
f523e737 | 439 | |
f523e737 | 440 | ptr = kmalloc(size, GFP_KERNEL); |
73228c7e | 441 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr); |
f33a0149 | 442 | |
d73dad4e | 443 | OPTIMIZER_HIDE_VAR(size); |
555999a0 | 444 | KUNIT_EXPECT_KASAN_FAIL(test, memset(ptr + size - 1, 0, 2)); |
f523e737 WL |
445 | kfree(ptr); |
446 | } | |
447 | ||
73228c7e | 448 | static void kmalloc_oob_memset_4(struct kunit *test) |
f523e737 WL |
449 | { |
450 | char *ptr; | |
555999a0 | 451 | size_t size = 128 - KASAN_GRANULE_SIZE; |
f523e737 | 452 | |
f523e737 | 453 | ptr = kmalloc(size, GFP_KERNEL); |
73228c7e | 454 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr); |
f33a0149 | 455 | |
d73dad4e | 456 | OPTIMIZER_HIDE_VAR(size); |
555999a0 | 457 | KUNIT_EXPECT_KASAN_FAIL(test, memset(ptr + size - 3, 0, 4)); |
f523e737 WL |
458 | kfree(ptr); |
459 | } | |
460 | ||
73228c7e | 461 | static void kmalloc_oob_memset_8(struct kunit *test) |
f523e737 WL |
462 | { |
463 | char *ptr; | |
555999a0 | 464 | size_t size = 128 - KASAN_GRANULE_SIZE; |
f523e737 | 465 | |
f523e737 | 466 | ptr = kmalloc(size, GFP_KERNEL); |
73228c7e | 467 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr); |
f33a0149 | 468 | |
d73dad4e | 469 | OPTIMIZER_HIDE_VAR(size); |
555999a0 | 470 | KUNIT_EXPECT_KASAN_FAIL(test, memset(ptr + size - 7, 0, 8)); |
f523e737 WL |
471 | kfree(ptr); |
472 | } | |
473 | ||
73228c7e | 474 | static void kmalloc_oob_memset_16(struct kunit *test) |
f523e737 WL |
475 | { |
476 | char *ptr; | |
555999a0 | 477 | size_t size = 128 - KASAN_GRANULE_SIZE; |
f523e737 | 478 | |
f523e737 | 479 | ptr = kmalloc(size, GFP_KERNEL); |
73228c7e | 480 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr); |
f33a0149 | 481 | |
d73dad4e | 482 | OPTIMIZER_HIDE_VAR(size); |
555999a0 | 483 | KUNIT_EXPECT_KASAN_FAIL(test, memset(ptr + size - 15, 0, 16)); |
f523e737 WL |
484 | kfree(ptr); |
485 | } | |
486 | ||
73228c7e | 487 | static void kmalloc_oob_in_memset(struct kunit *test) |
3f15801c AR |
488 | { |
489 | char *ptr; | |
555999a0 | 490 | size_t size = 128 - KASAN_GRANULE_SIZE; |
3f15801c | 491 | |
3f15801c | 492 | ptr = kmalloc(size, GFP_KERNEL); |
73228c7e | 493 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr); |
f33a0149 | 494 | |
d73dad4e | 495 | OPTIMIZER_HIDE_VAR(size); |
555999a0 AK |
496 | KUNIT_EXPECT_KASAN_FAIL(test, |
497 | memset(ptr, 0, size + KASAN_GRANULE_SIZE)); | |
3f15801c AR |
498 | kfree(ptr); |
499 | } | |
500 | ||
758cabae | 501 | static void kmalloc_memmove_negative_size(struct kunit *test) |
98f3b56f WW |
502 | { |
503 | char *ptr; | |
504 | size_t size = 64; | |
d73dad4e | 505 | size_t invalid_size = -2; |
98f3b56f | 506 | |
1b0668be AK |
507 | /* |
508 | * Hardware tag-based mode doesn't check memmove for negative size. | |
509 | * As a result, this test introduces a side-effect memory corruption, | |
510 | * which can result in a crash. | |
511 | */ | |
512 | KASAN_TEST_NEEDS_CONFIG_OFF(test, CONFIG_KASAN_HW_TAGS); | |
513 | ||
98f3b56f | 514 | ptr = kmalloc(size, GFP_KERNEL); |
73228c7e | 515 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr); |
98f3b56f WW |
516 | |
517 | memset((char *)ptr, 0, 64); | |
d73dad4e | 518 | OPTIMIZER_HIDE_VAR(invalid_size); |
73228c7e PA |
519 | KUNIT_EXPECT_KASAN_FAIL(test, |
520 | memmove((char *)ptr, (char *)ptr + 4, invalid_size)); | |
98f3b56f WW |
521 | kfree(ptr); |
522 | } | |
523 | ||
758cabae PC |
524 | static void kmalloc_memmove_invalid_size(struct kunit *test) |
525 | { | |
526 | char *ptr; | |
527 | size_t size = 64; | |
528 | volatile size_t invalid_size = size; | |
529 | ||
530 | ptr = kmalloc(size, GFP_KERNEL); | |
531 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr); | |
532 | ||
98f3b56f | 533 | memset((char *)ptr, 0, 64); |
73228c7e PA |
534 | KUNIT_EXPECT_KASAN_FAIL(test, |
535 | memmove((char *)ptr, (char *)ptr + 4, invalid_size)); | |
98f3b56f WW |
536 | kfree(ptr); |
537 | } | |
538 | ||
73228c7e | 539 | static void kmalloc_uaf(struct kunit *test) |
3f15801c AR |
540 | { |
541 | char *ptr; | |
542 | size_t size = 10; | |
543 | ||
3f15801c | 544 | ptr = kmalloc(size, GFP_KERNEL); |
73228c7e | 545 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr); |
3f15801c AR |
546 | |
547 | kfree(ptr); | |
8fbad19b | 548 | KUNIT_EXPECT_KASAN_FAIL(test, ((volatile char *)ptr)[8]); |
3f15801c AR |
549 | } |
550 | ||
73228c7e | 551 | static void kmalloc_uaf_memset(struct kunit *test) |
3f15801c AR |
552 | { |
553 | char *ptr; | |
554 | size_t size = 33; | |
555 | ||
25b12a58 AK |
556 | /* |
557 | * Only generic KASAN uses quarantine, which is required to avoid a | |
558 | * kernel memory corruption this test causes. | |
559 | */ | |
560 | KASAN_TEST_NEEDS_CONFIG_ON(test, CONFIG_KASAN_GENERIC); | |
561 | ||
3f15801c | 562 | ptr = kmalloc(size, GFP_KERNEL); |
73228c7e | 563 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr); |
3f15801c AR |
564 | |
565 | kfree(ptr); | |
73228c7e | 566 | KUNIT_EXPECT_KASAN_FAIL(test, memset(ptr, 0, size)); |
3f15801c AR |
567 | } |
568 | ||
73228c7e | 569 | static void kmalloc_uaf2(struct kunit *test) |
3f15801c AR |
570 | { |
571 | char *ptr1, *ptr2; | |
572 | size_t size = 43; | |
1b1df4c4 | 573 | int counter = 0; |
3f15801c | 574 | |
1b1df4c4 | 575 | again: |
3f15801c | 576 | ptr1 = kmalloc(size, GFP_KERNEL); |
73228c7e | 577 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr1); |
3f15801c AR |
578 | |
579 | kfree(ptr1); | |
73228c7e | 580 | |
3f15801c | 581 | ptr2 = kmalloc(size, GFP_KERNEL); |
73228c7e PA |
582 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr2); |
583 | ||
1b1df4c4 AK |
584 | /* |
585 | * For tag-based KASAN ptr1 and ptr2 tags might happen to be the same. | |
586 | * Allow up to 16 attempts at generating different tags. | |
587 | */ | |
588 | if (!IS_ENABLED(CONFIG_KASAN_GENERIC) && ptr1 == ptr2 && counter++ < 16) { | |
589 | kfree(ptr2); | |
590 | goto again; | |
591 | } | |
592 | ||
8fbad19b | 593 | KUNIT_EXPECT_KASAN_FAIL(test, ((volatile char *)ptr1)[40]); |
73228c7e | 594 | KUNIT_EXPECT_PTR_NE(test, ptr1, ptr2); |
3f15801c | 595 | |
3f15801c AR |
596 | kfree(ptr2); |
597 | } | |
598 | ||
73228c7e | 599 | static void kfree_via_page(struct kunit *test) |
b92a953c MR |
600 | { |
601 | char *ptr; | |
602 | size_t size = 8; | |
603 | struct page *page; | |
604 | unsigned long offset; | |
605 | ||
b92a953c | 606 | ptr = kmalloc(size, GFP_KERNEL); |
73228c7e | 607 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr); |
b92a953c MR |
608 | |
609 | page = virt_to_page(ptr); | |
610 | offset = offset_in_page(ptr); | |
611 | kfree(page_address(page) + offset); | |
612 | } | |
613 | ||
73228c7e | 614 | static void kfree_via_phys(struct kunit *test) |
b92a953c MR |
615 | { |
616 | char *ptr; | |
617 | size_t size = 8; | |
618 | phys_addr_t phys; | |
619 | ||
b92a953c | 620 | ptr = kmalloc(size, GFP_KERNEL); |
73228c7e | 621 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr); |
b92a953c MR |
622 | |
623 | phys = virt_to_phys(ptr); | |
624 | kfree(phys_to_virt(phys)); | |
625 | } | |
626 | ||
73228c7e | 627 | static void kmem_cache_oob(struct kunit *test) |
3f15801c AR |
628 | { |
629 | char *p; | |
630 | size_t size = 200; | |
11516135 AK |
631 | struct kmem_cache *cache; |
632 | ||
633 | cache = kmem_cache_create("test_cache", size, 0, 0, NULL); | |
73228c7e | 634 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, cache); |
11516135 | 635 | |
3f15801c AR |
636 | p = kmem_cache_alloc(cache, GFP_KERNEL); |
637 | if (!p) { | |
73228c7e | 638 | kunit_err(test, "Allocation failed: %s\n", __func__); |
3f15801c AR |
639 | kmem_cache_destroy(cache); |
640 | return; | |
641 | } | |
642 | ||
73228c7e | 643 | KUNIT_EXPECT_KASAN_FAIL(test, *p = p[size + OOB_TAG_OFF]); |
11516135 | 644 | |
3f15801c AR |
645 | kmem_cache_free(cache, p); |
646 | kmem_cache_destroy(cache); | |
647 | } | |
648 | ||
11516135 | 649 | static void kmem_cache_accounted(struct kunit *test) |
0386bf38 GT |
650 | { |
651 | int i; | |
652 | char *p; | |
653 | size_t size = 200; | |
654 | struct kmem_cache *cache; | |
655 | ||
656 | cache = kmem_cache_create("test_cache", size, 0, SLAB_ACCOUNT, NULL); | |
73228c7e | 657 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, cache); |
0386bf38 | 658 | |
0386bf38 GT |
659 | /* |
660 | * Several allocations with a delay to allow for lazy per memcg kmem | |
661 | * cache creation. | |
662 | */ | |
663 | for (i = 0; i < 5; i++) { | |
664 | p = kmem_cache_alloc(cache, GFP_KERNEL); | |
dc2bf000 | 665 | if (!p) |
0386bf38 | 666 | goto free_cache; |
dc2bf000 | 667 | |
0386bf38 GT |
668 | kmem_cache_free(cache, p); |
669 | msleep(100); | |
670 | } | |
671 | ||
672 | free_cache: | |
673 | kmem_cache_destroy(cache); | |
674 | } | |
675 | ||
11516135 AK |
676 | static void kmem_cache_bulk(struct kunit *test) |
677 | { | |
678 | struct kmem_cache *cache; | |
679 | size_t size = 200; | |
680 | char *p[10]; | |
681 | bool ret; | |
682 | int i; | |
683 | ||
684 | cache = kmem_cache_create("test_cache", size, 0, 0, NULL); | |
685 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, cache); | |
686 | ||
687 | ret = kmem_cache_alloc_bulk(cache, GFP_KERNEL, ARRAY_SIZE(p), (void **)&p); | |
688 | if (!ret) { | |
689 | kunit_err(test, "Allocation failed: %s\n", __func__); | |
690 | kmem_cache_destroy(cache); | |
691 | return; | |
692 | } | |
693 | ||
694 | for (i = 0; i < ARRAY_SIZE(p); i++) | |
695 | p[i][0] = p[i][size - 1] = 42; | |
696 | ||
697 | kmem_cache_free_bulk(cache, ARRAY_SIZE(p), (void **)&p); | |
698 | kmem_cache_destroy(cache); | |
699 | } | |
700 | ||
3f15801c AR |
701 | static char global_array[10]; |
702 | ||
73228c7e | 703 | static void kasan_global_oob(struct kunit *test) |
3f15801c | 704 | { |
f649dc0e PC |
705 | /* |
706 | * Deliberate out-of-bounds access. To prevent CONFIG_UBSAN_LOCAL_BOUNDS | |
53b0fe36 | 707 | * from failing here and panicking the kernel, access the array via a |
f649dc0e PC |
708 | * volatile pointer, which will prevent the compiler from being able to |
709 | * determine the array bounds. | |
710 | * | |
711 | * This access uses a volatile pointer to char (char *volatile) rather | |
712 | * than the more conventional pointer to volatile char (volatile char *) | |
713 | * because we want to prevent the compiler from making inferences about | |
714 | * the pointer itself (i.e. its array bounds), not the data that it | |
715 | * refers to. | |
716 | */ | |
717 | char *volatile array = global_array; | |
718 | char *p = &array[ARRAY_SIZE(global_array) + 3]; | |
3f15801c | 719 | |
58b999d7 | 720 | /* Only generic mode instruments globals. */ |
da17e377 | 721 | KASAN_TEST_NEEDS_CONFIG_ON(test, CONFIG_KASAN_GENERIC); |
58b999d7 | 722 | |
73228c7e | 723 | KUNIT_EXPECT_KASAN_FAIL(test, *(volatile char *)p); |
3f15801c AR |
724 | } |
725 | ||
611806b4 | 726 | /* Check that ksize() makes the whole object accessible. */ |
73228c7e | 727 | static void ksize_unpoisons_memory(struct kunit *test) |
96fe805f AP |
728 | { |
729 | char *ptr; | |
48c23239 | 730 | size_t size = 123, real_size; |
96fe805f | 731 | |
96fe805f | 732 | ptr = kmalloc(size, GFP_KERNEL); |
73228c7e | 733 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr); |
96fe805f | 734 | real_size = ksize(ptr); |
0fd37925 AK |
735 | |
736 | /* This access shouldn't trigger a KASAN report. */ | |
96fe805f | 737 | ptr[size] = 'x'; |
0fd37925 AK |
738 | |
739 | /* This one must. */ | |
8fbad19b | 740 | KUNIT_EXPECT_KASAN_FAIL(test, ((volatile char *)ptr)[real_size]); |
0fd37925 | 741 | |
96fe805f AP |
742 | kfree(ptr); |
743 | } | |
744 | ||
611806b4 AK |
745 | /* |
746 | * Check that a use-after-free is detected by ksize() and via normal accesses | |
747 | * after it. | |
748 | */ | |
749 | static void ksize_uaf(struct kunit *test) | |
750 | { | |
751 | char *ptr; | |
752 | int size = 128 - KASAN_GRANULE_SIZE; | |
753 | ||
754 | ptr = kmalloc(size, GFP_KERNEL); | |
755 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr); | |
756 | kfree(ptr); | |
757 | ||
758 | KUNIT_EXPECT_KASAN_FAIL(test, ksize(ptr)); | |
b38fcca3 AK |
759 | KUNIT_EXPECT_KASAN_FAIL(test, ((volatile char *)ptr)[0]); |
760 | KUNIT_EXPECT_KASAN_FAIL(test, ((volatile char *)ptr)[size]); | |
611806b4 AK |
761 | } |
762 | ||
73228c7e | 763 | static void kasan_stack_oob(struct kunit *test) |
eae08dca | 764 | { |
73228c7e | 765 | char stack_array[10]; |
f649dc0e PC |
766 | /* See comment in kasan_global_oob. */ |
767 | char *volatile array = stack_array; | |
768 | char *p = &array[ARRAY_SIZE(stack_array) + OOB_TAG_OFF]; | |
eae08dca | 769 | |
da17e377 | 770 | KASAN_TEST_NEEDS_CONFIG_ON(test, CONFIG_KASAN_STACK); |
eae08dca | 771 | |
73228c7e | 772 | KUNIT_EXPECT_KASAN_FAIL(test, *(volatile char *)p); |
eae08dca AR |
773 | } |
774 | ||
73228c7e | 775 | static void kasan_alloca_oob_left(struct kunit *test) |
00a14294 PL |
776 | { |
777 | volatile int i = 10; | |
778 | char alloca_array[i]; | |
f649dc0e PC |
779 | /* See comment in kasan_global_oob. */ |
780 | char *volatile array = alloca_array; | |
781 | char *p = array - 1; | |
00a14294 | 782 | |
58b999d7 | 783 | /* Only generic mode instruments dynamic allocas. */ |
da17e377 AK |
784 | KASAN_TEST_NEEDS_CONFIG_ON(test, CONFIG_KASAN_GENERIC); |
785 | KASAN_TEST_NEEDS_CONFIG_ON(test, CONFIG_KASAN_STACK); | |
73228c7e PA |
786 | |
787 | KUNIT_EXPECT_KASAN_FAIL(test, *(volatile char *)p); | |
00a14294 PL |
788 | } |
789 | ||
73228c7e | 790 | static void kasan_alloca_oob_right(struct kunit *test) |
00a14294 PL |
791 | { |
792 | volatile int i = 10; | |
793 | char alloca_array[i]; | |
f649dc0e PC |
794 | /* See comment in kasan_global_oob. */ |
795 | char *volatile array = alloca_array; | |
796 | char *p = array + i; | |
00a14294 | 797 | |
58b999d7 | 798 | /* Only generic mode instruments dynamic allocas. */ |
da17e377 AK |
799 | KASAN_TEST_NEEDS_CONFIG_ON(test, CONFIG_KASAN_GENERIC); |
800 | KASAN_TEST_NEEDS_CONFIG_ON(test, CONFIG_KASAN_STACK); | |
73228c7e PA |
801 | |
802 | KUNIT_EXPECT_KASAN_FAIL(test, *(volatile char *)p); | |
00a14294 PL |
803 | } |
804 | ||
73228c7e | 805 | static void kmem_cache_double_free(struct kunit *test) |
b1d57289 DV |
806 | { |
807 | char *p; | |
808 | size_t size = 200; | |
809 | struct kmem_cache *cache; | |
810 | ||
811 | cache = kmem_cache_create("test_cache", size, 0, 0, NULL); | |
73228c7e PA |
812 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, cache); |
813 | ||
b1d57289 DV |
814 | p = kmem_cache_alloc(cache, GFP_KERNEL); |
815 | if (!p) { | |
73228c7e | 816 | kunit_err(test, "Allocation failed: %s\n", __func__); |
b1d57289 DV |
817 | kmem_cache_destroy(cache); |
818 | return; | |
819 | } | |
820 | ||
821 | kmem_cache_free(cache, p); | |
73228c7e | 822 | KUNIT_EXPECT_KASAN_FAIL(test, kmem_cache_free(cache, p)); |
b1d57289 DV |
823 | kmem_cache_destroy(cache); |
824 | } | |
825 | ||
73228c7e | 826 | static void kmem_cache_invalid_free(struct kunit *test) |
b1d57289 DV |
827 | { |
828 | char *p; | |
829 | size_t size = 200; | |
830 | struct kmem_cache *cache; | |
831 | ||
832 | cache = kmem_cache_create("test_cache", size, 0, SLAB_TYPESAFE_BY_RCU, | |
833 | NULL); | |
73228c7e PA |
834 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, cache); |
835 | ||
b1d57289 DV |
836 | p = kmem_cache_alloc(cache, GFP_KERNEL); |
837 | if (!p) { | |
73228c7e | 838 | kunit_err(test, "Allocation failed: %s\n", __func__); |
b1d57289 DV |
839 | kmem_cache_destroy(cache); |
840 | return; | |
841 | } | |
842 | ||
0fd37925 | 843 | /* Trigger invalid free, the object doesn't get freed. */ |
73228c7e | 844 | KUNIT_EXPECT_KASAN_FAIL(test, kmem_cache_free(cache, p + 1)); |
91c93ed0 AK |
845 | |
846 | /* | |
847 | * Properly free the object to prevent the "Objects remaining in | |
848 | * test_cache on __kmem_cache_shutdown" BUG failure. | |
849 | */ | |
850 | kmem_cache_free(cache, p); | |
851 | ||
b1d57289 DV |
852 | kmem_cache_destroy(cache); |
853 | } | |
854 | ||
73228c7e | 855 | static void kasan_memchr(struct kunit *test) |
0c96350a AR |
856 | { |
857 | char *ptr; | |
858 | size_t size = 24; | |
859 | ||
0fd37925 AK |
860 | /* |
861 | * str* functions are not instrumented with CONFIG_AMD_MEM_ENCRYPT. | |
862 | * See https://bugzilla.kernel.org/show_bug.cgi?id=206337 for details. | |
863 | */ | |
da17e377 | 864 | KASAN_TEST_NEEDS_CONFIG_OFF(test, CONFIG_AMD_MEM_ENCRYPT); |
73228c7e | 865 | |
58b999d7 AK |
866 | if (OOB_TAG_OFF) |
867 | size = round_up(size, OOB_TAG_OFF); | |
868 | ||
73228c7e PA |
869 | ptr = kmalloc(size, GFP_KERNEL | __GFP_ZERO); |
870 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr); | |
871 | ||
cab71f74 | 872 | OPTIMIZER_HIDE_VAR(size); |
73228c7e PA |
873 | KUNIT_EXPECT_KASAN_FAIL(test, |
874 | kasan_ptr_result = memchr(ptr, '1', size + 1)); | |
0c96350a | 875 | |
0c96350a AR |
876 | kfree(ptr); |
877 | } | |
878 | ||
73228c7e | 879 | static void kasan_memcmp(struct kunit *test) |
0c96350a AR |
880 | { |
881 | char *ptr; | |
882 | size_t size = 24; | |
883 | int arr[9]; | |
884 | ||
0fd37925 AK |
885 | /* |
886 | * str* functions are not instrumented with CONFIG_AMD_MEM_ENCRYPT. | |
887 | * See https://bugzilla.kernel.org/show_bug.cgi?id=206337 for details. | |
888 | */ | |
da17e377 | 889 | KASAN_TEST_NEEDS_CONFIG_OFF(test, CONFIG_AMD_MEM_ENCRYPT); |
0c96350a | 890 | |
58b999d7 AK |
891 | if (OOB_TAG_OFF) |
892 | size = round_up(size, OOB_TAG_OFF); | |
893 | ||
73228c7e PA |
894 | ptr = kmalloc(size, GFP_KERNEL | __GFP_ZERO); |
895 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr); | |
0c96350a | 896 | memset(arr, 0, sizeof(arr)); |
73228c7e | 897 | |
cab71f74 | 898 | OPTIMIZER_HIDE_VAR(size); |
73228c7e PA |
899 | KUNIT_EXPECT_KASAN_FAIL(test, |
900 | kasan_int_result = memcmp(ptr, arr, size+1)); | |
0c96350a AR |
901 | kfree(ptr); |
902 | } | |
903 | ||
73228c7e | 904 | static void kasan_strings(struct kunit *test) |
0c96350a AR |
905 | { |
906 | char *ptr; | |
907 | size_t size = 24; | |
908 | ||
0fd37925 AK |
909 | /* |
910 | * str* functions are not instrumented with CONFIG_AMD_MEM_ENCRYPT. | |
911 | * See https://bugzilla.kernel.org/show_bug.cgi?id=206337 for details. | |
912 | */ | |
da17e377 | 913 | KASAN_TEST_NEEDS_CONFIG_OFF(test, CONFIG_AMD_MEM_ENCRYPT); |
73228c7e PA |
914 | |
915 | ptr = kmalloc(size, GFP_KERNEL | __GFP_ZERO); | |
916 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr); | |
0c96350a AR |
917 | |
918 | kfree(ptr); | |
919 | ||
920 | /* | |
921 | * Try to cause only 1 invalid access (less spam in dmesg). | |
922 | * For that we need ptr to point to zeroed byte. | |
923 | * Skip metadata that could be stored in freed object so ptr | |
924 | * will likely point to zeroed byte. | |
925 | */ | |
926 | ptr += 16; | |
73228c7e | 927 | KUNIT_EXPECT_KASAN_FAIL(test, kasan_ptr_result = strchr(ptr, '1')); |
0c96350a | 928 | |
73228c7e | 929 | KUNIT_EXPECT_KASAN_FAIL(test, kasan_ptr_result = strrchr(ptr, '1')); |
0c96350a | 930 | |
73228c7e | 931 | KUNIT_EXPECT_KASAN_FAIL(test, kasan_int_result = strcmp(ptr, "2")); |
0c96350a | 932 | |
73228c7e | 933 | KUNIT_EXPECT_KASAN_FAIL(test, kasan_int_result = strncmp(ptr, "2", 1)); |
0c96350a | 934 | |
73228c7e | 935 | KUNIT_EXPECT_KASAN_FAIL(test, kasan_int_result = strlen(ptr)); |
0c96350a | 936 | |
73228c7e | 937 | KUNIT_EXPECT_KASAN_FAIL(test, kasan_int_result = strnlen(ptr, 1)); |
0c96350a AR |
938 | } |
939 | ||
58b999d7 AK |
940 | static void kasan_bitops_modify(struct kunit *test, int nr, void *addr) |
941 | { | |
942 | KUNIT_EXPECT_KASAN_FAIL(test, set_bit(nr, addr)); | |
943 | KUNIT_EXPECT_KASAN_FAIL(test, __set_bit(nr, addr)); | |
944 | KUNIT_EXPECT_KASAN_FAIL(test, clear_bit(nr, addr)); | |
945 | KUNIT_EXPECT_KASAN_FAIL(test, __clear_bit(nr, addr)); | |
946 | KUNIT_EXPECT_KASAN_FAIL(test, clear_bit_unlock(nr, addr)); | |
947 | KUNIT_EXPECT_KASAN_FAIL(test, __clear_bit_unlock(nr, addr)); | |
948 | KUNIT_EXPECT_KASAN_FAIL(test, change_bit(nr, addr)); | |
949 | KUNIT_EXPECT_KASAN_FAIL(test, __change_bit(nr, addr)); | |
950 | } | |
951 | ||
952 | static void kasan_bitops_test_and_modify(struct kunit *test, int nr, void *addr) | |
953 | { | |
954 | KUNIT_EXPECT_KASAN_FAIL(test, test_and_set_bit(nr, addr)); | |
955 | KUNIT_EXPECT_KASAN_FAIL(test, __test_and_set_bit(nr, addr)); | |
956 | KUNIT_EXPECT_KASAN_FAIL(test, test_and_set_bit_lock(nr, addr)); | |
957 | KUNIT_EXPECT_KASAN_FAIL(test, test_and_clear_bit(nr, addr)); | |
958 | KUNIT_EXPECT_KASAN_FAIL(test, __test_and_clear_bit(nr, addr)); | |
959 | KUNIT_EXPECT_KASAN_FAIL(test, test_and_change_bit(nr, addr)); | |
960 | KUNIT_EXPECT_KASAN_FAIL(test, __test_and_change_bit(nr, addr)); | |
961 | KUNIT_EXPECT_KASAN_FAIL(test, kasan_int_result = test_bit(nr, addr)); | |
962 | ||
963 | #if defined(clear_bit_unlock_is_negative_byte) | |
964 | KUNIT_EXPECT_KASAN_FAIL(test, kasan_int_result = | |
965 | clear_bit_unlock_is_negative_byte(nr, addr)); | |
966 | #endif | |
967 | } | |
968 | ||
969 | static void kasan_bitops_generic(struct kunit *test) | |
19a33ca6 | 970 | { |
58b999d7 AK |
971 | long *bits; |
972 | ||
973 | /* This test is specifically crafted for the generic mode. */ | |
da17e377 | 974 | KASAN_TEST_NEEDS_CONFIG_ON(test, CONFIG_KASAN_GENERIC); |
58b999d7 | 975 | |
19a33ca6 | 976 | /* |
0fd37925 | 977 | * Allocate 1 more byte, which causes kzalloc to round up to 16 bytes; |
19a33ca6 ME |
978 | * this way we do not actually corrupt other memory. |
979 | */ | |
58b999d7 | 980 | bits = kzalloc(sizeof(*bits) + 1, GFP_KERNEL); |
73228c7e | 981 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, bits); |
19a33ca6 ME |
982 | |
983 | /* | |
984 | * Below calls try to access bit within allocated memory; however, the | |
985 | * below accesses are still out-of-bounds, since bitops are defined to | |
986 | * operate on the whole long the bit is in. | |
987 | */ | |
58b999d7 | 988 | kasan_bitops_modify(test, BITS_PER_LONG, bits); |
19a33ca6 ME |
989 | |
990 | /* | |
991 | * Below calls try to access bit beyond allocated memory. | |
992 | */ | |
58b999d7 | 993 | kasan_bitops_test_and_modify(test, BITS_PER_LONG + BITS_PER_BYTE, bits); |
19a33ca6 | 994 | |
58b999d7 AK |
995 | kfree(bits); |
996 | } | |
19a33ca6 | 997 | |
58b999d7 AK |
998 | static void kasan_bitops_tags(struct kunit *test) |
999 | { | |
1000 | long *bits; | |
19a33ca6 | 1001 | |
da17e377 AK |
1002 | /* This test is specifically crafted for tag-based modes. */ |
1003 | KASAN_TEST_NEEDS_CONFIG_OFF(test, CONFIG_KASAN_GENERIC); | |
19a33ca6 | 1004 | |
e66e1799 AK |
1005 | /* kmalloc-64 cache will be used and the last 16 bytes will be the redzone. */ |
1006 | bits = kzalloc(48, GFP_KERNEL); | |
58b999d7 | 1007 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, bits); |
19a33ca6 | 1008 | |
e66e1799 AK |
1009 | /* Do the accesses past the 48 allocated bytes, but within the redone. */ |
1010 | kasan_bitops_modify(test, BITS_PER_LONG, (void *)bits + 48); | |
1011 | kasan_bitops_test_and_modify(test, BITS_PER_LONG + BITS_PER_BYTE, (void *)bits + 48); | |
19a33ca6 | 1012 | |
19a33ca6 ME |
1013 | kfree(bits); |
1014 | } | |
1015 | ||
73228c7e | 1016 | static void kmalloc_double_kzfree(struct kunit *test) |
bb104ed7 ME |
1017 | { |
1018 | char *ptr; | |
1019 | size_t size = 16; | |
1020 | ||
bb104ed7 | 1021 | ptr = kmalloc(size, GFP_KERNEL); |
73228c7e | 1022 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr); |
bb104ed7 | 1023 | |
453431a5 | 1024 | kfree_sensitive(ptr); |
73228c7e | 1025 | KUNIT_EXPECT_KASAN_FAIL(test, kfree_sensitive(ptr)); |
bb104ed7 ME |
1026 | } |
1027 | ||
73228c7e | 1028 | static void vmalloc_oob(struct kunit *test) |
06513916 DA |
1029 | { |
1030 | void *area; | |
1031 | ||
da17e377 | 1032 | KASAN_TEST_NEEDS_CONFIG_ON(test, CONFIG_KASAN_VMALLOC); |
06513916 DA |
1033 | |
1034 | /* | |
1035 | * We have to be careful not to hit the guard page. | |
1036 | * The MMU will catch that and crash us. | |
1037 | */ | |
1038 | area = vmalloc(3000); | |
73228c7e | 1039 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, area); |
06513916 | 1040 | |
73228c7e | 1041 | KUNIT_EXPECT_KASAN_FAIL(test, ((volatile char *)area)[3100]); |
06513916 DA |
1042 | vfree(area); |
1043 | } | |
387d6e46 | 1044 | |
573a4809 AK |
1045 | /* |
1046 | * Check that the assigned pointer tag falls within the [KASAN_TAG_MIN, | |
1047 | * KASAN_TAG_KERNEL) range (note: excluding the match-all tag) for tag-based | |
1048 | * modes. | |
1049 | */ | |
1050 | static void match_all_not_assigned(struct kunit *test) | |
1051 | { | |
1052 | char *ptr; | |
1053 | struct page *pages; | |
1054 | int i, size, order; | |
1055 | ||
1056 | KASAN_TEST_NEEDS_CONFIG_OFF(test, CONFIG_KASAN_GENERIC); | |
1057 | ||
1058 | for (i = 0; i < 256; i++) { | |
1059 | size = (get_random_int() % 1024) + 1; | |
1060 | ptr = kmalloc(size, GFP_KERNEL); | |
1061 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr); | |
1062 | KUNIT_EXPECT_GE(test, (u8)get_tag(ptr), (u8)KASAN_TAG_MIN); | |
1063 | KUNIT_EXPECT_LT(test, (u8)get_tag(ptr), (u8)KASAN_TAG_KERNEL); | |
1064 | kfree(ptr); | |
1065 | } | |
1066 | ||
1067 | for (i = 0; i < 256; i++) { | |
1068 | order = (get_random_int() % 4) + 1; | |
1069 | pages = alloc_pages(GFP_KERNEL, order); | |
1070 | ptr = page_address(pages); | |
1071 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr); | |
1072 | KUNIT_EXPECT_GE(test, (u8)get_tag(ptr), (u8)KASAN_TAG_MIN); | |
1073 | KUNIT_EXPECT_LT(test, (u8)get_tag(ptr), (u8)KASAN_TAG_KERNEL); | |
1074 | free_pages((unsigned long)ptr, order); | |
1075 | } | |
1076 | } | |
1077 | ||
1078 | /* Check that 0xff works as a match-all pointer tag for tag-based modes. */ | |
1079 | static void match_all_ptr_tag(struct kunit *test) | |
1080 | { | |
1081 | char *ptr; | |
1082 | u8 tag; | |
1083 | ||
1084 | KASAN_TEST_NEEDS_CONFIG_OFF(test, CONFIG_KASAN_GENERIC); | |
1085 | ||
1086 | ptr = kmalloc(128, GFP_KERNEL); | |
1087 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr); | |
1088 | ||
1089 | /* Backup the assigned tag. */ | |
1090 | tag = get_tag(ptr); | |
1091 | KUNIT_EXPECT_NE(test, tag, (u8)KASAN_TAG_KERNEL); | |
1092 | ||
1093 | /* Reset the tag to 0xff.*/ | |
1094 | ptr = set_tag(ptr, KASAN_TAG_KERNEL); | |
1095 | ||
1096 | /* This access shouldn't trigger a KASAN report. */ | |
1097 | *ptr = 0; | |
1098 | ||
1099 | /* Recover the pointer tag and free. */ | |
1100 | ptr = set_tag(ptr, tag); | |
1101 | kfree(ptr); | |
1102 | } | |
1103 | ||
1104 | /* Check that there are no match-all memory tags for tag-based modes. */ | |
1105 | static void match_all_mem_tag(struct kunit *test) | |
1106 | { | |
1107 | char *ptr; | |
1108 | int tag; | |
1109 | ||
1110 | KASAN_TEST_NEEDS_CONFIG_OFF(test, CONFIG_KASAN_GENERIC); | |
1111 | ||
1112 | ptr = kmalloc(128, GFP_KERNEL); | |
1113 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr); | |
1114 | KUNIT_EXPECT_NE(test, (u8)get_tag(ptr), (u8)KASAN_TAG_KERNEL); | |
1115 | ||
1116 | /* For each possible tag value not matching the pointer tag. */ | |
1117 | for (tag = KASAN_TAG_MIN; tag <= KASAN_TAG_KERNEL; tag++) { | |
1118 | if (tag == get_tag(ptr)) | |
1119 | continue; | |
1120 | ||
1121 | /* Mark the first memory granule with the chosen memory tag. */ | |
aa5c219c | 1122 | kasan_poison(ptr, KASAN_GRANULE_SIZE, (u8)tag, false); |
573a4809 AK |
1123 | |
1124 | /* This access must cause a KASAN report. */ | |
1125 | KUNIT_EXPECT_KASAN_FAIL(test, *ptr = 0); | |
1126 | } | |
1127 | ||
1128 | /* Recover the memory tag and free. */ | |
aa5c219c | 1129 | kasan_poison(ptr, KASAN_GRANULE_SIZE, get_tag(ptr), false); |
573a4809 AK |
1130 | kfree(ptr); |
1131 | } | |
1132 | ||
73228c7e PA |
1133 | static struct kunit_case kasan_kunit_test_cases[] = { |
1134 | KUNIT_CASE(kmalloc_oob_right), | |
1135 | KUNIT_CASE(kmalloc_oob_left), | |
1136 | KUNIT_CASE(kmalloc_node_oob_right), | |
1137 | KUNIT_CASE(kmalloc_pagealloc_oob_right), | |
1138 | KUNIT_CASE(kmalloc_pagealloc_uaf), | |
1139 | KUNIT_CASE(kmalloc_pagealloc_invalid_free), | |
858bdeb0 AK |
1140 | KUNIT_CASE(pagealloc_oob_right), |
1141 | KUNIT_CASE(pagealloc_uaf), | |
73228c7e | 1142 | KUNIT_CASE(kmalloc_large_oob_right), |
b87c28b9 AK |
1143 | KUNIT_CASE(krealloc_more_oob), |
1144 | KUNIT_CASE(krealloc_less_oob), | |
1145 | KUNIT_CASE(krealloc_pagealloc_more_oob), | |
1146 | KUNIT_CASE(krealloc_pagealloc_less_oob), | |
26a5ca7a | 1147 | KUNIT_CASE(krealloc_uaf), |
73228c7e | 1148 | KUNIT_CASE(kmalloc_oob_16), |
58b999d7 | 1149 | KUNIT_CASE(kmalloc_uaf_16), |
73228c7e PA |
1150 | KUNIT_CASE(kmalloc_oob_in_memset), |
1151 | KUNIT_CASE(kmalloc_oob_memset_2), | |
1152 | KUNIT_CASE(kmalloc_oob_memset_4), | |
1153 | KUNIT_CASE(kmalloc_oob_memset_8), | |
1154 | KUNIT_CASE(kmalloc_oob_memset_16), | |
758cabae | 1155 | KUNIT_CASE(kmalloc_memmove_negative_size), |
73228c7e PA |
1156 | KUNIT_CASE(kmalloc_memmove_invalid_size), |
1157 | KUNIT_CASE(kmalloc_uaf), | |
1158 | KUNIT_CASE(kmalloc_uaf_memset), | |
1159 | KUNIT_CASE(kmalloc_uaf2), | |
1160 | KUNIT_CASE(kfree_via_page), | |
1161 | KUNIT_CASE(kfree_via_phys), | |
1162 | KUNIT_CASE(kmem_cache_oob), | |
11516135 AK |
1163 | KUNIT_CASE(kmem_cache_accounted), |
1164 | KUNIT_CASE(kmem_cache_bulk), | |
73228c7e PA |
1165 | KUNIT_CASE(kasan_global_oob), |
1166 | KUNIT_CASE(kasan_stack_oob), | |
1167 | KUNIT_CASE(kasan_alloca_oob_left), | |
1168 | KUNIT_CASE(kasan_alloca_oob_right), | |
1169 | KUNIT_CASE(ksize_unpoisons_memory), | |
611806b4 | 1170 | KUNIT_CASE(ksize_uaf), |
73228c7e PA |
1171 | KUNIT_CASE(kmem_cache_double_free), |
1172 | KUNIT_CASE(kmem_cache_invalid_free), | |
1173 | KUNIT_CASE(kasan_memchr), | |
1174 | KUNIT_CASE(kasan_memcmp), | |
1175 | KUNIT_CASE(kasan_strings), | |
58b999d7 AK |
1176 | KUNIT_CASE(kasan_bitops_generic), |
1177 | KUNIT_CASE(kasan_bitops_tags), | |
73228c7e PA |
1178 | KUNIT_CASE(kmalloc_double_kzfree), |
1179 | KUNIT_CASE(vmalloc_oob), | |
573a4809 AK |
1180 | KUNIT_CASE(match_all_not_assigned), |
1181 | KUNIT_CASE(match_all_ptr_tag), | |
1182 | KUNIT_CASE(match_all_mem_tag), | |
73228c7e PA |
1183 | {} |
1184 | }; | |
1185 | ||
1186 | static struct kunit_suite kasan_kunit_test_suite = { | |
1187 | .name = "kasan", | |
1188 | .init = kasan_test_init, | |
1189 | .test_cases = kasan_kunit_test_cases, | |
1190 | .exit = kasan_test_exit, | |
1191 | }; | |
1192 | ||
1193 | kunit_test_suite(kasan_kunit_test_suite); | |
3f15801c | 1194 | |
3f15801c | 1195 | MODULE_LICENSE("GPL"); |