diff options
Diffstat (limited to 'lib/test_kasan.c')
-rw-r--r-- | lib/test_kasan.c | 107 |
1 files changed, 106 insertions, 1 deletions
diff --git a/lib/test_kasan.c b/lib/test_kasan.c index ef1a3ac1397e..98854a64b014 100644 --- a/lib/test_kasan.c +++ b/lib/test_kasan.c | |||
@@ -94,6 +94,37 @@ static noinline void __init kmalloc_pagealloc_oob_right(void) | |||
94 | ptr[size] = 0; | 94 | ptr[size] = 0; |
95 | kfree(ptr); | 95 | kfree(ptr); |
96 | } | 96 | } |
97 | |||
98 | static noinline void __init kmalloc_pagealloc_uaf(void) | ||
99 | { | ||
100 | char *ptr; | ||
101 | size_t size = KMALLOC_MAX_CACHE_SIZE + 10; | ||
102 | |||
103 | pr_info("kmalloc pagealloc allocation: use-after-free\n"); | ||
104 | ptr = kmalloc(size, GFP_KERNEL); | ||
105 | if (!ptr) { | ||
106 | pr_err("Allocation failed\n"); | ||
107 | return; | ||
108 | } | ||
109 | |||
110 | kfree(ptr); | ||
111 | ptr[0] = 0; | ||
112 | } | ||
113 | |||
114 | static noinline void __init kmalloc_pagealloc_invalid_free(void) | ||
115 | { | ||
116 | char *ptr; | ||
117 | size_t size = KMALLOC_MAX_CACHE_SIZE + 10; | ||
118 | |||
119 | pr_info("kmalloc pagealloc allocation: invalid-free\n"); | ||
120 | ptr = kmalloc(size, GFP_KERNEL); | ||
121 | if (!ptr) { | ||
122 | pr_err("Allocation failed\n"); | ||
123 | return; | ||
124 | } | ||
125 | |||
126 | kfree(ptr + 1); | ||
127 | } | ||
97 | #endif | 128 | #endif |
98 | 129 | ||
99 | static noinline void __init kmalloc_large_oob_right(void) | 130 | static noinline void __init kmalloc_large_oob_right(void) |
@@ -388,7 +419,7 @@ static noinline void __init kasan_stack_oob(void) | |||
388 | static noinline void __init ksize_unpoisons_memory(void) | 419 | static noinline void __init ksize_unpoisons_memory(void) |
389 | { | 420 | { |
390 | char *ptr; | 421 | char *ptr; |
391 | size_t size = 123, real_size = size; | 422 | size_t size = 123, real_size; |
392 | 423 | ||
393 | pr_info("ksize() unpoisons the whole allocated chunk\n"); | 424 | pr_info("ksize() unpoisons the whole allocated chunk\n"); |
394 | ptr = kmalloc(size, GFP_KERNEL); | 425 | ptr = kmalloc(size, GFP_KERNEL); |
@@ -472,6 +503,74 @@ static noinline void __init use_after_scope_test(void) | |||
472 | p[1023] = 1; | 503 | p[1023] = 1; |
473 | } | 504 | } |
474 | 505 | ||
506 | static noinline void __init kasan_alloca_oob_left(void) | ||
507 | { | ||
508 | volatile int i = 10; | ||
509 | char alloca_array[i]; | ||
510 | char *p = alloca_array - 1; | ||
511 | |||
512 | pr_info("out-of-bounds to left on alloca\n"); | ||
513 | *(volatile char *)p; | ||
514 | } | ||
515 | |||
516 | static noinline void __init kasan_alloca_oob_right(void) | ||
517 | { | ||
518 | volatile int i = 10; | ||
519 | char alloca_array[i]; | ||
520 | char *p = alloca_array + i; | ||
521 | |||
522 | pr_info("out-of-bounds to right on alloca\n"); | ||
523 | *(volatile char *)p; | ||
524 | } | ||
525 | |||
526 | static noinline void __init kmem_cache_double_free(void) | ||
527 | { | ||
528 | char *p; | ||
529 | size_t size = 200; | ||
530 | struct kmem_cache *cache; | ||
531 | |||
532 | cache = kmem_cache_create("test_cache", size, 0, 0, NULL); | ||
533 | if (!cache) { | ||
534 | pr_err("Cache allocation failed\n"); | ||
535 | return; | ||
536 | } | ||
537 | pr_info("double-free on heap object\n"); | ||
538 | p = kmem_cache_alloc(cache, GFP_KERNEL); | ||
539 | if (!p) { | ||
540 | pr_err("Allocation failed\n"); | ||
541 | kmem_cache_destroy(cache); | ||
542 | return; | ||
543 | } | ||
544 | |||
545 | kmem_cache_free(cache, p); | ||
546 | kmem_cache_free(cache, p); | ||
547 | kmem_cache_destroy(cache); | ||
548 | } | ||
549 | |||
550 | static noinline void __init kmem_cache_invalid_free(void) | ||
551 | { | ||
552 | char *p; | ||
553 | size_t size = 200; | ||
554 | struct kmem_cache *cache; | ||
555 | |||
556 | cache = kmem_cache_create("test_cache", size, 0, SLAB_TYPESAFE_BY_RCU, | ||
557 | NULL); | ||
558 | if (!cache) { | ||
559 | pr_err("Cache allocation failed\n"); | ||
560 | return; | ||
561 | } | ||
562 | pr_info("invalid-free of heap object\n"); | ||
563 | p = kmem_cache_alloc(cache, GFP_KERNEL); | ||
564 | if (!p) { | ||
565 | pr_err("Allocation failed\n"); | ||
566 | kmem_cache_destroy(cache); | ||
567 | return; | ||
568 | } | ||
569 | |||
570 | kmem_cache_free(cache, p + 1); | ||
571 | kmem_cache_destroy(cache); | ||
572 | } | ||
573 | |||
475 | static int __init kmalloc_tests_init(void) | 574 | static int __init kmalloc_tests_init(void) |
476 | { | 575 | { |
477 | /* | 576 | /* |
@@ -485,6 +584,8 @@ static int __init kmalloc_tests_init(void) | |||
485 | kmalloc_node_oob_right(); | 584 | kmalloc_node_oob_right(); |
486 | #ifdef CONFIG_SLUB | 585 | #ifdef CONFIG_SLUB |
487 | kmalloc_pagealloc_oob_right(); | 586 | kmalloc_pagealloc_oob_right(); |
587 | kmalloc_pagealloc_uaf(); | ||
588 | kmalloc_pagealloc_invalid_free(); | ||
488 | #endif | 589 | #endif |
489 | kmalloc_large_oob_right(); | 590 | kmalloc_large_oob_right(); |
490 | kmalloc_oob_krealloc_more(); | 591 | kmalloc_oob_krealloc_more(); |
@@ -502,9 +603,13 @@ static int __init kmalloc_tests_init(void) | |||
502 | memcg_accounted_kmem_cache(); | 603 | memcg_accounted_kmem_cache(); |
503 | kasan_stack_oob(); | 604 | kasan_stack_oob(); |
504 | kasan_global_oob(); | 605 | kasan_global_oob(); |
606 | kasan_alloca_oob_left(); | ||
607 | kasan_alloca_oob_right(); | ||
505 | ksize_unpoisons_memory(); | 608 | ksize_unpoisons_memory(); |
506 | copy_user_test(); | 609 | copy_user_test(); |
507 | use_after_scope_test(); | 610 | use_after_scope_test(); |
611 | kmem_cache_double_free(); | ||
612 | kmem_cache_invalid_free(); | ||
508 | 613 | ||
509 | kasan_restore_multi_shot(multishot); | 614 | kasan_restore_multi_shot(multishot); |
510 | 615 | ||