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