]>
Commit | Line | Data |
---|---|---|
eee35659 A |
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 get_atm_voucher(void) | |
25 | { | |
26 | mach_voucher_attr_recipe_data_t r = { | |
27 | .key = MACH_VOUCHER_ATTR_KEY_ATM, | |
28 | .command = MACH_VOUCHER_ATTR_ATM_CREATE | |
29 | }; | |
30 | mach_port_t port = MACH_PORT_NULL; | |
31 | kern_return_t kr = host_create_mach_voucher(mach_host_self(), | |
32 | (mach_voucher_attr_raw_recipe_array_t)&r, | |
33 | sizeof(r), &port); | |
34 | T_ASSERT_MACH_SUCCESS(kr, "Create ATM voucher: 0x%x", (unsigned int)port); | |
35 | ||
36 | return port; | |
37 | } | |
38 | ||
39 | ||
40 | T_DECL(voucher_extract_attr_recipe, "voucher_extract_attr_recipe") | |
41 | { | |
42 | kern_return_t kr; | |
43 | mach_vm_size_t alloc_sz; | |
44 | mach_port_t port; | |
45 | mach_vm_address_t alloc_addr; | |
46 | ||
47 | /* map at least a page of memory at some arbitrary location */ | |
48 | alloc_sz = (mach_vm_size_t)round_page(MACH_VOUCHER_TRAP_STACK_LIMIT + 1); | |
49 | ||
50 | /* | |
51 | * We could theoretically ask for a fixed location, but this is more | |
52 | * reliable, and we're not actually trying to exploit anything - a | |
53 | * kernel panic on failure should suffice :-) | |
54 | */ | |
55 | alloc_addr = (mach_vm_address_t)round_page(MACH_VOUCHER_ATTR_MAX_RAW_RECIPE_ARRAY_SIZE + 1); | |
56 | kr = mach_vm_allocate(mach_task_self(), &alloc_addr, | |
57 | alloc_sz, VM_FLAGS_ANYWHERE); | |
58 | ||
59 | /* | |
60 | * Make sure that the address of the allocation is larger than the | |
61 | * maximum recipe size: this will test for the bug that was fixed in | |
62 | * <rdar://problem/29379175>. | |
63 | */ | |
64 | T_ASSERT_GT_ULLONG((uint64_t)alloc_addr, | |
65 | (uint64_t)MACH_VOUCHER_ATTR_MAX_RAW_RECIPE_ARRAY_SIZE, | |
66 | "Recipe addr (%llu bytes): 0x%llx > max recipe sz: %llu", | |
67 | (uint64_t)alloc_sz, (uint64_t)alloc_addr, | |
68 | (uint64_t)MACH_VOUCHER_ATTR_MAX_RAW_RECIPE_ARRAY_SIZE); | |
69 | ||
70 | /* make the allocation look like a pointer to an int */ | |
71 | mach_msg_type_number_t *recipe_size; | |
72 | recipe_size = (mach_msg_type_number_t *)((uintptr_t)alloc_addr); | |
73 | bzero(recipe_size, (unsigned long)alloc_sz); | |
74 | if (alloc_sz > MACH_VOUCHER_ATTR_MAX_RAW_RECIPE_ARRAY_SIZE) | |
75 | *recipe_size = MACH_VOUCHER_ATTR_MAX_RAW_RECIPE_ARRAY_SIZE; | |
76 | else | |
77 | *recipe_size = (mach_msg_type_number_t)alloc_sz; | |
78 | ||
79 | /* recipe buffer on the heap: memset it so panics show up loudly */ | |
80 | size_t size = (size_t)(10 * 1024 * 1024); | |
81 | void *recipe = malloc(size); | |
82 | memset(recipe, 0x41, size); | |
83 | ||
84 | port = get_atm_voucher(); | |
85 | ||
86 | /* | |
87 | * This should try to extract the ATM attribute using a buffer on the | |
88 | * kernel heap (probably zone memory). | |
89 | */ | |
90 | kr = mach_voucher_extract_attr_recipe_trap(port, MACH_VOUCHER_ATTR_KEY_ATM, | |
91 | recipe, recipe_size); | |
92 | T_ASSERT_MACH_SUCCESS(kr, "Extract attribute data with recipe: heap"); | |
93 | ||
94 | /* reset the recipe memory */ | |
95 | memset(recipe, 0x41, size); | |
96 | /* reduce the size to get an allocation on the kernel stack */ | |
97 | *recipe_size = MACH_VOUCHER_TRAP_STACK_LIMIT - 1; | |
98 | ||
99 | /* | |
100 | * This should try to extract the ATM attribute using a buffer on the | |
101 | * kernel stack. | |
102 | */ | |
103 | kr = mach_voucher_extract_attr_recipe_trap(port, MACH_VOUCHER_ATTR_KEY_ATM, | |
104 | recipe, recipe_size); | |
105 | T_ASSERT_MACH_SUCCESS(kr, "Extract attribute data with recipe: stack"); | |
106 | ||
107 | /* cleanup */ | |
108 | ||
109 | free(recipe); | |
110 | kr = mach_vm_deallocate(mach_task_self(), alloc_addr, alloc_sz); | |
111 | T_ASSERT_MACH_SUCCESS(kr, "Deallocate recipe buffers"); | |
112 | } |