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.
5 * clang -o voucherentry voucherentry.c -ldarwintest -Weverything -Wno-gnu-flexible-array-initializer
7 * <rdar://problem/18826844>
10 #include <mach/mach.h>
11 #include <darwintest.h>
13 T_DECL(voucher_entry
, "voucher_entry", T_META_CHECK_LEAKS(false), T_META_ALL_VALID_ARCHS(true))
15 kern_return_t kr
= KERN_SUCCESS
;
16 mach_voucher_t voucher
= MACH_VOUCHER_NULL
;
19 * The bank voucher already exists in this process, so using it doesn't
20 * actually test the problem. Use an importance voucher instead.
22 mach_voucher_attr_recipe_data_t recipe
= {
23 .key
= MACH_VOUCHER_ATTR_KEY_IMPORTANCE
,
24 .command
= MACH_VOUCHER_ATTR_IMPORTANCE_SELF
,
25 .previous_voucher
= MACH_VOUCHER_NULL
,
29 kr
= host_create_mach_voucher(mach_host_self(),
30 (mach_voucher_attr_raw_recipe_array_t
)&recipe
,
31 sizeof(recipe
), &voucher
);
33 T_ASSERT_MACH_SUCCESS(kr
, "host_create_mach_voucher");
35 T_ASSERT_NOTNULL(voucher
, "voucher must not be null");
37 mach_port_urefs_t refs
= 0;
39 kr
= mach_port_get_refs(mach_task_self(), voucher
, MACH_PORT_RIGHT_SEND
, &refs
);
41 T_ASSERT_MACH_SUCCESS(kr
, "mach_port_get_refs");
43 T_ASSERT_EQ(refs
, (mach_port_urefs_t
)1, "voucher must have only one ref");
45 /* First, try with two moves (must fail because there's only one ref) */
46 mach_msg_header_t request_msg_1
= {
47 .msgh_remote_port
= voucher
,
48 .msgh_local_port
= MACH_PORT_NULL
,
49 .msgh_voucher_port
= voucher
,
50 .msgh_bits
= MACH_MSGH_BITS_SET(MACH_MSG_TYPE_MOVE_SEND
, 0, MACH_MSG_TYPE_MOVE_SEND
, 0),
52 .msgh_size
= sizeof(request_msg_1
),
55 kr
= mach_msg_send(&request_msg_1
);
57 T_ASSERT_MACH_ERROR(MACH_SEND_INVALID_DEST
, kr
, "send with two moves should fail with invalid dest");
59 /* Next, try with a move and a copy (will succeed and destroy the last ref) */
60 mach_msg_header_t request_msg_2
= {
61 .msgh_remote_port
= voucher
,
62 .msgh_local_port
= MACH_PORT_NULL
,
63 .msgh_voucher_port
= voucher
,
64 .msgh_bits
= MACH_MSGH_BITS_SET(MACH_MSG_TYPE_MOVE_SEND
, 0, MACH_MSG_TYPE_COPY_SEND
, 0),
66 .msgh_size
= sizeof(request_msg_2
),
69 /* panic happens here */
70 kr
= mach_msg_send(&request_msg_2
);
72 T_ASSERT_MACH_SUCCESS(kr
, "send with move and copy succeeds");
74 kr
= mach_port_get_refs(mach_task_self(), voucher
, MACH_PORT_RIGHT_SEND
, &refs
);
76 T_ASSERT_MACH_ERROR(KERN_INVALID_NAME
, kr
, "voucher should now be invalid name");