]> git.saurik.com Git - apple/xnu.git/blob - tests/voucher_entry_18826844.c
xnu-6153.81.5.tar.gz
[apple/xnu.git] / tests / voucher_entry_18826844.c
1 /*
2 * Test that sending a message to a voucher with the same voucher as the voucher port
3 * with only one send right count with move send before the copy send doesn't panic.
4 *
5 * clang -o voucherentry voucherentry.c -ldarwintest -Weverything -Wno-gnu-flexible-array-initializer
6 *
7 * <rdar://problem/18826844>
8 */
9
10 #include <mach/mach.h>
11 #include <darwintest.h>
12
13 T_GLOBAL_META(T_META_RUN_CONCURRENTLY(true));
14
15 T_DECL(voucher_entry, "voucher_entry", T_META_CHECK_LEAKS(false), T_META_ALL_VALID_ARCHS(true))
16 {
17 kern_return_t kr = KERN_SUCCESS;
18 mach_voucher_t voucher = MACH_VOUCHER_NULL;
19
20 /*
21 * The bank voucher already exists in this process, so using it doesn't
22 * actually test the problem. Use an importance voucher instead.
23 */
24 mach_voucher_attr_recipe_data_t recipe = {
25 .key = MACH_VOUCHER_ATTR_KEY_IMPORTANCE,
26 .command = MACH_VOUCHER_ATTR_IMPORTANCE_SELF,
27 .previous_voucher = MACH_VOUCHER_NULL,
28 .content_size = 0,
29 };
30
31 kr = host_create_mach_voucher(mach_host_self(),
32 (mach_voucher_attr_raw_recipe_array_t)&recipe,
33 sizeof(recipe), &voucher);
34
35 T_ASSERT_MACH_SUCCESS(kr, "host_create_mach_voucher");
36
37 T_ASSERT_NOTNULL(voucher, "voucher must not be null");
38
39 mach_port_urefs_t refs = 0;
40
41 kr = mach_port_get_refs(mach_task_self(), voucher, MACH_PORT_RIGHT_SEND, &refs);
42
43 T_ASSERT_MACH_SUCCESS(kr, "mach_port_get_refs");
44
45 T_ASSERT_EQ(refs, (mach_port_urefs_t)1, "voucher must have only one ref");
46
47 /* First, try with two moves (must fail because there's only one ref) */
48 mach_msg_header_t request_msg_1 = {
49 .msgh_remote_port = voucher,
50 .msgh_local_port = MACH_PORT_NULL,
51 .msgh_voucher_port = voucher,
52 .msgh_bits = MACH_MSGH_BITS_SET(MACH_MSG_TYPE_MOVE_SEND, 0, MACH_MSG_TYPE_MOVE_SEND, 0),
53 .msgh_id = 0xDEAD,
54 .msgh_size = sizeof(request_msg_1),
55 };
56
57 kr = mach_msg_send(&request_msg_1);
58
59 T_ASSERT_MACH_ERROR(MACH_SEND_INVALID_DEST, kr, "send with two moves should fail with invalid dest");
60
61 /* Next, try with a move and a copy (will succeed and destroy the last ref) */
62 mach_msg_header_t request_msg_2 = {
63 .msgh_remote_port = voucher,
64 .msgh_local_port = MACH_PORT_NULL,
65 .msgh_voucher_port = voucher,
66 .msgh_bits = MACH_MSGH_BITS_SET(MACH_MSG_TYPE_MOVE_SEND, 0, MACH_MSG_TYPE_COPY_SEND, 0),
67 .msgh_id = 0xDEAD,
68 .msgh_size = sizeof(request_msg_2),
69 };
70
71 /* panic happens here */
72 kr = mach_msg_send(&request_msg_2);
73
74 T_ASSERT_MACH_SUCCESS(kr, "send with move and copy succeeds");
75
76 kr = mach_port_get_refs(mach_task_self(), voucher, MACH_PORT_RIGHT_SEND, &refs);
77
78 T_ASSERT_MACH_ERROR(KERN_INVALID_NAME, kr, "voucher should now be invalid name");
79 }