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