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