]> git.saurik.com Git - apple/xnu.git/blame - tests/voucher_traps.c
xnu-7195.101.1.tar.gz
[apple/xnu.git] / tests / voucher_traps.c
CommitLineData
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
cb323159 23T_GLOBAL_META(T_META_RUN_CONCURRENTLY(true));
eee35659 24
0a7de745 25static mach_port_t
f427ee49 26get_user_data_port(mach_msg_type_number_t *size)
eee35659 27{
f427ee49
A
28#define DATA "Hello World!"
29 struct {
30 mach_voucher_attr_recipe_data_t recipe;
31 char data[sizeof(DATA)];
32 } buf = {
33 .recipe = {
34 .key = MACH_VOUCHER_ATTR_KEY_USER_DATA,
35 .command = MACH_VOUCHER_ATTR_USER_DATA_STORE,
36 .content_size = sizeof(DATA),
37 },
38 .data = DATA,
eee35659 39 };
f427ee49 40
eee35659
A
41 mach_port_t port = MACH_PORT_NULL;
42 kern_return_t kr = host_create_mach_voucher(mach_host_self(),
f427ee49
A
43 (mach_voucher_attr_raw_recipe_array_t)&buf,
44 sizeof(buf), &port);
45 T_ASSERT_MACH_SUCCESS(kr, "Create USER_DATA voucher: 0x%x",
46 (unsigned int)port);
eee35659 47
f427ee49
A
48 if (size) {
49 *size = sizeof(buf);
50 }
eee35659
A
51 return port;
52}
53
54
55T_DECL(voucher_extract_attr_recipe, "voucher_extract_attr_recipe")
56{
57 kern_return_t kr;
58 mach_vm_size_t alloc_sz;
59 mach_port_t port;
60 mach_vm_address_t alloc_addr;
f427ee49 61 mach_msg_type_number_t expected_size;
eee35659
A
62
63 /* map at least a page of memory at some arbitrary location */
64 alloc_sz = (mach_vm_size_t)round_page(MACH_VOUCHER_TRAP_STACK_LIMIT + 1);
65
66 /*
67 * We could theoretically ask for a fixed location, but this is more
68 * reliable, and we're not actually trying to exploit anything - a
69 * kernel panic on failure should suffice :-)
70 */
71 alloc_addr = (mach_vm_address_t)round_page(MACH_VOUCHER_ATTR_MAX_RAW_RECIPE_ARRAY_SIZE + 1);
72 kr = mach_vm_allocate(mach_task_self(), &alloc_addr,
0a7de745 73 alloc_sz, VM_FLAGS_ANYWHERE);
eee35659
A
74
75 /*
76 * Make sure that the address of the allocation is larger than the
77 * maximum recipe size: this will test for the bug that was fixed in
78 * <rdar://problem/29379175>.
79 */
80 T_ASSERT_GT_ULLONG((uint64_t)alloc_addr,
0a7de745
A
81 (uint64_t)MACH_VOUCHER_ATTR_MAX_RAW_RECIPE_ARRAY_SIZE,
82 "Recipe addr (%llu bytes): 0x%llx > max recipe sz: %llu",
83 (uint64_t)alloc_sz, (uint64_t)alloc_addr,
84 (uint64_t)MACH_VOUCHER_ATTR_MAX_RAW_RECIPE_ARRAY_SIZE);
eee35659
A
85
86 /* make the allocation look like a pointer to an int */
87 mach_msg_type_number_t *recipe_size;
88 recipe_size = (mach_msg_type_number_t *)((uintptr_t)alloc_addr);
89 bzero(recipe_size, (unsigned long)alloc_sz);
0a7de745 90 if (alloc_sz > MACH_VOUCHER_ATTR_MAX_RAW_RECIPE_ARRAY_SIZE) {
eee35659 91 *recipe_size = MACH_VOUCHER_ATTR_MAX_RAW_RECIPE_ARRAY_SIZE;
0a7de745 92 } else {
eee35659 93 *recipe_size = (mach_msg_type_number_t)alloc_sz;
0a7de745 94 }
eee35659
A
95
96 /* recipe buffer on the heap: memset it so panics show up loudly */
97 size_t size = (size_t)(10 * 1024 * 1024);
98 void *recipe = malloc(size);
99 memset(recipe, 0x41, size);
100
f427ee49 101 port = get_user_data_port(&expected_size);
eee35659
A
102
103 /*
f427ee49 104 * This should try to extract the USER_DATA attribute using a buffer on the
eee35659
A
105 * kernel heap (probably zone memory).
106 */
f427ee49
A
107 kr = mach_voucher_extract_attr_recipe_trap(port,
108 MACH_VOUCHER_ATTR_KEY_USER_DATA, recipe, recipe_size);
eee35659 109 T_ASSERT_MACH_SUCCESS(kr, "Extract attribute data with recipe: heap");
f427ee49 110 T_ASSERT_EQ(*recipe_size, expected_size, "size should match");
eee35659
A
111
112 /* reset the recipe memory */
113 memset(recipe, 0x41, size);
114 /* reduce the size to get an allocation on the kernel stack */
115 *recipe_size = MACH_VOUCHER_TRAP_STACK_LIMIT - 1;
116
117 /*
f427ee49 118 * This should try to extract the USER_DATA attribute using a buffer on the
eee35659
A
119 * kernel stack.
120 */
f427ee49
A
121 kr = mach_voucher_extract_attr_recipe_trap(port,
122 MACH_VOUCHER_ATTR_KEY_USER_DATA, recipe, recipe_size);
eee35659 123 T_ASSERT_MACH_SUCCESS(kr, "Extract attribute data with recipe: stack");
f427ee49 124 T_ASSERT_EQ(*recipe_size, expected_size, "size should match");
eee35659
A
125
126 /* cleanup */
127
128 free(recipe);
129 kr = mach_vm_deallocate(mach_task_self(), alloc_addr, alloc_sz);
130 T_ASSERT_MACH_SUCCESS(kr, "Deallocate recipe buffers");
131}