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.
8 * clang -o voucher_traps voucher_traps.c -ldarwintest -Weverything -Wno-gnu-flexible-array-initializer
10 * <rdar://problem/29379175>
15 #include <mach/mach.h>
16 #include <mach/mach_vm.h>
17 #include <mach/mach_traps.h>
19 #include <atm/atm_types.h>
21 #include <darwintest.h>
23 T_GLOBAL_META(T_META_RUN_CONCURRENTLY(true));
28 mach_voucher_attr_recipe_data_t r
= {
29 .key
= MACH_VOUCHER_ATTR_KEY_ATM
,
30 .command
= MACH_VOUCHER_ATTR_ATM_CREATE
32 mach_port_t port
= MACH_PORT_NULL
;
33 kern_return_t kr
= host_create_mach_voucher(mach_host_self(),
34 (mach_voucher_attr_raw_recipe_array_t
)&r
,
36 T_ASSERT_MACH_SUCCESS(kr
, "Create ATM voucher: 0x%x", (unsigned int)port
);
42 T_DECL(voucher_extract_attr_recipe
, "voucher_extract_attr_recipe")
45 mach_vm_size_t alloc_sz
;
47 mach_vm_address_t alloc_addr
;
49 /* map at least a page of memory at some arbitrary location */
50 alloc_sz
= (mach_vm_size_t
)round_page(MACH_VOUCHER_TRAP_STACK_LIMIT
+ 1);
53 * We could theoretically ask for a fixed location, but this is more
54 * reliable, and we're not actually trying to exploit anything - a
55 * kernel panic on failure should suffice :-)
57 alloc_addr
= (mach_vm_address_t
)round_page(MACH_VOUCHER_ATTR_MAX_RAW_RECIPE_ARRAY_SIZE
+ 1);
58 kr
= mach_vm_allocate(mach_task_self(), &alloc_addr
,
59 alloc_sz
, VM_FLAGS_ANYWHERE
);
62 * Make sure that the address of the allocation is larger than the
63 * maximum recipe size: this will test for the bug that was fixed in
64 * <rdar://problem/29379175>.
66 T_ASSERT_GT_ULLONG((uint64_t)alloc_addr
,
67 (uint64_t)MACH_VOUCHER_ATTR_MAX_RAW_RECIPE_ARRAY_SIZE
,
68 "Recipe addr (%llu bytes): 0x%llx > max recipe sz: %llu",
69 (uint64_t)alloc_sz
, (uint64_t)alloc_addr
,
70 (uint64_t)MACH_VOUCHER_ATTR_MAX_RAW_RECIPE_ARRAY_SIZE
);
72 /* make the allocation look like a pointer to an int */
73 mach_msg_type_number_t
*recipe_size
;
74 recipe_size
= (mach_msg_type_number_t
*)((uintptr_t)alloc_addr
);
75 bzero(recipe_size
, (unsigned long)alloc_sz
);
76 if (alloc_sz
> MACH_VOUCHER_ATTR_MAX_RAW_RECIPE_ARRAY_SIZE
) {
77 *recipe_size
= MACH_VOUCHER_ATTR_MAX_RAW_RECIPE_ARRAY_SIZE
;
79 *recipe_size
= (mach_msg_type_number_t
)alloc_sz
;
82 /* recipe buffer on the heap: memset it so panics show up loudly */
83 size_t size
= (size_t)(10 * 1024 * 1024);
84 void *recipe
= malloc(size
);
85 memset(recipe
, 0x41, size
);
87 port
= get_atm_voucher();
90 * This should try to extract the ATM attribute using a buffer on the
91 * kernel heap (probably zone memory).
93 kr
= mach_voucher_extract_attr_recipe_trap(port
, MACH_VOUCHER_ATTR_KEY_ATM
,
95 T_ASSERT_MACH_SUCCESS(kr
, "Extract attribute data with recipe: heap");
97 /* reset the recipe memory */
98 memset(recipe
, 0x41, size
);
99 /* reduce the size to get an allocation on the kernel stack */
100 *recipe_size
= MACH_VOUCHER_TRAP_STACK_LIMIT
- 1;
103 * This should try to extract the ATM attribute using a buffer on the
106 kr
= mach_voucher_extract_attr_recipe_trap(port
, MACH_VOUCHER_ATTR_KEY_ATM
,
107 recipe
, recipe_size
);
108 T_ASSERT_MACH_SUCCESS(kr
, "Extract attribute data with recipe: stack");
113 kr
= mach_vm_deallocate(mach_task_self(), alloc_addr
, alloc_sz
);
114 T_ASSERT_MACH_SUCCESS(kr
, "Deallocate recipe buffers");