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