1 /*
2 * Copyright (c) 2016 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
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.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
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.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
29 #include <stdint.h>
30 #include <string.h>
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>
43 #include "kasan.h"
44 #include "kasan_internal.h"
45 #include "memintrinsics.h"
46
47 /* move to kasan-test.h */
48 typedef int jmp_buf[_JBLEN];
49 void _longjmp(jmp_buf env, int val) OS_NORETURN;
50 int _setjmp(jmp_buf env) __attribute__((returns_twice));
51
52
53 #define STATIC_ARRAY_SZ 66
54 #define STACK_ARRAY_SZ 9
55 #define BUFSZ 34
56 #define LBUFSZ 255
57
58 enum {
59 TEST_PASS,
60 TEST_FAIL_NOFAULT,
61 TEST_FAIL_BADFAULT,
62 TEST_SETUP_FAIL = 1,
63 TEST_INVALID,
64 TEST_UNKNOWN
65 };
66
67 unsigned long static_array[STATIC_ARRAY_SZ];
68
69 static jmp_buf jbuf;
70 static volatile int in_test = 0;
71
72 #define TEST_BARRIER() do { __asm__ __volatile__ ("" ::: "memory"); } while(0)
73 #define TEST_START(t) do { t->result = 1; TEST_BARRIER(); } while (0)
74 #define TEST_FAULT(t) do { TEST_BARRIER(); t->result = 0; TEST_BARRIER(); } while (0)
75 #define TEST_NOFAULT(t) do { TEST_BARRIER(); t->result = 1; TEST_BARRIER(); } while (0)
76 #define TEST_DONE(t, res) do { t->result = (res); kasan_handle_test(); } while (0)
77 #define DECLARE_TEST(f, s) { .func = f, .name = s }
78 #define DECLARE_TEST3(f, c, s) { .func = f, .cleanup = c, .name = s }
79
80 static void
heap_cleanup(struct kasan_test * t)81 heap_cleanup(struct kasan_test *t)
82 {
83 if (t->data) {
84 kfree_data(t->data, t->datasz);
85 t->data = NULL;
86 }
87 }
88
89 static int
test_global_overflow(struct kasan_test __unused * t)90 test_global_overflow(struct kasan_test __unused *t)
91 {
92 int i;
93 /* rookie error */
94 for (i = 0; i <= STATIC_ARRAY_SZ; i++) {
95 static_array[i] = i;
96 }
97 return 0;
98 }
99
100 static int
test_heap_underflow(struct kasan_test __unused * t)101 test_heap_underflow(struct kasan_test __unused *t)
102 {
103 uint8_t *x = kalloc_data(BUFSZ, Z_WAITOK);
104 if (!x) {
105 return 1;
106 }
107 t->datasz = BUFSZ;
108 t->data = x;
109 x[-1] = 0x12;
110 return 0;
111 }
112
113 static int
test_heap_overflow(struct kasan_test __unused * t)114 test_heap_overflow(struct kasan_test __unused *t)
115 {
116 uint8_t *x = kalloc_data(BUFSZ, Z_WAITOK);
117 if (!x) {
118 return 1;
119 }
120 t->datasz = BUFSZ;
121 t->data = x;
122 x[BUFSZ] = 0x11;
123 return 0;
124 }
125
126 static int
test_heap_uaf(struct kasan_test __unused * t)127 test_heap_uaf(struct kasan_test __unused *t)
128 {
129 uint8_t *x = kalloc_data(LBUFSZ, Z_WAITOK);
130 if (!x) {
131 return 1;
132 }
133 kfree_data(x, LBUFSZ);
134 x[0] = 0x10;
135 return 0;
136 }
137
138 static int
test_heap_inval_free(struct kasan_test __unused * t)139 test_heap_inval_free(struct kasan_test __unused *t)
140 {
141 int x;
142 int *ptr = &x;
143 kfree_data(ptr, BUFSZ);
144 return 0;
145 }
146
147 static int
test_heap_double_free(struct kasan_test * t)148 test_heap_double_free(struct kasan_test *t)
149 {
150 TEST_START(t);
151
152 uint8_t *x = kalloc_data(BUFSZ, Z_WAITOK);
153 if (!x) {
154 return 1;
155 }
156 kfree_data(x, BUFSZ);
157
158 TEST_FAULT(t);
159 kfree_data(x, BUFSZ);
160
161 return 0;
162 }
163
164 static int
test_heap_small_free(struct kasan_test * t)165 test_heap_small_free(struct kasan_test *t)
166 {
167 TEST_START(t);
168
169 uint8_t *x = kalloc_data(BUFSZ, Z_WAITOK);
170 if (!x) {
171 return 1;
172 }
173 t->datasz = BUFSZ;
174 t->data = x;
175
176 TEST_FAULT(t);
177 kfree_data(x, BUFSZ - 2);
178 t->data = NULL;
179 t->datasz = 0;
180
181 return 0;
182 }
183
184 static int
test_stack_overflow(struct kasan_test * t)185 test_stack_overflow(struct kasan_test *t)
186 {
187 TEST_START(t);
188
189 uint8_t i;
190 volatile uint8_t a[STACK_ARRAY_SZ];
191
192 for (i = 0; i < STACK_ARRAY_SZ; i++) {
193 a[i] = i;
194 }
195
196 TEST_FAULT(t);
197 a[i] = i; /* rookie error */
198 TEST_NOFAULT(t);
199
200 TEST_BARRIER();
201
202 return !(a[0] == 0);
203 }
204
205 static int
test_stack_underflow(struct kasan_test * t)206 test_stack_underflow(struct kasan_test *t)
207 {
208 TEST_START(t);
209
210 long idx;
211 uint8_t a[STACK_ARRAY_SZ];
212
213 __nosan_memset(a, 0, STACK_ARRAY_SZ);
214
215 /* generate a negative index without the compiler noticing */
216 #if __x86_64__
217 __asm__ __volatile__ ("movq $-1, %0" : "=r"(idx) :: "memory");
218 #else
219 __asm__ __volatile__ ("mov %0, #-1" : "=r"(idx) :: "memory");
220 #endif
221
222 TEST_FAULT(t);
223 a[idx] = 0xbd;
224 TEST_NOFAULT(t);
225
226 TEST_BARRIER();
227 return a[0] == 0;
228 }
229
230 static int
test_memcpy(struct kasan_test * t)231 test_memcpy(struct kasan_test *t)
232 {
233 TEST_START(t);
234 uint8_t a1[STACK_ARRAY_SZ];
235 uint8_t a2[STACK_ARRAY_SZ];
236
237 /* should work */
238 memcpy(a1, a2, STACK_ARRAY_SZ);
239
240 TEST_BARRIER();
241
242 /* should fail */
243 TEST_FAULT(t);
244 memcpy(a2, a1, STACK_ARRAY_SZ + 1);
245 TEST_NOFAULT(t);
246
247 return 0;
248 }
249
250 static int
test_memmove(struct kasan_test * t)251 test_memmove(struct kasan_test *t)
252 {
253 TEST_START(t);
254 uint8_t a1[STACK_ARRAY_SZ];
255 uint8_t a2[STACK_ARRAY_SZ];
256
257 /* should work */
258 memmove(a1, a2, STACK_ARRAY_SZ);
259
260 TEST_BARRIER();
261
262 /* should fail */
263 TEST_FAULT(t);
264 memmove(a2, a1, STACK_ARRAY_SZ + 1);
265 TEST_NOFAULT(t);
266
267 return 0;
268 }
269
270 static int
test_bcopy(struct kasan_test * t)271 test_bcopy(struct kasan_test *t)
272 {
273 TEST_START(t);
274 uint8_t a1[STACK_ARRAY_SZ];
275 uint8_t a2[STACK_ARRAY_SZ];
276
277 /* should work */
278 bcopy(a1, a2, STACK_ARRAY_SZ);
279
280 TEST_BARRIER();
281
282 /* should fail */
283 TEST_FAULT(t);
284 bcopy(a2, a1, STACK_ARRAY_SZ + 1);
285 TEST_NOFAULT(t);
286
287 return 0;
288 }
289
290 static int
test_memset(struct kasan_test * t)291 test_memset(struct kasan_test *t)
292 {
293 TEST_START(t);
294 uint8_t a1[STACK_ARRAY_SZ];
295
296 /* should work */
297 memset(a1, 'e', STACK_ARRAY_SZ);
298
299 TEST_BARRIER();
300
301 /* should fail */
302 TEST_FAULT(t);
303 memset(a1, 'f', STACK_ARRAY_SZ + 1);
304 TEST_NOFAULT(t);
305
306 return 0;
307 }
308
309 static int
test_memcmp(struct kasan_test * t)310 test_memcmp(struct kasan_test *t)
311 {
312 TEST_START(t);
313 uint8_t *a1;
314 uint8_t *a2;
315
316 a1 = kalloc_data(STACK_ARRAY_SZ, Z_WAITOK);
317 if (!a1) {
318 return 1;
319 }
320 a2 = kalloc_data(STACK_ARRAY_SZ + 1, Z_WAITOK);
321 if (!a2) {
322 return 1;
323 }
324
325 /* should work */
326 memcmp(a1, a2, STACK_ARRAY_SZ);
327 memcmp(a1, a2 + 1, STACK_ARRAY_SZ);
328
329 TEST_BARRIER();
330
331 /* should fail */
332 TEST_FAULT(t);
333 memcmp(a1, a2, STACK_ARRAY_SZ + 1);
334 TEST_NOFAULT(t);
335
336 return 0;
337 }
338
339 static int
test_bcmp(struct kasan_test * t)340 test_bcmp(struct kasan_test *t)
341 {
342 TEST_START(t);
343 uint8_t *a1;
344 uint8_t *a2;
345
346 a1 = kalloc_data(STACK_ARRAY_SZ, Z_WAITOK);
347 if (!a1) {
348 return 1;
349 }
350 a2 = kalloc_data(STACK_ARRAY_SZ + 1, Z_WAITOK);
351 if (!a2) {
352 return 1;
353 }
354
355 /* should work */
356 bcmp(a1, a2, STACK_ARRAY_SZ);
357 bcmp(a1, a2 + 1, STACK_ARRAY_SZ);
358
359 TEST_BARRIER();
360
361 /* should fail */
362 TEST_FAULT(t);
363 bcmp(a1, a2, STACK_ARRAY_SZ + 1);
364 TEST_NOFAULT(t);
365
366 return 0;
367 }
368
369 static int
test_bzero(struct kasan_test * t)370 test_bzero(struct kasan_test *t)
371 {
372 TEST_START(t);
373 uint8_t a1[STACK_ARRAY_SZ];
374
375 /* should work */
376 bzero(a1, STACK_ARRAY_SZ);
377
378 TEST_BARRIER();
379
380 /* should fail */
381 TEST_FAULT(t);
382 bzero(a1, STACK_ARRAY_SZ + 1);
383 TEST_NOFAULT(t);
384
385 return 0;
386 }
387
388 static int
test_strlcpy(struct kasan_test * t)389 test_strlcpy(struct kasan_test *t)
390 {
391 TEST_START(t);
392 char a1[8];
393
394 /* should not fault */
395 strlcpy(a1, "small", 8);
396 strlcpy(a1, "looooonnnnggg", 8);
397
398 TEST_FAULT(t);
399 strlcpy(a1, "looooooooonnnnggg", 9);
400 TEST_NOFAULT(t);
401
402 return 0;
403 }
404
405 static int
test_strncpy(struct kasan_test * t)406 test_strncpy(struct kasan_test *t)
407 {
408 TEST_START(t);
409 char a1[9];
410
411 /* should not fault */
412 strncpy(a1, "small", 9);
413 strncpy(a1, "looooonnnnggg", 9);
414
415 TEST_FAULT(t);
416 strncpy(a1, "looooonnnnggg", 10);
417 TEST_NOFAULT(t);
418
419 return a1[0] != 'l';
420 }
421
422 static int
test_strlcat(struct kasan_test * t)423 test_strlcat(struct kasan_test *t)
424 {
425 TEST_START(t);
426 char a1[9] = {};
427
428 /* should not fault */
429 strlcat(a1, "abcd", 9);
430 strlcat(a1, "efgh", 9);
431 strlcat(a1, "ijkl", 9);
432 a1[0] = '\0';
433 strlcat(a1, "looooonnnnggg", 9);
434
435 a1[0] = '\0';
436 TEST_FAULT(t);
437 strlcat(a1, "looooonnnnggg", 10);
438 TEST_NOFAULT(t);
439
440 return a1[0] != 'l';
441 }
442
443 static int
test_strncat(struct kasan_test * t)444 test_strncat(struct kasan_test *t)
445 {
446 TEST_START(t);
447 char a1[9] = {};
448
449 /* should not fault */
450 strncat(a1, "abcd", 4);
451 strncat(a1, "efgh", 4);
452
453 TEST_FAULT(t);
454 strncat(a1, "i", 1);
455 TEST_NOFAULT(t);
456
457 return a1[0] != 'a';
458 }
459
460 /* we ignore the top *two* frames in backtrace - so add an extra one */
461 static int OS_NOINLINE
test_blacklist_helper(void)462 test_blacklist_helper(void)
463 {
464 return kasan_is_blacklisted(TYPE_TEST);
465 }
466
467 static int OS_NOINLINE
test_blacklist(struct kasan_test * t)468 test_blacklist(struct kasan_test *t)
469 {
470 TEST_START(t);
471 int res = (int)!test_blacklist_helper();
472 TEST_DONE(t, res);
473 return 0;
474 }
475
476 static int OS_NOINLINE
test_blacklist_str(struct kasan_test * t)477 test_blacklist_str(struct kasan_test *t)
478 {
479 TEST_START(t);
480 char a1[8];
481
482 bcopy("123456", a1, 8);
483
484 TEST_DONE(t, 0); /* success */
485 return 0;
486 }
487
488 static void OS_NOINLINE
force_fakestack(char * x)489 force_fakestack(char *x)
490 {
491 __asm__ __volatile__ ("" :: "r" (x) : "memory");
492 }
493
494 OS_NOINLINE
495 static int
test_fakestack_helper(struct kasan_test * t,char * x)496 test_fakestack_helper(struct kasan_test *t, char *x)
497 {
498 TEST_START(t);
499
500 x[0] = 0x55;
501
502 /* ensure that 'x' is on the fakestack */
503 uintptr_t base = dtrace_get_kernel_stack(current_thread());
504 uintptr_t p = (uintptr_t)x;
505 if (p >= base && p < base + kernel_stack_size) {
506 return 1;
507 }
508
509 __asan_handle_no_return();
510
511 /* x better still be accessible */
512 TEST_NOFAULT(t);
513 if (x[0] != 0x55) {
514 TEST_DONE(t, 1);
515 }
516
517 TEST_DONE(t, 0);
518 return 0;
519 }
520
521 static int
test_fakestack(struct kasan_test * t)522 test_fakestack(struct kasan_test *t)
523 {
524 char x[8];
525 if (!fakestack_enabled) {
526 return 1;
527 }
528 force_fakestack(x);
529 return test_fakestack_helper(t, x);
530 }
531
532 int *uaf_ptr;
533 static int * NOINLINE
stack_uaf_helper(void)534 stack_uaf_helper(void)
535 {
536 int x;
537 uaf_ptr = &x;
538 return uaf_ptr;
539 }
540
541 static int
test_stack_uaf(struct kasan_test __unused * t)542 test_stack_uaf(struct kasan_test __unused *t)
543 {
544 int *x = stack_uaf_helper();
545 *x = 0xb4d;
546 TEST_BARRIER();
547 return !(*x == 0xb4d);
548 }
549
550 static struct kasan_test xnu_tests[] = {
551 DECLARE_TEST(NULL, NULL),
552 DECLARE_TEST(test_global_overflow, "Global overflow"),
553 DECLARE_TEST3(test_heap_underflow, heap_cleanup, "Heap underflow"),
554 DECLARE_TEST3(test_heap_overflow, heap_cleanup, "Heap overflow"),
555 DECLARE_TEST(test_heap_uaf, "Heap use-after-free"),
556 DECLARE_TEST(test_heap_inval_free, "Heap invalid free"),
557 DECLARE_TEST(test_heap_double_free, "Heap double free"),
558 DECLARE_TEST3(test_heap_small_free, heap_cleanup, "Heap small free"),
559 DECLARE_TEST(test_stack_overflow, "Stack overflow"),
560 DECLARE_TEST(test_stack_underflow, "Stack underflow"),
561 DECLARE_TEST(test_stack_uaf, "Stack use-after-return"),
562 DECLARE_TEST(test_memcpy, "memcpy"),
563 DECLARE_TEST(test_memmove, "memmmove"),
564 DECLARE_TEST(test_bcopy, "bcopy"),
565 DECLARE_TEST(test_memset, "memset"),
566 DECLARE_TEST(test_memcmp, "memcmp"),
567 DECLARE_TEST(test_bcmp, "bcmp"),
568 DECLARE_TEST(test_bzero, "bzero"),
569 DECLARE_TEST(test_strlcpy, "strlcpy"),
570 DECLARE_TEST(test_strlcat, "strlcat"),
571 DECLARE_TEST(test_strncpy, "strncpy"),
572 DECLARE_TEST(test_strncat, "strncat"),
573 DECLARE_TEST(test_blacklist, "blacklist"),
574 DECLARE_TEST(test_blacklist_str, "blacklist_str"),
575 DECLARE_TEST(test_fakestack, "fakestack"),
576 };
577 static int num_xnutests = sizeof(xnu_tests) / sizeof(xnu_tests[0]);
578
579 static int
kasan_run_test(struct kasan_test * test_list,int testno,int fail)580 kasan_run_test(struct kasan_test *test_list, int testno, int fail)
581 {
582 int status = TEST_UNKNOWN;
583 struct kasan_test *t = &test_list[testno];
584
585 if (testno < 0 || testno >= num_xnutests || !t->func) {
586 printf("KASan: test.%02d INVALID\n", testno);
587 return TEST_INVALID;
588 }
589
590 if (!fail) {
591 in_test = 1;
592 }
593
594 if (_setjmp(jbuf) == 0) {
595 t->result = 0;
596 int ret = t->func(t);
597 if (ret) {
598 printf("KASan: test.%02d SETUP FAIL (%s)\n", testno, t->name);
599 status = ret;
600 } else {
601 /* did not fault when it should have */
602 printf("KASan: test.%02d FAIL (%s)\n", testno, t->name);
603 status = TEST_FAIL_NOFAULT;
604 }
605 } else {
606 if (t->result) {
607 /* faulted, but at the wrong place */
608 printf("KASan: test.%02d FAIL %d (%s)\n", testno, t->result, t->name);
609 status = TEST_FAIL_BADFAULT;
610 } else {
611 printf("KASan: test.%02d PASS (%s)\n", testno, t->name);
612 status = TEST_PASS;
613 }
614 }
615 in_test = 0;
616 if (t->cleanup) {
617 t->cleanup(t);
618 }
619
620 return status;
621 }
622
623 static void
kasan_test(int testno,int fail)624 kasan_test(int testno, int fail)
625 {
626 int i = 1;
627 int pass = 0, total = 0;
628 int ret;
629
630 if (testno == -1) {
631 /* shorthand for all tests */
632 testno = (1U << (num_xnutests - 1)) - 1;
633 }
634
635 while (testno) {
636 if (testno & 0x1) {
637 ret = kasan_run_test(xnu_tests, i, fail);
638 if (ret == TEST_PASS) {
639 pass++;
640 }
641 if (ret != TEST_INVALID) {
642 total++;
643 }
644 }
645
646 i++;
647 testno >>= 1;
648 }
649 printf("KASan: TEST SUMMARY %d/%d passed\n", pass, total);
650 }
651
652 void
kasan_handle_test(void)653 kasan_handle_test(void)
654 {
655 if (in_test) {
656 _longjmp(jbuf, 1);
657 /* NOTREACHED */
658 }
659 }
660
661 void
__kasan_runtests(struct kasan_test * kext_tests,int numtests)662 __kasan_runtests(struct kasan_test *kext_tests, int numtests)
663 {
664 int i;
665 for (i = 0; i < numtests; i++) {
666 kasan_run_test(kext_tests, i, 0);
667 }
668 }
669
670 static int
sysctl_kasan_test(__unused struct sysctl_oid * oidp,__unused void * arg1,int arg2,struct sysctl_req * req)671 sysctl_kasan_test(__unused struct sysctl_oid *oidp, __unused void *arg1, int arg2, struct sysctl_req *req)
672 {
673 int ch, err, mask = 0;
674 err = sysctl_io_number(req, 0, sizeof(int), &mask, &ch);
675
676 if (!err && mask) {
677 kasan_test(mask, arg2);
678 }
679
680 return err;
681 }
682
683 SYSCTL_PROC(_kern_kasan, OID_AUTO, test,
684 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_LOCKED,
685 0, 0, sysctl_kasan_test, "I", "");
686
687 SYSCTL_PROC(_kern_kasan, OID_AUTO, fail,
688 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_LOCKED,
689 0, 1, sysctl_kasan_test, "I", "");
690