]> git.saurik.com Git - apple/xnu.git/blob - tests/voucher_traps.c
0b4967720d972d05cd776524bcd3645087136d3c
[apple/xnu.git] / tests / voucher_traps.c
1 /*
2 * Test voucher trap APIs.
3 * There was an unfortunate bug in the trap interface that used the user space
4 * _address_ of a trap parameter as a copyin size. This test validates there
5 * are no other kernel panics in the voucher create and voucher attribute
6 * extraction mach traps.
7 *
8 * clang -o voucher_traps voucher_traps.c -ldarwintest -Weverything -Wno-gnu-flexible-array-initializer
9 *
10 * <rdar://problem/29379175>
11 */
12
13 #include <stdint.h>
14 #include <stdlib.h>
15 #include <mach/mach.h>
16 #include <mach/mach_vm.h>
17 #include <mach/mach_traps.h>
18
19 #include <atm/atm_types.h>
20
21 #include <darwintest.h>
22
23
24 static mach_port_t
25 get_atm_voucher(void)
26 {
27 mach_voucher_attr_recipe_data_t r = {
28 .key = MACH_VOUCHER_ATTR_KEY_ATM,
29 .command = MACH_VOUCHER_ATTR_ATM_CREATE
30 };
31 mach_port_t port = MACH_PORT_NULL;
32 kern_return_t kr = host_create_mach_voucher(mach_host_self(),
33 (mach_voucher_attr_raw_recipe_array_t)&r,
34 sizeof(r), &port);
35 T_ASSERT_MACH_SUCCESS(kr, "Create ATM voucher: 0x%x", (unsigned int)port);
36
37 return port;
38 }
39
40
41 T_DECL(voucher_extract_attr_recipe, "voucher_extract_attr_recipe")
42 {
43 kern_return_t kr;
44 mach_vm_size_t alloc_sz;
45 mach_port_t port;
46 mach_vm_address_t alloc_addr;
47
48 /* map at least a page of memory at some arbitrary location */
49 alloc_sz = (mach_vm_size_t)round_page(MACH_VOUCHER_TRAP_STACK_LIMIT + 1);
50
51 /*
52 * We could theoretically ask for a fixed location, but this is more
53 * reliable, and we're not actually trying to exploit anything - a
54 * kernel panic on failure should suffice :-)
55 */
56 alloc_addr = (mach_vm_address_t)round_page(MACH_VOUCHER_ATTR_MAX_RAW_RECIPE_ARRAY_SIZE + 1);
57 kr = mach_vm_allocate(mach_task_self(), &alloc_addr,
58 alloc_sz, VM_FLAGS_ANYWHERE);
59
60 /*
61 * Make sure that the address of the allocation is larger than the
62 * maximum recipe size: this will test for the bug that was fixed in
63 * <rdar://problem/29379175>.
64 */
65 T_ASSERT_GT_ULLONG((uint64_t)alloc_addr,
66 (uint64_t)MACH_VOUCHER_ATTR_MAX_RAW_RECIPE_ARRAY_SIZE,
67 "Recipe addr (%llu bytes): 0x%llx > max recipe sz: %llu",
68 (uint64_t)alloc_sz, (uint64_t)alloc_addr,
69 (uint64_t)MACH_VOUCHER_ATTR_MAX_RAW_RECIPE_ARRAY_SIZE);
70
71 /* make the allocation look like a pointer to an int */
72 mach_msg_type_number_t *recipe_size;
73 recipe_size = (mach_msg_type_number_t *)((uintptr_t)alloc_addr);
74 bzero(recipe_size, (unsigned long)alloc_sz);
75 if (alloc_sz > MACH_VOUCHER_ATTR_MAX_RAW_RECIPE_ARRAY_SIZE) {
76 *recipe_size = MACH_VOUCHER_ATTR_MAX_RAW_RECIPE_ARRAY_SIZE;
77 } else {
78 *recipe_size = (mach_msg_type_number_t)alloc_sz;
79 }
80
81 /* recipe buffer on the heap: memset it so panics show up loudly */
82 size_t size = (size_t)(10 * 1024 * 1024);
83 void *recipe = malloc(size);
84 memset(recipe, 0x41, size);
85
86 port = get_atm_voucher();
87
88 /*
89 * This should try to extract the ATM attribute using a buffer on the
90 * kernel heap (probably zone memory).
91 */
92 kr = mach_voucher_extract_attr_recipe_trap(port, MACH_VOUCHER_ATTR_KEY_ATM,
93 recipe, recipe_size);
94 T_ASSERT_MACH_SUCCESS(kr, "Extract attribute data with recipe: heap");
95
96 /* reset the recipe memory */
97 memset(recipe, 0x41, size);
98 /* reduce the size to get an allocation on the kernel stack */
99 *recipe_size = MACH_VOUCHER_TRAP_STACK_LIMIT - 1;
100
101 /*
102 * This should try to extract the ATM attribute using a buffer on the
103 * kernel stack.
104 */
105 kr = mach_voucher_extract_attr_recipe_trap(port, MACH_VOUCHER_ATTR_KEY_ATM,
106 recipe, recipe_size);
107 T_ASSERT_MACH_SUCCESS(kr, "Extract attribute data with recipe: stack");
108
109 /* cleanup */
110
111 free(recipe);
112 kr = mach_vm_deallocate(mach_task_self(), alloc_addr, alloc_sz);
113 T_ASSERT_MACH_SUCCESS(kr, "Deallocate recipe buffers");
114 }