xref: /xnu-12377.61.12/tests/reply_port_defense_client.c (revision 4d495c6e23c53686cf65f45067f79024cf5dcee8)
1*4d495c6eSApple OSS Distributions #include <stdlib.h>
2*4d495c6eSApple OSS Distributions #include <stdio.h>
3*4d495c6eSApple OSS Distributions #include <pthread.h>
4*4d495c6eSApple OSS Distributions #include <pthread/private.h>
5*4d495c6eSApple OSS Distributions #include <unistd.h>
6*4d495c6eSApple OSS Distributions #include <mach/kern_return.h>
7*4d495c6eSApple OSS Distributions #include <mach/mach.h>
8*4d495c6eSApple OSS Distributions #include <mach/task.h>
9*4d495c6eSApple OSS Distributions #include <mach/thread_status.h>
10*4d495c6eSApple OSS Distributions #include <os/tsd.h>
11*4d495c6eSApple OSS Distributions #include <assert.h>
12*4d495c6eSApple OSS Distributions #include <sys/codesign.h>
13*4d495c6eSApple OSS Distributions #include <stdbool.h>
14*4d495c6eSApple OSS Distributions #include <darwintest.h>
15*4d495c6eSApple OSS Distributions #include <mach/mk_timer.h>
16*4d495c6eSApple OSS Distributions #include "cs_helpers.h"
17*4d495c6eSApple OSS Distributions 
18*4d495c6eSApple OSS Distributions #define MAX_TEST_NUM 22
19*4d495c6eSApple OSS Distributions 
20*4d495c6eSApple OSS Distributions #if __arm64__
21*4d495c6eSApple OSS Distributions #define machine_thread_state_t          arm_thread_state64_t
22*4d495c6eSApple OSS Distributions #define EXCEPTION_THREAD_STATE          ARM_THREAD_STATE64
23*4d495c6eSApple OSS Distributions #define EXCEPTION_THREAD_STATE_COUNT    ARM_THREAD_STATE64_COUNT
24*4d495c6eSApple OSS Distributions #elif __x86_64__
25*4d495c6eSApple OSS Distributions #define machine_thread_state_t          x86_thread_state_t
26*4d495c6eSApple OSS Distributions #define EXCEPTION_THREAD_STATE          x86_THREAD_STATE
27*4d495c6eSApple OSS Distributions #define EXCEPTION_THREAD_STATE_COUNT    x86_THREAD_STATE_COUNT
28*4d495c6eSApple OSS Distributions #else
29*4d495c6eSApple OSS Distributions #error Unsupported architecture
30*4d495c6eSApple OSS Distributions #endif
31*4d495c6eSApple OSS Distributions 
32*4d495c6eSApple OSS Distributions /* in xpc/launch_private.h */
33*4d495c6eSApple OSS Distributions #define XPC_DOMAIN_SYSTEM 1
34*4d495c6eSApple OSS Distributions #define XPC_DOMAIN_PORT 7
35*4d495c6eSApple OSS Distributions 
36*4d495c6eSApple OSS Distributions static mach_port_t
alloc_server_port(void)37*4d495c6eSApple OSS Distributions alloc_server_port(void)
38*4d495c6eSApple OSS Distributions {
39*4d495c6eSApple OSS Distributions 	mach_port_t server_port = MACH_PORT_NULL;
40*4d495c6eSApple OSS Distributions 	kern_return_t kr;
41*4d495c6eSApple OSS Distributions 
42*4d495c6eSApple OSS Distributions 	kr = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &server_port);
43*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "alloc_server_port");
44*4d495c6eSApple OSS Distributions 
45*4d495c6eSApple OSS Distributions 	kr = mach_port_insert_right(mach_task_self(), server_port, server_port, MACH_MSG_TYPE_MAKE_SEND);
46*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "alloc_server_port mach_port_insert_right");
47*4d495c6eSApple OSS Distributions 
48*4d495c6eSApple OSS Distributions 	return server_port;
49*4d495c6eSApple OSS Distributions }
50*4d495c6eSApple OSS Distributions 
51*4d495c6eSApple OSS Distributions static mach_port_t
alloc_reply_port()52*4d495c6eSApple OSS Distributions alloc_reply_port()
53*4d495c6eSApple OSS Distributions {
54*4d495c6eSApple OSS Distributions 	kern_return_t kr;
55*4d495c6eSApple OSS Distributions 	mach_port_t reply_port = MACH_PORT_NULL;
56*4d495c6eSApple OSS Distributions 
57*4d495c6eSApple OSS Distributions 	mach_port_options_t opts = {
58*4d495c6eSApple OSS Distributions 		.flags = MPO_REPLY_PORT | MPO_INSERT_SEND_RIGHT,
59*4d495c6eSApple OSS Distributions 	};
60*4d495c6eSApple OSS Distributions 
61*4d495c6eSApple OSS Distributions 	kr = mach_port_construct(mach_task_self(), &opts, 0, &reply_port);
62*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "alloc_reply_port");
63*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_NE(reply_port, (mach_port_t)MACH_PORT_NULL, "reply_port_create: %s", mach_error_string(kr));
64*4d495c6eSApple OSS Distributions 
65*4d495c6eSApple OSS Distributions 	return reply_port;
66*4d495c6eSApple OSS Distributions }
67*4d495c6eSApple OSS Distributions 
68*4d495c6eSApple OSS Distributions static mach_port_t
alloc_weak_reply_port()69*4d495c6eSApple OSS Distributions alloc_weak_reply_port()
70*4d495c6eSApple OSS Distributions {
71*4d495c6eSApple OSS Distributions 	kern_return_t kr;
72*4d495c6eSApple OSS Distributions 	mach_port_t reply_port = MACH_PORT_NULL;
73*4d495c6eSApple OSS Distributions 
74*4d495c6eSApple OSS Distributions 	mach_port_options_t opts = {
75*4d495c6eSApple OSS Distributions 		.flags = MPO_PROVISIONAL_REPLY_PORT,
76*4d495c6eSApple OSS Distributions 	};
77*4d495c6eSApple OSS Distributions 
78*4d495c6eSApple OSS Distributions 	kr = mach_port_construct(mach_task_self(), &opts, 0, &reply_port);
79*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "alloc_reply_port");
80*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_NE(reply_port, (mach_port_t)MACH_PORT_NULL, "weak_reply_port_create: %s", mach_error_string(kr));
81*4d495c6eSApple OSS Distributions 
82*4d495c6eSApple OSS Distributions 	return reply_port;
83*4d495c6eSApple OSS Distributions }
84*4d495c6eSApple OSS Distributions 
85*4d495c6eSApple OSS Distributions static mach_port_t
alloc_service_port(void)86*4d495c6eSApple OSS Distributions alloc_service_port(void)
87*4d495c6eSApple OSS Distributions {
88*4d495c6eSApple OSS Distributions 	kern_return_t kr;
89*4d495c6eSApple OSS Distributions 	mach_port_t service_port = MACH_PORT_NULL;
90*4d495c6eSApple OSS Distributions 
91*4d495c6eSApple OSS Distributions 	struct mach_service_port_info sp_info = {
92*4d495c6eSApple OSS Distributions 		.mspi_string_name = "com.apple.testservice",
93*4d495c6eSApple OSS Distributions 		.mspi_domain_type = XPC_DOMAIN_SYSTEM,
94*4d495c6eSApple OSS Distributions 	};
95*4d495c6eSApple OSS Distributions 
96*4d495c6eSApple OSS Distributions 	mach_port_options_t opts = {
97*4d495c6eSApple OSS Distributions 		.flags = MPO_STRICT_SERVICE_PORT | MPO_INSERT_SEND_RIGHT,
98*4d495c6eSApple OSS Distributions 		.service_port_info = &sp_info,
99*4d495c6eSApple OSS Distributions 	};
100*4d495c6eSApple OSS Distributions 
101*4d495c6eSApple OSS Distributions 	kr = mach_port_construct(mach_task_self(), &opts, 0, &service_port);
102*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "alloc_service_port");
103*4d495c6eSApple OSS Distributions 
104*4d495c6eSApple OSS Distributions 	return service_port;
105*4d495c6eSApple OSS Distributions }
106*4d495c6eSApple OSS Distributions 
107*4d495c6eSApple OSS Distributions static mach_port_t
alloc_bootstrap_port(void)108*4d495c6eSApple OSS Distributions alloc_bootstrap_port(void)
109*4d495c6eSApple OSS Distributions {
110*4d495c6eSApple OSS Distributions 	kern_return_t kr;
111*4d495c6eSApple OSS Distributions 	mach_port_t bootstrap_port = MACH_PORT_NULL;
112*4d495c6eSApple OSS Distributions 
113*4d495c6eSApple OSS Distributions 	struct mach_service_port_info sp_info = {
114*4d495c6eSApple OSS Distributions 		.mspi_string_name = "com.apple.testservice",
115*4d495c6eSApple OSS Distributions 		.mspi_domain_type = XPC_DOMAIN_PORT,
116*4d495c6eSApple OSS Distributions 	};
117*4d495c6eSApple OSS Distributions 
118*4d495c6eSApple OSS Distributions 	mach_port_options_t opts = {
119*4d495c6eSApple OSS Distributions 		.flags = MPO_STRICT_SERVICE_PORT | MPO_INSERT_SEND_RIGHT,
120*4d495c6eSApple OSS Distributions 		.service_port_info = &sp_info,
121*4d495c6eSApple OSS Distributions 	};
122*4d495c6eSApple OSS Distributions 
123*4d495c6eSApple OSS Distributions 	kr = mach_port_construct(mach_task_self(), &opts, 0, &bootstrap_port);
124*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "alloc_bootstrap_port");
125*4d495c6eSApple OSS Distributions 
126*4d495c6eSApple OSS Distributions 	return bootstrap_port;
127*4d495c6eSApple OSS Distributions }
128*4d495c6eSApple OSS Distributions 
129*4d495c6eSApple OSS Distributions static mach_port_t
alloc_weak_service_port(void)130*4d495c6eSApple OSS Distributions alloc_weak_service_port(void)
131*4d495c6eSApple OSS Distributions {
132*4d495c6eSApple OSS Distributions 	kern_return_t kr;
133*4d495c6eSApple OSS Distributions 	mach_port_t weak_service_port = MACH_PORT_NULL;
134*4d495c6eSApple OSS Distributions 
135*4d495c6eSApple OSS Distributions 	struct mach_service_port_info sp_info = {
136*4d495c6eSApple OSS Distributions 		.mspi_string_name = "com.apple.testservice",
137*4d495c6eSApple OSS Distributions 		.mspi_domain_type = XPC_DOMAIN_SYSTEM,
138*4d495c6eSApple OSS Distributions 	};
139*4d495c6eSApple OSS Distributions 
140*4d495c6eSApple OSS Distributions 	mach_port_options_t opts = {
141*4d495c6eSApple OSS Distributions 		.flags = MPO_SERVICE_PORT | MPO_INSERT_SEND_RIGHT,
142*4d495c6eSApple OSS Distributions 		.service_port_info = &sp_info,
143*4d495c6eSApple OSS Distributions 	};
144*4d495c6eSApple OSS Distributions 
145*4d495c6eSApple OSS Distributions 	kr = mach_port_construct(mach_task_self(), &opts, 0, &weak_service_port);
146*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "alloc_weak_service_port");
147*4d495c6eSApple OSS Distributions 
148*4d495c6eSApple OSS Distributions 	return weak_service_port;
149*4d495c6eSApple OSS Distributions }
150*4d495c6eSApple OSS Distributions 
151*4d495c6eSApple OSS Distributions /* The rcv right of the port would be marked immovable. */
152*4d495c6eSApple OSS Distributions static void
test_immovable_receive_right(void)153*4d495c6eSApple OSS Distributions test_immovable_receive_right(void)
154*4d495c6eSApple OSS Distributions {
155*4d495c6eSApple OSS Distributions 	kern_return_t kr;
156*4d495c6eSApple OSS Distributions 	mach_port_t server_port = MACH_PORT_NULL, reply_port = MACH_PORT_NULL;
157*4d495c6eSApple OSS Distributions 	struct {
158*4d495c6eSApple OSS Distributions 		mach_msg_header_t header;
159*4d495c6eSApple OSS Distributions 		mach_msg_body_t body;
160*4d495c6eSApple OSS Distributions 		mach_msg_port_descriptor_t desc;
161*4d495c6eSApple OSS Distributions 	} msg;
162*4d495c6eSApple OSS Distributions 
163*4d495c6eSApple OSS Distributions 	server_port = alloc_server_port();
164*4d495c6eSApple OSS Distributions 	reply_port = alloc_reply_port();
165*4d495c6eSApple OSS Distributions 
166*4d495c6eSApple OSS Distributions 	msg.header.msgh_remote_port = server_port;
167*4d495c6eSApple OSS Distributions 	msg.header.msgh_local_port = MACH_PORT_NULL;
168*4d495c6eSApple OSS Distributions 	msg.header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0) | MACH_MSGH_BITS_COMPLEX;
169*4d495c6eSApple OSS Distributions 	msg.header.msgh_size = sizeof msg;
170*4d495c6eSApple OSS Distributions 
171*4d495c6eSApple OSS Distributions 	msg.body.msgh_descriptor_count = 1;
172*4d495c6eSApple OSS Distributions 
173*4d495c6eSApple OSS Distributions 	msg.desc.name = reply_port;
174*4d495c6eSApple OSS Distributions 	msg.desc.disposition = MACH_MSG_TYPE_MOVE_RECEIVE;
175*4d495c6eSApple OSS Distributions 	msg.desc.type = MACH_MSG_PORT_DESCRIPTOR;
176*4d495c6eSApple OSS Distributions 	kr = mach_msg_send(&msg.header);
177*4d495c6eSApple OSS Distributions 
178*4d495c6eSApple OSS Distributions 	printf("[reply_port_defense_client test_immovable_receive_right]: mach_msg2() returned %d\n", kr);
179*4d495c6eSApple OSS Distributions }
180*4d495c6eSApple OSS Distributions 
181*4d495c6eSApple OSS Distributions /* The only way you could create a send once right is when you send the port in local port of a mach msg with MAKE_SEND_ONCE disposition. */
182*4d495c6eSApple OSS Distributions static void
test_make_send_once_right(void)183*4d495c6eSApple OSS Distributions test_make_send_once_right(void)
184*4d495c6eSApple OSS Distributions {
185*4d495c6eSApple OSS Distributions 	kern_return_t kr;
186*4d495c6eSApple OSS Distributions 	mach_port_t reply_port = alloc_reply_port();
187*4d495c6eSApple OSS Distributions 	kr = mach_port_insert_right(mach_task_self(), reply_port, reply_port, MACH_MSG_TYPE_MAKE_SEND_ONCE);
188*4d495c6eSApple OSS Distributions 	printf("[reply_port_defense_client test_make_send_once_right]: mach_port_insert_right() returned %d\n", kr);
189*4d495c6eSApple OSS Distributions }
190*4d495c6eSApple OSS Distributions 
191*4d495c6eSApple OSS Distributions static void
test_alloc_weak_reply_port(void)192*4d495c6eSApple OSS Distributions test_alloc_weak_reply_port(void)
193*4d495c6eSApple OSS Distributions {
194*4d495c6eSApple OSS Distributions 	mach_port_t reply_port = alloc_weak_reply_port();
195*4d495c6eSApple OSS Distributions 	printf("[reply_port_defense_client test_alloc_weak_reply_port]: did not crash with port=%d\n", reply_port);
196*4d495c6eSApple OSS Distributions }
197*4d495c6eSApple OSS Distributions 
198*4d495c6eSApple OSS Distributions /* The send right of the port would only used for guarding a name in ipc space, it would not allow to send a message. */
199*4d495c6eSApple OSS Distributions static void
test_using_send_right(void)200*4d495c6eSApple OSS Distributions test_using_send_right(void)
201*4d495c6eSApple OSS Distributions {
202*4d495c6eSApple OSS Distributions 	kern_return_t kr;
203*4d495c6eSApple OSS Distributions 	mach_port_t reply_port = alloc_reply_port();
204*4d495c6eSApple OSS Distributions 	struct {
205*4d495c6eSApple OSS Distributions 		mach_msg_header_t header;
206*4d495c6eSApple OSS Distributions 		mach_msg_body_t body;
207*4d495c6eSApple OSS Distributions 	} msg;
208*4d495c6eSApple OSS Distributions 
209*4d495c6eSApple OSS Distributions 	msg.header.msgh_remote_port = reply_port;
210*4d495c6eSApple OSS Distributions 	msg.header.msgh_local_port = MACH_PORT_NULL;
211*4d495c6eSApple OSS Distributions 	msg.header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0);
212*4d495c6eSApple OSS Distributions 	msg.header.msgh_size = sizeof msg;
213*4d495c6eSApple OSS Distributions 
214*4d495c6eSApple OSS Distributions 	kr = mach_msg_send(&msg.header);
215*4d495c6eSApple OSS Distributions 	printf("[reply_port_defense_client test_using_send_right]: mach_msg2() returned %d\n", kr);
216*4d495c6eSApple OSS Distributions }
217*4d495c6eSApple OSS Distributions 
218*4d495c6eSApple OSS Distributions /* The send right of the port would only used for guarding a name in ipc space, it would not allowed to get moved. */
219*4d495c6eSApple OSS Distributions static void
test_move_send_right(void)220*4d495c6eSApple OSS Distributions test_move_send_right(void)
221*4d495c6eSApple OSS Distributions {
222*4d495c6eSApple OSS Distributions 	kern_return_t kr;
223*4d495c6eSApple OSS Distributions 	mach_port_t server_port = MACH_PORT_NULL, reply_port = MACH_PORT_NULL;
224*4d495c6eSApple OSS Distributions 	struct {
225*4d495c6eSApple OSS Distributions 		mach_msg_header_t header;
226*4d495c6eSApple OSS Distributions 		mach_msg_body_t body;
227*4d495c6eSApple OSS Distributions 		mach_msg_port_descriptor_t desc;
228*4d495c6eSApple OSS Distributions 	} msg;
229*4d495c6eSApple OSS Distributions 
230*4d495c6eSApple OSS Distributions 	server_port = alloc_server_port();
231*4d495c6eSApple OSS Distributions 	reply_port = alloc_reply_port();
232*4d495c6eSApple OSS Distributions 
233*4d495c6eSApple OSS Distributions 	msg.header.msgh_remote_port = server_port;
234*4d495c6eSApple OSS Distributions 	msg.header.msgh_local_port = MACH_PORT_NULL;
235*4d495c6eSApple OSS Distributions 	msg.header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0) | MACH_MSGH_BITS_COMPLEX;
236*4d495c6eSApple OSS Distributions 	msg.header.msgh_size = sizeof msg;
237*4d495c6eSApple OSS Distributions 
238*4d495c6eSApple OSS Distributions 	msg.body.msgh_descriptor_count = 1;
239*4d495c6eSApple OSS Distributions 
240*4d495c6eSApple OSS Distributions 	msg.desc.name = reply_port;
241*4d495c6eSApple OSS Distributions 	msg.desc.disposition = MACH_MSG_TYPE_MOVE_SEND;
242*4d495c6eSApple OSS Distributions 	msg.desc.type = MACH_MSG_PORT_DESCRIPTOR;
243*4d495c6eSApple OSS Distributions 
244*4d495c6eSApple OSS Distributions 	kr = mach_msg_send(&msg.header);
245*4d495c6eSApple OSS Distributions 	printf("[reply_port_defense_client test_move_send_right]: mach_msg2() returned %d\n", kr);
246*4d495c6eSApple OSS Distributions }
247*4d495c6eSApple OSS Distributions 
248*4d495c6eSApple OSS Distributions static void
test_unentitled_thread_set_state(void)249*4d495c6eSApple OSS Distributions test_unentitled_thread_set_state(void)
250*4d495c6eSApple OSS Distributions {
251*4d495c6eSApple OSS Distributions 	machine_thread_state_t ts;
252*4d495c6eSApple OSS Distributions 	mach_msg_type_number_t count = MACHINE_THREAD_STATE_COUNT;
253*4d495c6eSApple OSS Distributions 
254*4d495c6eSApple OSS Distributions 	/* thread_set_state as a platform restrictions binary should fail */
255*4d495c6eSApple OSS Distributions 	kern_return_t kr = thread_get_state(mach_thread_self(), MACHINE_THREAD_STATE, (thread_state_t)&ts, &count);
256*4d495c6eSApple OSS Distributions 
257*4d495c6eSApple OSS Distributions 	kr = thread_set_state(mach_thread_self(), MACHINE_THREAD_STATE, (thread_state_t)&ts, count);
258*4d495c6eSApple OSS Distributions 	assert(kr != KERN_SUCCESS);
259*4d495c6eSApple OSS Distributions 	exit(-1); /* Should have crashed before here! */
260*4d495c6eSApple OSS Distributions }
261*4d495c6eSApple OSS Distributions 
262*4d495c6eSApple OSS Distributions static void
test_unentitled_thread_set_exception_ports(void)263*4d495c6eSApple OSS Distributions test_unentitled_thread_set_exception_ports(void)
264*4d495c6eSApple OSS Distributions {
265*4d495c6eSApple OSS Distributions 	mach_port_t exc_port = alloc_server_port();
266*4d495c6eSApple OSS Distributions 
267*4d495c6eSApple OSS Distributions 	/* thread_set_exception_ports as a platform restrictions binary should fail without identity protected options */
268*4d495c6eSApple OSS Distributions 	kern_return_t kr = thread_set_exception_ports(
269*4d495c6eSApple OSS Distributions 		mach_thread_self(),
270*4d495c6eSApple OSS Distributions 		EXC_MASK_ALL,
271*4d495c6eSApple OSS Distributions 		exc_port,
272*4d495c6eSApple OSS Distributions 		(exception_behavior_t)((unsigned int)EXCEPTION_DEFAULT | MACH_EXCEPTION_CODES),
273*4d495c6eSApple OSS Distributions 		EXCEPTION_THREAD_STATE);
274*4d495c6eSApple OSS Distributions 
275*4d495c6eSApple OSS Distributions 	/* thread_set_exception_ports is supposed to crash, unless the policy is turned off.
276*4d495c6eSApple OSS Distributions 	 * Things that disable the policy: AMFI boot-args in use, SIP disabled,
277*4d495c6eSApple OSS Distributions 	 * third party plugins in a process. The caller of this client will check
278*4d495c6eSApple OSS Distributions 	 * whether the test crashed and correctly adhered to these policies.
279*4d495c6eSApple OSS Distributions 	 */
280*4d495c6eSApple OSS Distributions 	printf("thread_set_exception_ports did not crash\n");
281*4d495c6eSApple OSS Distributions }
282*4d495c6eSApple OSS Distributions 
283*4d495c6eSApple OSS Distributions static void
unentitled_set_exception_ports_pass(void)284*4d495c6eSApple OSS Distributions unentitled_set_exception_ports_pass(void)
285*4d495c6eSApple OSS Distributions {
286*4d495c6eSApple OSS Distributions 	mach_port_t exc_port = alloc_server_port();
287*4d495c6eSApple OSS Distributions 
288*4d495c6eSApple OSS Distributions 	/* thread_set_exception_ports with state *IDENTITY_PROTECTED should not fail */
289*4d495c6eSApple OSS Distributions 	kern_return_t kr = thread_set_exception_ports(
290*4d495c6eSApple OSS Distributions 		mach_thread_self(),
291*4d495c6eSApple OSS Distributions 		EXC_MASK_ALL,
292*4d495c6eSApple OSS Distributions 		exc_port,
293*4d495c6eSApple OSS Distributions 		(exception_behavior_t)((unsigned int)EXCEPTION_STATE_IDENTITY_PROTECTED | MACH_EXCEPTION_CODES),
294*4d495c6eSApple OSS Distributions 		EXCEPTION_THREAD_STATE);
295*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "thread_set_exception_ports EXCEPTION_STATE_IDENTITY_PROTECTED");
296*4d495c6eSApple OSS Distributions 
297*4d495c6eSApple OSS Distributions 	kr = thread_set_exception_ports(
298*4d495c6eSApple OSS Distributions 		mach_thread_self(),
299*4d495c6eSApple OSS Distributions 		EXC_MASK_ALL,
300*4d495c6eSApple OSS Distributions 		exc_port,
301*4d495c6eSApple OSS Distributions 		(exception_behavior_t)((unsigned int)EXCEPTION_IDENTITY_PROTECTED | MACH_EXCEPTION_CODES),
302*4d495c6eSApple OSS Distributions 		EXCEPTION_THREAD_STATE);
303*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "thread_set_exception_ports EXCEPTION_IDENTITY_PROTECTED");
304*4d495c6eSApple OSS Distributions 
305*4d495c6eSApple OSS Distributions 	return;
306*4d495c6eSApple OSS Distributions }
307*4d495c6eSApple OSS Distributions 
308*4d495c6eSApple OSS Distributions static void
exception_ports_crash(void)309*4d495c6eSApple OSS Distributions exception_ports_crash(void)
310*4d495c6eSApple OSS Distributions {
311*4d495c6eSApple OSS Distributions 	kern_return_t kr;
312*4d495c6eSApple OSS Distributions 	mach_port_t exc_port;
313*4d495c6eSApple OSS Distributions 	mach_port_options_t opts = {
314*4d495c6eSApple OSS Distributions 		.flags = MPO_INSERT_SEND_RIGHT | MPO_EXCEPTION_PORT,
315*4d495c6eSApple OSS Distributions 	};
316*4d495c6eSApple OSS Distributions 
317*4d495c6eSApple OSS Distributions 	kr = mach_port_construct(mach_task_self(), &opts, 0ull, &exc_port);
318*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "exception_ports_crash mach_port_construct");
319*4d495c6eSApple OSS Distributions 
320*4d495c6eSApple OSS Distributions 	kr = task_register_hardened_exception_handler(current_task(),
321*4d495c6eSApple OSS Distributions 	    0, EXC_MASK_BAD_ACCESS,
322*4d495c6eSApple OSS Distributions 	    EXCEPTION_STATE_IDENTITY_PROTECTED, EXCEPTION_THREAD_STATE, exc_port);
323*4d495c6eSApple OSS Distributions 
324*4d495c6eSApple OSS Distributions 	kr = thread_set_exception_ports(
325*4d495c6eSApple OSS Distributions 		mach_thread_self(),
326*4d495c6eSApple OSS Distributions 		EXC_MASK_BAD_ACCESS,
327*4d495c6eSApple OSS Distributions 		exc_port,
328*4d495c6eSApple OSS Distributions 		(exception_behavior_t)((unsigned int)EXCEPTION_STATE_IDENTITY_PROTECTED | MACH_EXCEPTION_CODES),
329*4d495c6eSApple OSS Distributions 		EXCEPTION_THREAD_STATE);
330*4d495c6eSApple OSS Distributions 
331*4d495c6eSApple OSS Distributions 	printf("thread_set_exception_ports did not crash: %d\n", kr);
332*4d495c6eSApple OSS Distributions }
333*4d495c6eSApple OSS Distributions 
334*4d495c6eSApple OSS Distributions static void
kobject_reply_port_defense(void)335*4d495c6eSApple OSS Distributions kobject_reply_port_defense(void)
336*4d495c6eSApple OSS Distributions {
337*4d495c6eSApple OSS Distributions 	machine_thread_state_t ts;
338*4d495c6eSApple OSS Distributions 	mach_msg_type_number_t count = MACHINE_THREAD_STATE_COUNT;
339*4d495c6eSApple OSS Distributions 	mach_port_t port = MACH_PORT_NULL;
340*4d495c6eSApple OSS Distributions 
341*4d495c6eSApple OSS Distributions 	kern_return_t kr = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &port);
342*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "kobject_reply_port_defense mach_port_allocate");
343*4d495c6eSApple OSS Distributions 
344*4d495c6eSApple OSS Distributions 	// make a kobject call
345*4d495c6eSApple OSS Distributions 	kr = thread_get_state(mach_thread_self(), MACHINE_THREAD_STATE, (thread_state_t)&ts, &count);
346*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "kobject_reply_port_defense thread_get_state");
347*4d495c6eSApple OSS Distributions 
348*4d495c6eSApple OSS Distributions 	// set the MIG reply port to a "normal" port
349*4d495c6eSApple OSS Distributions 	_os_tsd_set_direct(__TSD_MIG_REPLY, (void *)(uintptr_t)port);
350*4d495c6eSApple OSS Distributions 
351*4d495c6eSApple OSS Distributions 	kr = thread_get_state(mach_thread_self(), MACHINE_THREAD_STATE, (thread_state_t)&ts, &count);
352*4d495c6eSApple OSS Distributions 
353*4d495c6eSApple OSS Distributions 	T_FAIL("kobject call did not crash: %d\n", kr);
354*4d495c6eSApple OSS Distributions }
355*4d495c6eSApple OSS Distributions 
356*4d495c6eSApple OSS Distributions static void
test_move_service_port(void)357*4d495c6eSApple OSS Distributions test_move_service_port(void)
358*4d495c6eSApple OSS Distributions {
359*4d495c6eSApple OSS Distributions 	kern_return_t kr;
360*4d495c6eSApple OSS Distributions 	mach_port_t server_port = MACH_PORT_NULL, service_port = MACH_PORT_NULL;
361*4d495c6eSApple OSS Distributions 	struct {
362*4d495c6eSApple OSS Distributions 		mach_msg_header_t header;
363*4d495c6eSApple OSS Distributions 		mach_msg_body_t body;
364*4d495c6eSApple OSS Distributions 		mach_msg_port_descriptor_t desc;
365*4d495c6eSApple OSS Distributions 	} msg;
366*4d495c6eSApple OSS Distributions 
367*4d495c6eSApple OSS Distributions 	server_port = alloc_server_port();
368*4d495c6eSApple OSS Distributions 	service_port = alloc_service_port();
369*4d495c6eSApple OSS Distributions 
370*4d495c6eSApple OSS Distributions 	msg.header.msgh_remote_port = server_port;
371*4d495c6eSApple OSS Distributions 	msg.header.msgh_local_port = MACH_PORT_NULL;
372*4d495c6eSApple OSS Distributions 	msg.header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0) | MACH_MSGH_BITS_COMPLEX;
373*4d495c6eSApple OSS Distributions 	msg.header.msgh_size = sizeof msg;
374*4d495c6eSApple OSS Distributions 
375*4d495c6eSApple OSS Distributions 	msg.body.msgh_descriptor_count = 1;
376*4d495c6eSApple OSS Distributions 
377*4d495c6eSApple OSS Distributions 	msg.desc.name = service_port;
378*4d495c6eSApple OSS Distributions 	msg.desc.disposition = MACH_MSG_TYPE_MOVE_RECEIVE;
379*4d495c6eSApple OSS Distributions 	msg.desc.type = MACH_MSG_PORT_DESCRIPTOR;
380*4d495c6eSApple OSS Distributions 
381*4d495c6eSApple OSS Distributions 	kr = mach_msg_send(&msg.header);
382*4d495c6eSApple OSS Distributions 	T_FAIL("move service port did not crash: %d\n", kr);
383*4d495c6eSApple OSS Distributions }
384*4d495c6eSApple OSS Distributions 
385*4d495c6eSApple OSS Distributions static void
test_mktimer_notification_policy(void)386*4d495c6eSApple OSS Distributions test_mktimer_notification_policy(void)
387*4d495c6eSApple OSS Distributions {
388*4d495c6eSApple OSS Distributions 	mach_port_t timer_port = MACH_PORT_NULL;
389*4d495c6eSApple OSS Distributions 	mach_port_t notify_port = MACH_PORT_NULL;
390*4d495c6eSApple OSS Distributions 	mach_port_t previous = MACH_PORT_NULL;
391*4d495c6eSApple OSS Distributions 
392*4d495c6eSApple OSS Distributions 	kern_return_t kr = KERN_SUCCESS;
393*4d495c6eSApple OSS Distributions 
394*4d495c6eSApple OSS Distributions 	timer_port = mk_timer_create();
395*4d495c6eSApple OSS Distributions 	T_ASSERT_NE(timer_port, (mach_port_t)MACH_PORT_NULL, "mk_timer_create: %s", mach_error_string(kr));
396*4d495c6eSApple OSS Distributions 
397*4d495c6eSApple OSS Distributions 	/* notification port for the mk_timer port to come back on */
398*4d495c6eSApple OSS Distributions 	kr = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &notify_port);
399*4d495c6eSApple OSS Distributions 	T_ASSERT_EQ(kr, KERN_SUCCESS, "mach_port_allocate(notify_port): %s", mach_error_string(kr));
400*4d495c6eSApple OSS Distributions 
401*4d495c6eSApple OSS Distributions 	T_LOG("timer: 0x%x, notify: 0x%x", timer_port, notify_port);
402*4d495c6eSApple OSS Distributions 
403*4d495c6eSApple OSS Distributions 	/* request a port-destroyed notification on the timer port, which should crash */
404*4d495c6eSApple OSS Distributions 	kr = mach_port_request_notification(mach_task_self(), timer_port, MACH_NOTIFY_PORT_DESTROYED,
405*4d495c6eSApple OSS Distributions 	    0, notify_port, MACH_MSG_TYPE_MAKE_SEND_ONCE, &previous);
406*4d495c6eSApple OSS Distributions 
407*4d495c6eSApple OSS Distributions 	T_FAIL("mktimer did not crash with exc_guard kr=%d", kr);
408*4d495c6eSApple OSS Distributions }
409*4d495c6eSApple OSS Distributions 
410*4d495c6eSApple OSS Distributions static void
test_reply_port_port_destroyed_notification_policy(void)411*4d495c6eSApple OSS Distributions test_reply_port_port_destroyed_notification_policy(void)
412*4d495c6eSApple OSS Distributions {
413*4d495c6eSApple OSS Distributions 	mach_port_t reply_port = MACH_PORT_NULL;
414*4d495c6eSApple OSS Distributions 	mach_port_t previous = MACH_PORT_NULL;
415*4d495c6eSApple OSS Distributions 	mach_port_t notify_port = MACH_PORT_NULL;
416*4d495c6eSApple OSS Distributions 
417*4d495c6eSApple OSS Distributions 	kern_return_t kr = KERN_SUCCESS;
418*4d495c6eSApple OSS Distributions 	mach_port_options_t opts = {};
419*4d495c6eSApple OSS Distributions 
420*4d495c6eSApple OSS Distributions 	reply_port = alloc_reply_port();
421*4d495c6eSApple OSS Distributions 
422*4d495c6eSApple OSS Distributions 	kr = mach_port_construct(mach_task_self(), &opts, 0, &notify_port);
423*4d495c6eSApple OSS Distributions 	T_ASSERT_EQ(kr, KERN_SUCCESS, "mach_port_allocate(notify_port): %s", mach_error_string(kr));
424*4d495c6eSApple OSS Distributions 
425*4d495c6eSApple OSS Distributions 	/* request a port-destroyed notification on the reply port */
426*4d495c6eSApple OSS Distributions 	kr = mach_port_request_notification(mach_task_self(), reply_port, MACH_NOTIFY_PORT_DESTROYED,
427*4d495c6eSApple OSS Distributions 	    0, notify_port, MACH_MSG_TYPE_MAKE_SEND_ONCE, &previous);
428*4d495c6eSApple OSS Distributions 
429*4d495c6eSApple OSS Distributions 	printf("reply port did not crash kr=%d\n", kr);
430*4d495c6eSApple OSS Distributions }
431*4d495c6eSApple OSS Distributions 
432*4d495c6eSApple OSS Distributions static void
test_reply_port_no_senders_notification_policy(void)433*4d495c6eSApple OSS Distributions test_reply_port_no_senders_notification_policy(void)
434*4d495c6eSApple OSS Distributions {
435*4d495c6eSApple OSS Distributions 	mach_port_t reply_port = MACH_PORT_NULL;
436*4d495c6eSApple OSS Distributions 	mach_port_t previous = MACH_PORT_NULL;
437*4d495c6eSApple OSS Distributions 	mach_port_t notify_port = MACH_PORT_NULL;
438*4d495c6eSApple OSS Distributions 
439*4d495c6eSApple OSS Distributions 	kern_return_t kr = KERN_SUCCESS;
440*4d495c6eSApple OSS Distributions 
441*4d495c6eSApple OSS Distributions 	reply_port = alloc_reply_port();
442*4d495c6eSApple OSS Distributions 	mach_port_options_t opts = {};
443*4d495c6eSApple OSS Distributions 
444*4d495c6eSApple OSS Distributions 	kr = mach_port_construct(mach_task_self(), &opts, 0, &notify_port);
445*4d495c6eSApple OSS Distributions 	T_ASSERT_EQ(kr, KERN_SUCCESS, "mach_port_allocate(notify_port): %s", mach_error_string(kr));
446*4d495c6eSApple OSS Distributions 
447*4d495c6eSApple OSS Distributions 	/* request a no-senders notification on the reply port */
448*4d495c6eSApple OSS Distributions 	kr = mach_port_request_notification(mach_task_self(), reply_port, MACH_NOTIFY_NO_SENDERS,
449*4d495c6eSApple OSS Distributions 	    0, notify_port, MACH_MSG_TYPE_MAKE_SEND_ONCE, &previous);
450*4d495c6eSApple OSS Distributions 
451*4d495c6eSApple OSS Distributions 	T_FAIL("reply port did not crash kr=%d", kr);
452*4d495c6eSApple OSS Distributions }
453*4d495c6eSApple OSS Distributions 
454*4d495c6eSApple OSS Distributions static void
test_reply_port_insert_right_disallowed(void)455*4d495c6eSApple OSS Distributions test_reply_port_insert_right_disallowed(void)
456*4d495c6eSApple OSS Distributions {
457*4d495c6eSApple OSS Distributions 	mach_port_t reply_port = MACH_PORT_NULL;
458*4d495c6eSApple OSS Distributions 	mach_port_t send_reply_port = MACH_PORT_NULL;
459*4d495c6eSApple OSS Distributions 	mach_msg_type_name_t right = 0;
460*4d495c6eSApple OSS Distributions 
461*4d495c6eSApple OSS Distributions 	kern_return_t kr = KERN_SUCCESS;
462*4d495c6eSApple OSS Distributions 	reply_port = alloc_reply_port();
463*4d495c6eSApple OSS Distributions 	kr = mach_port_extract_right(mach_task_self(), reply_port, MACH_MSG_TYPE_MAKE_SEND_ONCE, &send_reply_port, &right);
464*4d495c6eSApple OSS Distributions 	T_ASSERT_EQ(kr, KERN_SUCCESS, "mach_port_extract_right(reply_port, make_send_once): %s", mach_error_string(kr));
465*4d495c6eSApple OSS Distributions 
466*4d495c6eSApple OSS Distributions 	T_FAIL("reply port make send once outside of kmsg did not crash kr=%d", kr);
467*4d495c6eSApple OSS Distributions }
468*4d495c6eSApple OSS Distributions 
469*4d495c6eSApple OSS Distributions static kern_return_t
move_port(mach_port_t immovable_port)470*4d495c6eSApple OSS Distributions move_port(mach_port_t immovable_port)
471*4d495c6eSApple OSS Distributions {
472*4d495c6eSApple OSS Distributions 	mach_port_t server_port = MACH_PORT_NULL;
473*4d495c6eSApple OSS Distributions 	struct {
474*4d495c6eSApple OSS Distributions 		mach_msg_header_t header;
475*4d495c6eSApple OSS Distributions 		mach_msg_body_t body;
476*4d495c6eSApple OSS Distributions 		mach_msg_port_descriptor_t desc;
477*4d495c6eSApple OSS Distributions 	} msg;
478*4d495c6eSApple OSS Distributions 
479*4d495c6eSApple OSS Distributions 	server_port = alloc_server_port();
480*4d495c6eSApple OSS Distributions 
481*4d495c6eSApple OSS Distributions 	msg.header.msgh_remote_port = server_port;
482*4d495c6eSApple OSS Distributions 	msg.header.msgh_local_port = MACH_PORT_NULL;
483*4d495c6eSApple OSS Distributions 	msg.header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0) | MACH_MSGH_BITS_COMPLEX;
484*4d495c6eSApple OSS Distributions 	msg.header.msgh_size = sizeof msg;
485*4d495c6eSApple OSS Distributions 
486*4d495c6eSApple OSS Distributions 	msg.body.msgh_descriptor_count = 1;
487*4d495c6eSApple OSS Distributions 
488*4d495c6eSApple OSS Distributions 	msg.desc.name = immovable_port;
489*4d495c6eSApple OSS Distributions 	msg.desc.disposition = MACH_MSG_TYPE_MOVE_SEND;
490*4d495c6eSApple OSS Distributions 	msg.desc.type = MACH_MSG_PORT_DESCRIPTOR;
491*4d495c6eSApple OSS Distributions 	return mach_msg_send(&msg.header);
492*4d495c6eSApple OSS Distributions }
493*4d495c6eSApple OSS Distributions 
494*4d495c6eSApple OSS Distributions /* attempt to move mach_task_self */
495*4d495c6eSApple OSS Distributions static void
test_mach_task_self_send_movability(void)496*4d495c6eSApple OSS Distributions test_mach_task_self_send_movability(void)
497*4d495c6eSApple OSS Distributions {
498*4d495c6eSApple OSS Distributions 	kern_return_t kr = move_port(mach_task_self());
499*4d495c6eSApple OSS Distributions 	printf("[reply_port_defense_client test_task_self_immovable]: mach_msg2() returned %d\n", kr);
500*4d495c6eSApple OSS Distributions }
501*4d495c6eSApple OSS Distributions 
502*4d495c6eSApple OSS Distributions /* mach_task_self() is movable before and after calling task_get_special_port, when entitled */
503*4d495c6eSApple OSS Distributions static void
test_task_self_movable_send(void)504*4d495c6eSApple OSS Distributions test_task_self_movable_send(void)
505*4d495c6eSApple OSS Distributions {
506*4d495c6eSApple OSS Distributions 	kern_return_t kr;
507*4d495c6eSApple OSS Distributions 	mach_port_t task_self = MACH_PORT_NULL;
508*4d495c6eSApple OSS Distributions 
509*4d495c6eSApple OSS Distributions 	kr = move_port(mach_task_self());
510*4d495c6eSApple OSS Distributions 	T_EXPECT_MACH_SUCCESS(kr, "move mach_task_self");
511*4d495c6eSApple OSS Distributions 
512*4d495c6eSApple OSS Distributions 	kr = task_get_special_port(mach_task_self(), TASK_KERNEL_PORT, &task_self);
513*4d495c6eSApple OSS Distributions 	T_EXPECT_MACH_SUCCESS(kr, "task_get_special_port");
514*4d495c6eSApple OSS Distributions 
515*4d495c6eSApple OSS Distributions 	kr = move_port(mach_task_self());
516*4d495c6eSApple OSS Distributions 	T_EXPECT_MACH_SUCCESS(kr, "move mach_task_self again");
517*4d495c6eSApple OSS Distributions 
518*4d495c6eSApple OSS Distributions 	mach_port_t thread_port = pthread_mach_thread_np(pthread_main_thread_np());
519*4d495c6eSApple OSS Distributions 	kr = move_port(thread_port);
520*4d495c6eSApple OSS Distributions 	T_EXPECT_MACH_SUCCESS(kr, "move main_thread_port");
521*4d495c6eSApple OSS Distributions }
522*4d495c6eSApple OSS Distributions 
523*4d495c6eSApple OSS Distributions static void
test_move_newly_constructed_port_immovable_send(void)524*4d495c6eSApple OSS Distributions test_move_newly_constructed_port_immovable_send(void)
525*4d495c6eSApple OSS Distributions {
526*4d495c6eSApple OSS Distributions 	kern_return_t kr;
527*4d495c6eSApple OSS Distributions 	mach_port_t port = MACH_PORT_NULL;
528*4d495c6eSApple OSS Distributions 
529*4d495c6eSApple OSS Distributions 	mach_port_options_t opts = {
530*4d495c6eSApple OSS Distributions 		.flags = MPO_INSERT_SEND_RIGHT | MPO_CONNECTION_PORT,
531*4d495c6eSApple OSS Distributions 		.service_port_name = MPO_ANONYMOUS_SERVICE,
532*4d495c6eSApple OSS Distributions 	};
533*4d495c6eSApple OSS Distributions 
534*4d495c6eSApple OSS Distributions 	kr = mach_port_construct(mach_task_self(), &opts, 0, &port);
535*4d495c6eSApple OSS Distributions 
536*4d495c6eSApple OSS Distributions 	kr = move_port(port);
537*4d495c6eSApple OSS Distributions 	printf("kr=%d\n", kr);
538*4d495c6eSApple OSS Distributions 	T_EXPECT_MACH_ERROR(kr, KERN_DENIED, "move port with immovable send rights");
539*4d495c6eSApple OSS Distributions }
540*4d495c6eSApple OSS Distributions 
541*4d495c6eSApple OSS Distributions static void
test_move_special_reply_port(void)542*4d495c6eSApple OSS Distributions test_move_special_reply_port(void)
543*4d495c6eSApple OSS Distributions {
544*4d495c6eSApple OSS Distributions 	kern_return_t kr;
545*4d495c6eSApple OSS Distributions 	mach_port_t special_reply_port = thread_get_special_reply_port();
546*4d495c6eSApple OSS Distributions 
547*4d495c6eSApple OSS Distributions 	kr = move_port(special_reply_port);
548*4d495c6eSApple OSS Distributions 	T_EXPECT_MACH_ERROR(kr, KERN_DENIED, "move special reply port");
549*4d495c6eSApple OSS Distributions }
550*4d495c6eSApple OSS Distributions 
551*4d495c6eSApple OSS Distributions static void
test_reply_port_header_disposition(void)552*4d495c6eSApple OSS Distributions test_reply_port_header_disposition(void)
553*4d495c6eSApple OSS Distributions {
554*4d495c6eSApple OSS Distributions 	kern_return_t kr;
555*4d495c6eSApple OSS Distributions 	mach_port_t server_port = MACH_PORT_NULL;
556*4d495c6eSApple OSS Distributions 	mach_port_t reply_port1 = MACH_PORT_NULL, reply_port2 = MACH_PORT_NULL;
557*4d495c6eSApple OSS Distributions 	struct {
558*4d495c6eSApple OSS Distributions 		mach_msg_header_t header;
559*4d495c6eSApple OSS Distributions 	} msg;
560*4d495c6eSApple OSS Distributions 
561*4d495c6eSApple OSS Distributions 	server_port = alloc_server_port();
562*4d495c6eSApple OSS Distributions 	reply_port1 = alloc_reply_port();
563*4d495c6eSApple OSS Distributions 	reply_port2 = alloc_reply_port();
564*4d495c6eSApple OSS Distributions 
565*4d495c6eSApple OSS Distributions 	msg.header.msgh_remote_port = server_port;
566*4d495c6eSApple OSS Distributions 	msg.header.msgh_size = sizeof msg;
567*4d495c6eSApple OSS Distributions 
568*4d495c6eSApple OSS Distributions 	/* sending with make_send_once should succeed */
569*4d495c6eSApple OSS Distributions 	msg.header.msgh_local_port = reply_port1;
570*4d495c6eSApple OSS Distributions 	msg.header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND,
571*4d495c6eSApple OSS Distributions 	    MACH_MSG_TYPE_MAKE_SEND_ONCE);
572*4d495c6eSApple OSS Distributions 	kr = mach_msg_send(&msg.header);
573*4d495c6eSApple OSS Distributions 	T_EXPECT_MACH_SUCCESS(kr, "reply_port_disposition make_send_once");
574*4d495c6eSApple OSS Distributions 
575*4d495c6eSApple OSS Distributions 	/* sending with make_send should fail */
576*4d495c6eSApple OSS Distributions 	msg.header.msgh_local_port = reply_port2;
577*4d495c6eSApple OSS Distributions 	msg.header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND,
578*4d495c6eSApple OSS Distributions 	    MACH_MSG_TYPE_MAKE_SEND);
579*4d495c6eSApple OSS Distributions 	kr = mach_msg_send(&msg.header);
580*4d495c6eSApple OSS Distributions 	T_ASSERT_MACH_ERROR(kr, MACH_SEND_INVALID_REPLY, "reply_port_disposition make_send");
581*4d495c6eSApple OSS Distributions }
582*4d495c6eSApple OSS Distributions 
583*4d495c6eSApple OSS Distributions static void
test_service_port_as_exception_port(void)584*4d495c6eSApple OSS Distributions test_service_port_as_exception_port(void)
585*4d495c6eSApple OSS Distributions {
586*4d495c6eSApple OSS Distributions 	kern_return_t kr;
587*4d495c6eSApple OSS Distributions 	mach_port_t service_port = alloc_service_port();
588*4d495c6eSApple OSS Distributions 	mach_port_t bootstrap_port = alloc_bootstrap_port();
589*4d495c6eSApple OSS Distributions 	mach_port_t weak_service_port = alloc_weak_service_port();
590*4d495c6eSApple OSS Distributions 
591*4d495c6eSApple OSS Distributions 	/* Should succeed */
592*4d495c6eSApple OSS Distributions 	kr = thread_set_exception_ports(
593*4d495c6eSApple OSS Distributions 		mach_thread_self(),
594*4d495c6eSApple OSS Distributions 		EXC_MASK_ALL,
595*4d495c6eSApple OSS Distributions 		service_port,
596*4d495c6eSApple OSS Distributions 		(exception_behavior_t)((unsigned int)EXCEPTION_STATE_IDENTITY_PROTECTED | MACH_EXCEPTION_CODES),
597*4d495c6eSApple OSS Distributions 		EXCEPTION_THREAD_STATE);
598*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "test_service_port_as_exception_port IOT_SERVICE_PORT");
599*4d495c6eSApple OSS Distributions 
600*4d495c6eSApple OSS Distributions 	/* Should succeed */
601*4d495c6eSApple OSS Distributions 	kr = thread_set_exception_ports(
602*4d495c6eSApple OSS Distributions 		mach_thread_self(),
603*4d495c6eSApple OSS Distributions 		EXC_MASK_ALL,
604*4d495c6eSApple OSS Distributions 		weak_service_port,
605*4d495c6eSApple OSS Distributions 		(exception_behavior_t)((unsigned int)EXCEPTION_STATE_IDENTITY_PROTECTED | MACH_EXCEPTION_CODES),
606*4d495c6eSApple OSS Distributions 		EXCEPTION_THREAD_STATE);
607*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "test_service_port_as_exception_port IOT_WEAK_SERVICE_PORT");
608*4d495c6eSApple OSS Distributions 
609*4d495c6eSApple OSS Distributions 	/* Should fail, but no guard exception */
610*4d495c6eSApple OSS Distributions 	kr = thread_set_exception_ports(
611*4d495c6eSApple OSS Distributions 		mach_thread_self(),
612*4d495c6eSApple OSS Distributions 		EXC_MASK_ALL,
613*4d495c6eSApple OSS Distributions 		bootstrap_port,
614*4d495c6eSApple OSS Distributions 		(exception_behavior_t)((unsigned int)EXCEPTION_STATE_IDENTITY_PROTECTED | MACH_EXCEPTION_CODES),
615*4d495c6eSApple OSS Distributions 		EXCEPTION_THREAD_STATE);
616*4d495c6eSApple OSS Distributions 	T_QUIET; T_ASSERT_MACH_ERROR(kr, KERN_INVALID_RIGHT, "test_service_port_as_exception_port IOT_BOOTSTRAP_PORT");
617*4d495c6eSApple OSS Distributions }
618*4d495c6eSApple OSS Distributions 
619*4d495c6eSApple OSS Distributions int
main(int argc,char * argv[])620*4d495c6eSApple OSS Distributions main(int argc, char *argv[])
621*4d495c6eSApple OSS Distributions {
622*4d495c6eSApple OSS Distributions 	uint32_t my_csflags = 0;
623*4d495c6eSApple OSS Distributions 	bool thirdparty_hardened = !strcmp(argv[0], "./reply_port_defense_client_3P_hardened");
624*4d495c6eSApple OSS Distributions 	T_ASSERT_POSIX_ZERO(csops(getpid(), CS_OPS_STATUS, &my_csflags, sizeof(my_csflags)), NULL);
625*4d495c6eSApple OSS Distributions 
626*4d495c6eSApple OSS Distributions 	/* TODO add some sysctl which disabled platform binary bit here */
627*4d495c6eSApple OSS Distributions 	if ((my_csflags & CS_PLATFORM_BINARY) == thirdparty_hardened) {
628*4d495c6eSApple OSS Distributions 		printf("platform binary does not match expected\n");
629*4d495c6eSApple OSS Distributions 		return -1;
630*4d495c6eSApple OSS Distributions 	}
631*4d495c6eSApple OSS Distributions 
632*4d495c6eSApple OSS Distributions 
633*4d495c6eSApple OSS Distributions 	void (*tests[MAX_TEST_NUM])(void) = {
634*4d495c6eSApple OSS Distributions 		test_immovable_receive_right, /* 0 */
635*4d495c6eSApple OSS Distributions 		test_using_send_right,        /* 1 */
636*4d495c6eSApple OSS Distributions 		test_move_send_right,         /* 2 */
637*4d495c6eSApple OSS Distributions 		test_make_send_once_right,    /* 3 */
638*4d495c6eSApple OSS Distributions 		NULL, /* 4 */
639*4d495c6eSApple OSS Distributions 		test_unentitled_thread_set_exception_ports, /* 5 */
640*4d495c6eSApple OSS Distributions 		test_unentitled_thread_set_state, /* 6 */
641*4d495c6eSApple OSS Distributions 		unentitled_set_exception_ports_pass,
642*4d495c6eSApple OSS Distributions 		exception_ports_crash, /* 8 */
643*4d495c6eSApple OSS Distributions 		kobject_reply_port_defense, /* 9 */
644*4d495c6eSApple OSS Distributions 		test_alloc_weak_reply_port, /* 10 */
645*4d495c6eSApple OSS Distributions 		test_move_service_port, /* 11 */
646*4d495c6eSApple OSS Distributions 		test_mktimer_notification_policy, /* 12 */
647*4d495c6eSApple OSS Distributions 		test_reply_port_port_destroyed_notification_policy, /* 13 */
648*4d495c6eSApple OSS Distributions 		test_reply_port_no_senders_notification_policy, /* 14 */
649*4d495c6eSApple OSS Distributions 		test_reply_port_insert_right_disallowed, /* 15 */
650*4d495c6eSApple OSS Distributions 		test_mach_task_self_send_movability, /* 16 */
651*4d495c6eSApple OSS Distributions 		test_task_self_movable_send, /* 17 */
652*4d495c6eSApple OSS Distributions 		test_move_newly_constructed_port_immovable_send, /* 18 */
653*4d495c6eSApple OSS Distributions 		test_move_special_reply_port, /* 19 */
654*4d495c6eSApple OSS Distributions 		test_reply_port_header_disposition, /* 20 */
655*4d495c6eSApple OSS Distributions 		test_service_port_as_exception_port, /* 21 */
656*4d495c6eSApple OSS Distributions 	};
657*4d495c6eSApple OSS Distributions 
658*4d495c6eSApple OSS Distributions 	if (argc < 2) {
659*4d495c6eSApple OSS Distributions 		printf("[reply_port_defense_client]: Specify a test to run.");
660*4d495c6eSApple OSS Distributions 		exit(-1);
661*4d495c6eSApple OSS Distributions 	}
662*4d495c6eSApple OSS Distributions 
663*4d495c6eSApple OSS Distributions 	int test_num = atoi(argv[1]);
664*4d495c6eSApple OSS Distributions 	printf("[reply_port_defense_client]: My Pid: %d Test num: %d third_party_hardened: %s\n",
665*4d495c6eSApple OSS Distributions 	    getpid(), test_num, thirdparty_hardened ? "yes" : "no");
666*4d495c6eSApple OSS Distributions 	fflush(stdout);
667*4d495c6eSApple OSS Distributions 	if (test_num >= 0 && test_num < MAX_TEST_NUM) {
668*4d495c6eSApple OSS Distributions 		(*tests[test_num])();
669*4d495c6eSApple OSS Distributions 	} else {
670*4d495c6eSApple OSS Distributions 		printf("[reply_port_defense_client]: Invalid test num. Exiting...\n");
671*4d495c6eSApple OSS Distributions 		exit(-1);
672*4d495c6eSApple OSS Distributions 	}
673*4d495c6eSApple OSS Distributions 	printf("Child exiting cleanly!!\n");
674*4d495c6eSApple OSS Distributions 	fflush(stdout);
675*4d495c6eSApple OSS Distributions 	// return 0;
676*4d495c6eSApple OSS Distributions 	exit(0);
677*4d495c6eSApple OSS Distributions }
678