]>
git.saurik.com Git - apple/xnu.git/blob - san/kasan-test.c
820af1b7f17441672d3ce20bb73ce106f6c844e4
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 <mach/mach_vm.h>
38 #include <mach/vm_param.h>
39 #include <libkern/libkern.h>
40 #include <libkern/kernel_mach_header.h>
41 #include <sys/queue.h>
43 #include <kasan_internal.h>
44 #include <memintrinsics.h>
46 #define STATIC_ARRAY_SZ 66
47 #define STACK_ARRAY_SZ 9
60 unsigned long static_array
[STATIC_ARRAY_SZ
];
63 static volatile int in_test
= 0;
66 int (* func
)(struct kasan_test
*);
67 void (* cleanup
)(struct kasan_test
*);
74 #define TEST_BARRIER() do { __asm__ __volatile__ ("" ::: "memory"); } while(0)
75 #define TEST_START(t) do { t->result = 1; TEST_BARRIER(); } while (0)
76 #define TEST_FAULT(t) do { TEST_BARRIER(); t->result = 0; TEST_BARRIER(); } while (0)
77 #define TEST_NOFAULT(t) do { TEST_BARRIER(); t->result = 1; TEST_BARRIER(); } while (0)
78 #define TEST_DONE(t,res) do { t->result = (res); kasan_handle_test(); } while (0)
79 #define DECLARE_TEST(f,s) { .func = f, .name = s }
80 #define DECLARE_TEST3(f,c,s) { .func = f, .cleanup = c, .name = s }
82 static void heap_cleanup(struct kasan_test
*t
)
85 kfree(t
->data
, t
->datasz
);
90 static int test_global_overflow(struct kasan_test __unused
*t
)
94 for (i
= 0; i
<= STATIC_ARRAY_SZ
; i
++) {
100 static int test_heap_underflow(struct kasan_test __unused
*t
)
102 uint8_t *x
= kalloc(BUFSZ
);
112 static int test_heap_overflow(struct kasan_test __unused
*t
)
114 uint8_t *x
= kalloc(BUFSZ
);
124 static int test_heap_uaf(struct kasan_test __unused
*t
)
126 uint8_t *x
= kalloc(LBUFSZ
);
135 static int test_heap_inval_free(struct kasan_test __unused
*t
)
142 static int test_heap_double_free(struct kasan_test
*t
)
146 uint8_t *x
= kalloc(BUFSZ
);
158 static int test_heap_small_free(struct kasan_test
*t
)
162 uint8_t *x
= kalloc(BUFSZ
);
177 static int test_stack_overflow(struct kasan_test
*t
)
182 volatile uint8_t a
[STACK_ARRAY_SZ
];
184 for (i
= 0; i
< STACK_ARRAY_SZ
; i
++) {
189 a
[i
] = i
; /* rookie error */
197 static int test_stack_underflow(struct kasan_test
*t
)
202 uint8_t a
[STACK_ARRAY_SZ
];
204 __nosan_memset(a
, 0, STACK_ARRAY_SZ
);
206 /* generate a negative index without the compiler noticing */
208 __asm__
__volatile__("movq $-1, %0" : "=r"(idx
) :: "memory");
210 __asm__
__volatile__("mov %0, #-1" : "=r"(idx
) :: "memory");
221 static int test_memcpy(struct kasan_test
*t
)
224 uint8_t a1
[STACK_ARRAY_SZ
];
225 uint8_t a2
[STACK_ARRAY_SZ
];
228 memcpy(a1
, a2
, STACK_ARRAY_SZ
);
234 memcpy(a2
, a1
, STACK_ARRAY_SZ
+1);
240 static int test_memmove(struct kasan_test
*t
)
243 uint8_t a1
[STACK_ARRAY_SZ
];
244 uint8_t a2
[STACK_ARRAY_SZ
];
247 memmove(a1
, a2
, STACK_ARRAY_SZ
);
253 memmove(a2
, a1
, STACK_ARRAY_SZ
+1);
259 static int test_bcopy(struct kasan_test
*t
)
262 uint8_t a1
[STACK_ARRAY_SZ
];
263 uint8_t a2
[STACK_ARRAY_SZ
];
266 bcopy(a1
, a2
, STACK_ARRAY_SZ
);
272 bcopy(a2
, a1
, STACK_ARRAY_SZ
+1);
278 static int test_memset(struct kasan_test
*t
)
281 uint8_t a1
[STACK_ARRAY_SZ
];
284 memset(a1
, 'e', STACK_ARRAY_SZ
);
290 memset(a1
, 'f', STACK_ARRAY_SZ
+1);
296 static int test_memcmp(struct kasan_test
*t
)
302 a1
= kalloc(STACK_ARRAY_SZ
);
305 a2
= kalloc(STACK_ARRAY_SZ
+1);
310 memcmp(a1
, a2
, STACK_ARRAY_SZ
);
311 memcmp(a1
, a2
+1, STACK_ARRAY_SZ
);
317 memcmp(a1
, a2
, STACK_ARRAY_SZ
+1);
323 static int test_bcmp(struct kasan_test
*t
)
329 a1
= kalloc(STACK_ARRAY_SZ
);
332 a2
= kalloc(STACK_ARRAY_SZ
+1);
337 bcmp(a1
, a2
, STACK_ARRAY_SZ
);
338 bcmp(a1
, a2
+1, STACK_ARRAY_SZ
);
344 bcmp(a1
, a2
, STACK_ARRAY_SZ
+1);
350 static int test_bzero(struct kasan_test
*t
)
353 uint8_t a1
[STACK_ARRAY_SZ
];
356 bzero(a1
, STACK_ARRAY_SZ
);
362 bzero(a1
, STACK_ARRAY_SZ
+1);
368 static int test_strlcpy(struct kasan_test
*t
)
373 /* should not fault */
374 strlcpy(a1
, "small", 8);
375 strlcpy(a1
, "looooonnnnggg", 8);
378 strlcpy(a1
, "looooooooonnnnggg", 9);
384 static int test_strncpy(struct kasan_test
*t
)
389 /* should not fault */
390 strncpy(a1
, "small", 9);
391 strncpy(a1
, "looooonnnnggg", 9);
394 strncpy(a1
, "looooonnnnggg", 10);
400 static int test_strlcat(struct kasan_test
*t
)
405 /* should not fault */
406 strlcat(a1
, "abcd", 9);
407 strlcat(a1
, "efgh", 9);
408 strlcat(a1
, "ijkl", 9);
410 strlcat(a1
, "looooonnnnggg", 9);
414 strlcat(a1
, "looooonnnnggg", 10);
420 static int test_strncat(struct kasan_test
*t
)
425 /* should not fault */
426 strncat(a1
, "abcd", 4);
427 strncat(a1
, "efgh", 4);
436 /* we ignore the top *two* frames in backtrace - so add an extra one */
437 static int NOINLINE
test_blacklist_helper(void)
439 return kasan_is_blacklisted(TYPE_TEST
);
442 static int NOINLINE
test_blacklist(struct kasan_test
*t
)
445 int res
= (int)!test_blacklist_helper();
450 static int NOINLINE
test_blacklist_str(struct kasan_test
*t
)
455 strlcpy(a1
, "looooooooonnnnggg", 9);
457 TEST_DONE(t
, 0); /* success */
462 static int test_strnlen(struct kasan_test
*t
)
465 const char *a1
= "abcdef";
467 /* should not fault */
468 if (strnlen(a1
, 6) != 6)
470 if (strnlen(a1
, 7) != 6)
474 if (strnlen(a1
, 8) != 6)
483 static int * NOINLINE
484 stack_uaf_helper(void)
491 static int test_stack_uaf(struct kasan_test __unused
*t
)
493 int *x
= stack_uaf_helper();
496 return !(*x
== 0xb4d);
499 static struct kasan_test xnu_tests
[] = {
500 DECLARE_TEST(NULL
, NULL
),
501 DECLARE_TEST(test_global_overflow
, "Global overflow"),
502 DECLARE_TEST3(test_heap_underflow
, heap_cleanup
, "Heap underflow"),
503 DECLARE_TEST3(test_heap_overflow
, heap_cleanup
, "Heap overflow"),
504 DECLARE_TEST(test_heap_uaf
, "Heap use-after-free"),
505 DECLARE_TEST(test_heap_inval_free
, "Heap invalid free"),
506 DECLARE_TEST(test_heap_double_free
,"Heap double free"),
507 DECLARE_TEST3(test_heap_small_free
, heap_cleanup
, "Heap small free"),
508 DECLARE_TEST(test_stack_overflow
, "Stack overflow"),
509 DECLARE_TEST(test_stack_underflow
, "Stack underflow"),
510 DECLARE_TEST(test_stack_uaf
, "Stack use-after-return"),
511 DECLARE_TEST(test_memcpy
, "memcpy"),
512 DECLARE_TEST(test_memmove
, "memmmove"),
513 DECLARE_TEST(test_bcopy
, "bcopy"),
514 DECLARE_TEST(test_memset
, "memset"),
515 DECLARE_TEST(test_memcmp
, "memcmp"),
516 DECLARE_TEST(test_bcmp
, "bcmp"),
517 DECLARE_TEST(test_bzero
, "bzero"),
518 DECLARE_TEST(test_strlcpy
, "strlcpy"),
519 DECLARE_TEST(test_strlcat
, "strlcat"),
520 DECLARE_TEST(test_strncpy
, "strncpy"),
521 DECLARE_TEST(test_strncat
, "strncat"),
522 DECLARE_TEST(test_blacklist
, "blacklist"),
523 DECLARE_TEST(test_blacklist_str
, "blacklist_str"),
524 // DECLARE_TEST(test_strnlen, "strnlen"),
526 static int num_xnutests
= sizeof(xnu_tests
)/sizeof(xnu_tests
[0]);
529 kasan_run_test(struct kasan_test
*test_list
, int testno
, int fail
)
531 int status
= TEST_UNKNOWN
;
532 struct kasan_test
*t
= &test_list
[testno
];
534 if (testno
< 0 || testno
>= num_xnutests
|| !t
->func
) {
535 printf("KASan: test.%02d INVALID\n", testno
);
539 // printf("KASan: test.%02d RUNNING (%s)\n", testno, t->name);
545 if (_setjmp(jbuf
) == 0) {
547 int ret
= t
->func(t
);
549 printf("KASan: test.%02d SETUP FAIL (%s)\n", testno
, t
->name
);
552 /* did not fault when it should have */
553 printf("KASan: test.%02d FAIL (%s)\n", testno
, t
->name
);
554 status
= TEST_FAIL_NOFAULT
;
557 /* Triggering a KASan violation will return here by longjmp, bypassing
558 * stack unpoisoning, so do it here explicitly. We just hope that
559 * fakestack free will happen later... */
560 kasan_unpoison_curstack();
563 /* faulted, but at the wrong place */
564 printf("KASan: test.%02d FAIL %d (%s)\n", testno
, t
->result
, t
->name
);
565 status
= TEST_FAIL_BADFAULT
;
567 printf("KASan: test.%02d PASS (%s)\n", testno
, t
->name
);
580 kasan_test(int testno
, int fail
)
583 int pass
= 0, total
= 0;
587 /* shorthand for all tests */
588 testno
= (1U << (num_xnutests
-1)) - 1;
593 ret
= kasan_run_test(xnu_tests
, i
, fail
);
594 if (ret
== TEST_PASS
) {
597 if (ret
!= TEST_INVALID
) {
605 printf("KASan: TEST SUMMARY %d/%d passed\n", pass
, total
);
609 kasan_handle_test(void)
618 __kasan_runtests(struct kasan_test
*kext_tests
, int numtests
)
621 for (i
= 0; i
< numtests
; i
++) {
622 kasan_run_test(kext_tests
, i
, 0);