]>
git.saurik.com Git - apple/xnu.git/blob - san/kasan-test.c
2 * Copyright (c) 2016 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
31 #include <vm/vm_map.h>
32 #include <kern/assert.h>
33 #include <kern/locks.h>
34 #include <kern/kalloc.h>
35 #include <kern/simple_lock.h>
36 #include <kern/debug.h>
37 #include <kern/thread.h>
38 #include <mach/mach_vm.h>
39 #include <mach/vm_param.h>
40 #include <libkern/libkern.h>
41 #include <libkern/kernel_mach_header.h>
42 #include <sys/queue.h>
44 #include <kasan_internal.h>
45 #include <memintrinsics.h>
47 #define STATIC_ARRAY_SZ 66
48 #define STACK_ARRAY_SZ 9
61 unsigned long static_array
[STATIC_ARRAY_SZ
];
64 static volatile int in_test
= 0;
67 int (* func
)(struct kasan_test
*);
68 void (* cleanup
)(struct kasan_test
*);
75 #define TEST_BARRIER() do { __asm__ __volatile__ ("" ::: "memory"); } while(0)
76 #define TEST_START(t) do { t->result = 1; TEST_BARRIER(); } while (0)
77 #define TEST_FAULT(t) do { TEST_BARRIER(); t->result = 0; TEST_BARRIER(); } while (0)
78 #define TEST_NOFAULT(t) do { TEST_BARRIER(); t->result = 1; TEST_BARRIER(); } while (0)
79 #define TEST_DONE(t, res) do { t->result = (res); kasan_handle_test(); } while (0)
80 #define DECLARE_TEST(f, s) { .func = f, .name = s }
81 #define DECLARE_TEST3(f, c, s) { .func = f, .cleanup = c, .name = s }
84 heap_cleanup(struct kasan_test
*t
)
87 kfree(t
->data
, t
->datasz
);
93 test_global_overflow(struct kasan_test __unused
*t
)
97 for (i
= 0; i
<= STATIC_ARRAY_SZ
; i
++) {
104 test_heap_underflow(struct kasan_test __unused
*t
)
106 uint8_t *x
= kalloc(BUFSZ
);
117 test_heap_overflow(struct kasan_test __unused
*t
)
119 uint8_t *x
= kalloc(BUFSZ
);
130 test_heap_uaf(struct kasan_test __unused
*t
)
132 uint8_t *x
= kalloc(LBUFSZ
);
142 test_heap_inval_free(struct kasan_test __unused
*t
)
151 test_heap_double_free(struct kasan_test
*t
)
155 uint8_t *x
= kalloc(BUFSZ
);
168 test_heap_small_free(struct kasan_test
*t
)
172 uint8_t *x
= kalloc(BUFSZ
);
188 test_stack_overflow(struct kasan_test
*t
)
193 volatile uint8_t a
[STACK_ARRAY_SZ
];
195 for (i
= 0; i
< STACK_ARRAY_SZ
; i
++) {
200 a
[i
] = i
; /* rookie error */
209 test_stack_underflow(struct kasan_test
*t
)
214 uint8_t a
[STACK_ARRAY_SZ
];
216 __nosan_memset(a
, 0, STACK_ARRAY_SZ
);
218 /* generate a negative index without the compiler noticing */
220 __asm__
__volatile__ ("movq $-1, %0" : "=r"(idx
) :: "memory");
222 __asm__
__volatile__ ("mov %0, #-1" : "=r"(idx
) :: "memory");
234 test_memcpy(struct kasan_test
*t
)
237 uint8_t a1
[STACK_ARRAY_SZ
];
238 uint8_t a2
[STACK_ARRAY_SZ
];
241 memcpy(a1
, a2
, STACK_ARRAY_SZ
);
247 memcpy(a2
, a1
, STACK_ARRAY_SZ
+ 1);
254 test_memmove(struct kasan_test
*t
)
257 uint8_t a1
[STACK_ARRAY_SZ
];
258 uint8_t a2
[STACK_ARRAY_SZ
];
261 memmove(a1
, a2
, STACK_ARRAY_SZ
);
267 memmove(a2
, a1
, STACK_ARRAY_SZ
+ 1);
274 test_bcopy(struct kasan_test
*t
)
277 uint8_t a1
[STACK_ARRAY_SZ
];
278 uint8_t a2
[STACK_ARRAY_SZ
];
281 bcopy(a1
, a2
, STACK_ARRAY_SZ
);
287 bcopy(a2
, a1
, STACK_ARRAY_SZ
+ 1);
294 test_memset(struct kasan_test
*t
)
297 uint8_t a1
[STACK_ARRAY_SZ
];
300 memset(a1
, 'e', STACK_ARRAY_SZ
);
306 memset(a1
, 'f', STACK_ARRAY_SZ
+ 1);
313 test_memcmp(struct kasan_test
*t
)
319 a1
= kalloc(STACK_ARRAY_SZ
);
323 a2
= kalloc(STACK_ARRAY_SZ
+ 1);
329 memcmp(a1
, a2
, STACK_ARRAY_SZ
);
330 memcmp(a1
, a2
+ 1, STACK_ARRAY_SZ
);
336 memcmp(a1
, a2
, STACK_ARRAY_SZ
+ 1);
343 test_bcmp(struct kasan_test
*t
)
349 a1
= kalloc(STACK_ARRAY_SZ
);
353 a2
= kalloc(STACK_ARRAY_SZ
+ 1);
359 bcmp(a1
, a2
, STACK_ARRAY_SZ
);
360 bcmp(a1
, a2
+ 1, STACK_ARRAY_SZ
);
366 bcmp(a1
, a2
, STACK_ARRAY_SZ
+ 1);
373 test_bzero(struct kasan_test
*t
)
376 uint8_t a1
[STACK_ARRAY_SZ
];
379 bzero(a1
, STACK_ARRAY_SZ
);
385 bzero(a1
, STACK_ARRAY_SZ
+ 1);
392 test_strlcpy(struct kasan_test
*t
)
397 /* should not fault */
398 strlcpy(a1
, "small", 8);
399 strlcpy(a1
, "looooonnnnggg", 8);
402 strlcpy(a1
, "looooooooonnnnggg", 9);
409 test_strncpy(struct kasan_test
*t
)
414 /* should not fault */
415 strncpy(a1
, "small", 9);
416 strncpy(a1
, "looooonnnnggg", 9);
419 strncpy(a1
, "looooonnnnggg", 10);
426 test_strlcat(struct kasan_test
*t
)
431 /* should not fault */
432 strlcat(a1
, "abcd", 9);
433 strlcat(a1
, "efgh", 9);
434 strlcat(a1
, "ijkl", 9);
436 strlcat(a1
, "looooonnnnggg", 9);
440 strlcat(a1
, "looooonnnnggg", 10);
447 test_strncat(struct kasan_test
*t
)
452 /* should not fault */
453 strncat(a1
, "abcd", 4);
454 strncat(a1
, "efgh", 4);
463 /* we ignore the top *two* frames in backtrace - so add an extra one */
464 static int OS_NOINLINE
465 test_blacklist_helper(void)
467 return kasan_is_blacklisted(TYPE_TEST
);
470 static int OS_NOINLINE
471 test_blacklist(struct kasan_test
*t
)
474 int res
= (int)!test_blacklist_helper();
479 static int OS_NOINLINE
480 test_blacklist_str(struct kasan_test
*t
)
485 bcopy("123456", a1
, 8);
487 TEST_DONE(t
, 0); /* success */
493 test_strnlen(struct kasan_test
*t
)
496 const char *a1
= "abcdef";
498 /* should not fault */
499 if (strnlen(a1
, 6) != 6) {
502 if (strnlen(a1
, 7) != 6) {
507 if (strnlen(a1
, 8) != 6) {
516 static void OS_NOINLINE
517 force_fakestack(char *x
)
519 __asm__
__volatile__ ("" :: "r" (x
) : "memory");
524 test_fakestack_helper(struct kasan_test
*t
, char *x
)
530 /* ensure that 'x' is on the fakestack */
531 uintptr_t base
= dtrace_get_kernel_stack(current_thread());
532 uintptr_t p
= (uintptr_t)x
;
533 if (p
>= base
&& p
< base
+ kernel_stack_size
) {
537 __asan_handle_no_return();
539 /* x better still be accessible */
550 test_fakestack(struct kasan_test
*t
)
553 if (!fakestack_enabled
) {
557 return test_fakestack_helper(t
, x
);
561 static int * NOINLINE
562 stack_uaf_helper(void)
570 test_stack_uaf(struct kasan_test __unused
*t
)
572 int *x
= stack_uaf_helper();
575 return !(*x
== 0xb4d);
578 static struct kasan_test xnu_tests
[] = {
579 DECLARE_TEST(NULL
, NULL
),
580 DECLARE_TEST(test_global_overflow
, "Global overflow"),
581 DECLARE_TEST3(test_heap_underflow
, heap_cleanup
, "Heap underflow"),
582 DECLARE_TEST3(test_heap_overflow
, heap_cleanup
, "Heap overflow"),
583 DECLARE_TEST(test_heap_uaf
, "Heap use-after-free"),
584 DECLARE_TEST(test_heap_inval_free
, "Heap invalid free"),
585 DECLARE_TEST(test_heap_double_free
, "Heap double free"),
586 DECLARE_TEST3(test_heap_small_free
, heap_cleanup
, "Heap small free"),
587 DECLARE_TEST(test_stack_overflow
, "Stack overflow"),
588 DECLARE_TEST(test_stack_underflow
, "Stack underflow"),
589 DECLARE_TEST(test_stack_uaf
, "Stack use-after-return"),
590 DECLARE_TEST(test_memcpy
, "memcpy"),
591 DECLARE_TEST(test_memmove
, "memmmove"),
592 DECLARE_TEST(test_bcopy
, "bcopy"),
593 DECLARE_TEST(test_memset
, "memset"),
594 DECLARE_TEST(test_memcmp
, "memcmp"),
595 DECLARE_TEST(test_bcmp
, "bcmp"),
596 DECLARE_TEST(test_bzero
, "bzero"),
597 DECLARE_TEST(test_strlcpy
, "strlcpy"),
598 DECLARE_TEST(test_strlcat
, "strlcat"),
599 DECLARE_TEST(test_strncpy
, "strncpy"),
600 DECLARE_TEST(test_strncat
, "strncat"),
601 DECLARE_TEST(test_blacklist
, "blacklist"),
602 DECLARE_TEST(test_blacklist_str
, "blacklist_str"),
603 DECLARE_TEST(test_fakestack
, "fakestack"),
604 // DECLARE_TEST(test_strnlen, "strnlen"),
606 static int num_xnutests
= sizeof(xnu_tests
) / sizeof(xnu_tests
[0]);
609 kasan_run_test(struct kasan_test
*test_list
, int testno
, int fail
)
611 int status
= TEST_UNKNOWN
;
612 struct kasan_test
*t
= &test_list
[testno
];
614 if (testno
< 0 || testno
>= num_xnutests
|| !t
->func
) {
615 printf("KASan: test.%02d INVALID\n", testno
);
619 // printf("KASan: test.%02d RUNNING (%s)\n", testno, t->name);
625 if (_setjmp(jbuf
) == 0) {
627 int ret
= t
->func(t
);
629 printf("KASan: test.%02d SETUP FAIL (%s)\n", testno
, t
->name
);
632 /* did not fault when it should have */
633 printf("KASan: test.%02d FAIL (%s)\n", testno
, t
->name
);
634 status
= TEST_FAIL_NOFAULT
;
638 /* faulted, but at the wrong place */
639 printf("KASan: test.%02d FAIL %d (%s)\n", testno
, t
->result
, t
->name
);
640 status
= TEST_FAIL_BADFAULT
;
642 printf("KASan: test.%02d PASS (%s)\n", testno
, t
->name
);
655 kasan_test(int testno
, int fail
)
658 int pass
= 0, total
= 0;
662 /* shorthand for all tests */
663 testno
= (1U << (num_xnutests
- 1)) - 1;
668 ret
= kasan_run_test(xnu_tests
, i
, fail
);
669 if (ret
== TEST_PASS
) {
672 if (ret
!= TEST_INVALID
) {
680 printf("KASan: TEST SUMMARY %d/%d passed\n", pass
, total
);
684 kasan_handle_test(void)
693 __kasan_runtests(struct kasan_test
*kext_tests
, int numtests
)
696 for (i
= 0; i
< numtests
; i
++) {
697 kasan_run_test(kext_tests
, i
, 0);