xref: /xnu-10063.121.3/tests/imm_pinned_control_port_crasher.c (revision 2c2f96dc2b9a4408a43d3150ae9c105355ca3daa)
1*2c2f96dcSApple OSS Distributions #include <mach/mach.h>
2*2c2f96dcSApple OSS Distributions #include <stdlib.h>
3*2c2f96dcSApple OSS Distributions #include <pthread.h>
4*2c2f96dcSApple OSS Distributions #include <unistd.h>
5*2c2f96dcSApple OSS Distributions #include <stdio.h>
6*2c2f96dcSApple OSS Distributions #include <assert.h>
7*2c2f96dcSApple OSS Distributions #include <mach/task.h>
8*2c2f96dcSApple OSS Distributions #include <stdbool.h>
9*2c2f96dcSApple OSS Distributions #include <mach/mk_timer.h>
10*2c2f96dcSApple OSS Distributions #include "cs_helpers.h"
11*2c2f96dcSApple OSS Distributions 
12*2c2f96dcSApple OSS Distributions /*
13*2c2f96dcSApple OSS Distributions  * DO NOT run this test file by itself.
14*2c2f96dcSApple OSS Distributions  * This test is meant to be invoked by control_port_options darwintest.
15*2c2f96dcSApple OSS Distributions  *
16*2c2f96dcSApple OSS Distributions  * If hard enforcement for pinned control port is on, pinned tests are
17*2c2f96dcSApple OSS Distributions  * expected to generate fatal EXC_GUARD.
18*2c2f96dcSApple OSS Distributions  *
19*2c2f96dcSApple OSS Distributions  * If hard enforcement for immovable control port is on, immovable tests are
20*2c2f96dcSApple OSS Distributions  * expected to generate fatal EXC_GUARD.
21*2c2f96dcSApple OSS Distributions  *
22*2c2f96dcSApple OSS Distributions  * The type of exception raised (if any) is checked on control_port_options side.
23*2c2f96dcSApple OSS Distributions  */
24*2c2f96dcSApple OSS Distributions #define MAX_TEST_NUM 21
25*2c2f96dcSApple OSS Distributions 
26*2c2f96dcSApple OSS Distributions #ifndef MACH64_SEND_ANY
27*2c2f96dcSApple OSS Distributions #define MACH64_SEND_ANY 0x0000000800000000ull
28*2c2f96dcSApple OSS Distributions #define MACH64_SEND_MQ_CALL 0x0000000400000000ull
29*2c2f96dcSApple OSS Distributions #endif
30*2c2f96dcSApple OSS Distributions 
31*2c2f96dcSApple OSS Distributions static int
attempt_send_immovable_port(mach_port_name_t port,mach_msg_type_name_t disp)32*2c2f96dcSApple OSS Distributions attempt_send_immovable_port(mach_port_name_t port, mach_msg_type_name_t disp)
33*2c2f96dcSApple OSS Distributions {
34*2c2f96dcSApple OSS Distributions 	mach_port_t server;
35*2c2f96dcSApple OSS Distributions 	kern_return_t kr;
36*2c2f96dcSApple OSS Distributions 	kr = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &server);
37*2c2f96dcSApple OSS Distributions 	assert(kr == 0);
38*2c2f96dcSApple OSS Distributions 
39*2c2f96dcSApple OSS Distributions 	kr = mach_port_insert_right(mach_task_self(), server, server, MACH_MSG_TYPE_MAKE_SEND);
40*2c2f96dcSApple OSS Distributions 	assert(kr == 0);
41*2c2f96dcSApple OSS Distributions 
42*2c2f96dcSApple OSS Distributions 	struct {
43*2c2f96dcSApple OSS Distributions 		mach_msg_header_t header;
44*2c2f96dcSApple OSS Distributions 		mach_msg_body_t body;
45*2c2f96dcSApple OSS Distributions 		mach_msg_port_descriptor_t desc;
46*2c2f96dcSApple OSS Distributions 	} msg;
47*2c2f96dcSApple OSS Distributions 
48*2c2f96dcSApple OSS Distributions 	msg.header.msgh_remote_port = server;
49*2c2f96dcSApple OSS Distributions 	msg.header.msgh_local_port = MACH_PORT_NULL;
50*2c2f96dcSApple OSS Distributions 	msg.header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0) | MACH_MSGH_BITS_COMPLEX;
51*2c2f96dcSApple OSS Distributions 	msg.header.msgh_size = sizeof msg;
52*2c2f96dcSApple OSS Distributions 
53*2c2f96dcSApple OSS Distributions 	msg.body.msgh_descriptor_count = 1;
54*2c2f96dcSApple OSS Distributions 
55*2c2f96dcSApple OSS Distributions 	msg.desc.name = port;
56*2c2f96dcSApple OSS Distributions 	msg.desc.disposition = disp;
57*2c2f96dcSApple OSS Distributions 	msg.desc.type = MACH_MSG_PORT_DESCRIPTOR;
58*2c2f96dcSApple OSS Distributions 
59*2c2f96dcSApple OSS Distributions 	return mach_msg_send(&msg.header);
60*2c2f96dcSApple OSS Distributions }
61*2c2f96dcSApple OSS Distributions 
62*2c2f96dcSApple OSS Distributions static void
pinned_test_main_thread_mod_ref(void)63*2c2f96dcSApple OSS Distributions pinned_test_main_thread_mod_ref(void)
64*2c2f96dcSApple OSS Distributions {
65*2c2f96dcSApple OSS Distributions 	printf("[Crasher]: Mod refs main thread's self port to 0\n");
66*2c2f96dcSApple OSS Distributions 	mach_port_t thread_self = mach_thread_self();
67*2c2f96dcSApple OSS Distributions 	kern_return_t kr = mach_port_mod_refs(mach_task_self(), thread_self, MACH_PORT_RIGHT_SEND, -2);
68*2c2f96dcSApple OSS Distributions 
69*2c2f96dcSApple OSS Distributions 	printf("[Crasher pinned_test_main_thread_mod_ref] mach_port_mod_refs returned %s \n.", mach_error_string(kr));
70*2c2f96dcSApple OSS Distributions }
71*2c2f96dcSApple OSS Distributions 
72*2c2f96dcSApple OSS Distributions static void* _Nullable
pthread_run(void * _Nullable)73*2c2f96dcSApple OSS Distributions pthread_run(void *_Nullable)
74*2c2f96dcSApple OSS Distributions {
75*2c2f96dcSApple OSS Distributions 	printf("[Crasher]: Deallocate pthread_self\n");
76*2c2f96dcSApple OSS Distributions 	mach_port_t th_self = pthread_mach_thread_np(pthread_self());
77*2c2f96dcSApple OSS Distributions 	kern_return_t kr = mach_port_deallocate(mach_task_self(), th_self);
78*2c2f96dcSApple OSS Distributions 
79*2c2f96dcSApple OSS Distributions 	printf("[Crasher pinned_test_pthread_dealloc] mach_port_deallocate returned %s \n.", mach_error_string(kr));
80*2c2f96dcSApple OSS Distributions 	return NULL;
81*2c2f96dcSApple OSS Distributions }
82*2c2f96dcSApple OSS Distributions 
83*2c2f96dcSApple OSS Distributions static void
pinned_test_pthread_dealloc(void)84*2c2f96dcSApple OSS Distributions pinned_test_pthread_dealloc(void)
85*2c2f96dcSApple OSS Distributions {
86*2c2f96dcSApple OSS Distributions 	printf("[Crasher]: Create a pthread and deallocate its self port\n");
87*2c2f96dcSApple OSS Distributions 	pthread_t thread;
88*2c2f96dcSApple OSS Distributions 	int ret = pthread_create(&thread, NULL, pthread_run, NULL);
89*2c2f96dcSApple OSS Distributions 	assert(ret == 0);
90*2c2f96dcSApple OSS Distributions 	ret = pthread_join(thread, NULL);
91*2c2f96dcSApple OSS Distributions 	assert(ret == 0);
92*2c2f96dcSApple OSS Distributions }
93*2c2f96dcSApple OSS Distributions 
94*2c2f96dcSApple OSS Distributions static void
pinned_test_task_self_dealloc(void)95*2c2f96dcSApple OSS Distributions pinned_test_task_self_dealloc(void)
96*2c2f96dcSApple OSS Distributions {
97*2c2f96dcSApple OSS Distributions 	printf("[Crasher]: Deallocate mach_task_self twice\n");
98*2c2f96dcSApple OSS Distributions 	mach_port_t task_self = mach_task_self();
99*2c2f96dcSApple OSS Distributions 	kern_return_t kr = mach_port_deallocate(task_self, task_self);
100*2c2f96dcSApple OSS Distributions 	assert(kr == 0);
101*2c2f96dcSApple OSS Distributions 	kr = mach_port_deallocate(task_self, task_self);
102*2c2f96dcSApple OSS Distributions 
103*2c2f96dcSApple OSS Distributions 	printf("[Crasher pinned_test_task_self_dealloc] mach_port_deallocate returned %s \n.", mach_error_string(kr));
104*2c2f96dcSApple OSS Distributions }
105*2c2f96dcSApple OSS Distributions 
106*2c2f96dcSApple OSS Distributions static void
pinned_test_task_self_mod_ref(void)107*2c2f96dcSApple OSS Distributions pinned_test_task_self_mod_ref(void)
108*2c2f96dcSApple OSS Distributions {
109*2c2f96dcSApple OSS Distributions 	printf("[Crasher]: Mod refs mach_task_self() to 0\n");
110*2c2f96dcSApple OSS Distributions 	kern_return_t kr = mach_port_mod_refs(mach_task_self(), mach_task_self(), MACH_PORT_RIGHT_SEND, -2);
111*2c2f96dcSApple OSS Distributions 
112*2c2f96dcSApple OSS Distributions 	printf("[Crasher pinned_test_task_self_mod_ref] mach_port_mod_refs returned %s \n.", mach_error_string(kr));
113*2c2f96dcSApple OSS Distributions }
114*2c2f96dcSApple OSS Distributions 
115*2c2f96dcSApple OSS Distributions static void
pinned_test_task_threads_mod_ref(void)116*2c2f96dcSApple OSS Distributions pinned_test_task_threads_mod_ref(void)
117*2c2f96dcSApple OSS Distributions {
118*2c2f96dcSApple OSS Distributions 	printf("[Crasher]: task_threads should return pinned thread ports. Mod refs them to 0\n");
119*2c2f96dcSApple OSS Distributions 	thread_array_t th_list;
120*2c2f96dcSApple OSS Distributions 	mach_msg_type_number_t th_cnt;
121*2c2f96dcSApple OSS Distributions 	kern_return_t kr;
122*2c2f96dcSApple OSS Distributions 	mach_port_t th_kp = mach_thread_self();
123*2c2f96dcSApple OSS Distributions 	mach_port_deallocate(mach_task_self(), th_kp);
124*2c2f96dcSApple OSS Distributions 
125*2c2f96dcSApple OSS Distributions 	kr = task_threads(mach_task_self(), &th_list, &th_cnt);
126*2c2f96dcSApple OSS Distributions 	mach_port_deallocate(mach_task_self(), th_list[0]);
127*2c2f96dcSApple OSS Distributions 
128*2c2f96dcSApple OSS Distributions 	kr = mach_port_mod_refs(mach_task_self(), th_list[0], MACH_PORT_RIGHT_SEND, -1);
129*2c2f96dcSApple OSS Distributions 
130*2c2f96dcSApple OSS Distributions 	printf("[Crasher pinned_test_task_threads_mod_ref] mach_port_mod_refs returned %s \n.", mach_error_string(kr));
131*2c2f96dcSApple OSS Distributions }
132*2c2f96dcSApple OSS Distributions 
133*2c2f96dcSApple OSS Distributions static void
pinned_test_mach_port_destroy(void)134*2c2f96dcSApple OSS Distributions pinned_test_mach_port_destroy(void)
135*2c2f96dcSApple OSS Distributions {
136*2c2f96dcSApple OSS Distributions 	kern_return_t kr = mach_port_destroy(mach_task_self(), mach_task_self());
137*2c2f96dcSApple OSS Distributions 	printf("[Crasher pinned_test_mach_port_destroy] mach_port_destroy returned %s \n.", mach_error_string(kr));
138*2c2f96dcSApple OSS Distributions }
139*2c2f96dcSApple OSS Distributions 
140*2c2f96dcSApple OSS Distributions static void
pinned_test_move_send_as_remote_port(void)141*2c2f96dcSApple OSS Distributions pinned_test_move_send_as_remote_port(void)
142*2c2f96dcSApple OSS Distributions {
143*2c2f96dcSApple OSS Distributions 	struct {
144*2c2f96dcSApple OSS Distributions 		mach_msg_header_t header;
145*2c2f96dcSApple OSS Distributions 	} msg;
146*2c2f96dcSApple OSS Distributions 
147*2c2f96dcSApple OSS Distributions 	kern_return_t kr = mach_port_deallocate(mach_task_self(), mach_task_self());
148*2c2f96dcSApple OSS Distributions 	assert(kr == 0);
149*2c2f96dcSApple OSS Distributions 
150*2c2f96dcSApple OSS Distributions 	/*
151*2c2f96dcSApple OSS Distributions 	 * We allow move send on remote kobject port but this should trip on pinning on last ref.
152*2c2f96dcSApple OSS Distributions 	 * See: IPC_OBJECT_COPYIN_FLAGS_ALLOW_IMMOVABLE_SEND.
153*2c2f96dcSApple OSS Distributions 	 */
154*2c2f96dcSApple OSS Distributions 	msg.header.msgh_remote_port = mach_task_self();
155*2c2f96dcSApple OSS Distributions 	msg.header.msgh_local_port = MACH_PORT_NULL;
156*2c2f96dcSApple OSS Distributions 	msg.header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MOVE_SEND, 0);
157*2c2f96dcSApple OSS Distributions 	msg.header.msgh_id = 2000;
158*2c2f96dcSApple OSS Distributions 	msg.header.msgh_size = sizeof msg;
159*2c2f96dcSApple OSS Distributions 
160*2c2f96dcSApple OSS Distributions 	kr = mach_msg_send(&msg.header);
161*2c2f96dcSApple OSS Distributions 
162*2c2f96dcSApple OSS Distributions 	printf("[Crasher pinned_test_move_send_as_remote_port] mach_msg_send returned %s \n.", mach_error_string(kr));
163*2c2f96dcSApple OSS Distributions }
164*2c2f96dcSApple OSS Distributions 
165*2c2f96dcSApple OSS Distributions static void
immovable_test_move_send_as_remote_port(void)166*2c2f96dcSApple OSS Distributions immovable_test_move_send_as_remote_port(void)
167*2c2f96dcSApple OSS Distributions {
168*2c2f96dcSApple OSS Distributions 	struct {
169*2c2f96dcSApple OSS Distributions 		mach_msg_header_t header;
170*2c2f96dcSApple OSS Distributions 	} msg;
171*2c2f96dcSApple OSS Distributions 
172*2c2f96dcSApple OSS Distributions 	/* Local port cannot be immovable. See: ipc_right_copyin_check_reply() */
173*2c2f96dcSApple OSS Distributions 	msg.header.msgh_remote_port = mach_task_self();
174*2c2f96dcSApple OSS Distributions 	msg.header.msgh_local_port = mach_task_self();
175*2c2f96dcSApple OSS Distributions 	msg.header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MOVE_SEND, MACH_MSG_TYPE_MOVE_SEND);
176*2c2f96dcSApple OSS Distributions 	msg.header.msgh_id = 2000;
177*2c2f96dcSApple OSS Distributions 	msg.header.msgh_size = sizeof msg;
178*2c2f96dcSApple OSS Distributions 
179*2c2f96dcSApple OSS Distributions 	kern_return_t kr = mach_msg_send(&msg.header);
180*2c2f96dcSApple OSS Distributions 
181*2c2f96dcSApple OSS Distributions 	printf("[Crasher immovable_test_move_send_as_remote_port] mach_msg_send returned %s \n.", mach_error_string(kr));
182*2c2f96dcSApple OSS Distributions }
183*2c2f96dcSApple OSS Distributions 
184*2c2f96dcSApple OSS Distributions static void
immovable_test_move_send_task_self(void)185*2c2f96dcSApple OSS Distributions immovable_test_move_send_task_self(void)
186*2c2f96dcSApple OSS Distributions {
187*2c2f96dcSApple OSS Distributions 	kern_return_t kr;
188*2c2f96dcSApple OSS Distributions 	printf("[Crasher]: Move send mach_task_self_\n");
189*2c2f96dcSApple OSS Distributions 	kr = attempt_send_immovable_port(mach_task_self(), MACH_MSG_TYPE_MOVE_SEND);
190*2c2f96dcSApple OSS Distributions 
191*2c2f96dcSApple OSS Distributions 	printf("[Crasher immovable_test_move_send_task_self] attempt_send_immovable_port returned %s \n.", mach_error_string(kr));
192*2c2f96dcSApple OSS Distributions }
193*2c2f96dcSApple OSS Distributions 
194*2c2f96dcSApple OSS Distributions static void
immovable_test_copy_send_task_self(void)195*2c2f96dcSApple OSS Distributions immovable_test_copy_send_task_self(void)
196*2c2f96dcSApple OSS Distributions {
197*2c2f96dcSApple OSS Distributions 	kern_return_t kr;
198*2c2f96dcSApple OSS Distributions 	printf("[Crasher]: Copy send mach_task_self_\n");
199*2c2f96dcSApple OSS Distributions 	kr = attempt_send_immovable_port(mach_task_self(), MACH_MSG_TYPE_COPY_SEND);
200*2c2f96dcSApple OSS Distributions 
201*2c2f96dcSApple OSS Distributions 	printf("[Crasher immovable_test_copy_send_task_self] attempt_send_immovable_port returned %s \n.", mach_error_string(kr));
202*2c2f96dcSApple OSS Distributions }
203*2c2f96dcSApple OSS Distributions 
204*2c2f96dcSApple OSS Distributions static void
immovable_test_move_send_thread_self(void)205*2c2f96dcSApple OSS Distributions immovable_test_move_send_thread_self(void)
206*2c2f96dcSApple OSS Distributions {
207*2c2f96dcSApple OSS Distributions 	kern_return_t kr;
208*2c2f96dcSApple OSS Distributions 	printf("[Crasher]: Move send main thread's self port\n");
209*2c2f96dcSApple OSS Distributions 	kr = attempt_send_immovable_port(mach_thread_self(), MACH_MSG_TYPE_MOVE_SEND);
210*2c2f96dcSApple OSS Distributions 
211*2c2f96dcSApple OSS Distributions 	printf("[Crasher immovable_test_move_send_thread_self] attempt_send_immovable_port returned %s \n.", mach_error_string(kr));
212*2c2f96dcSApple OSS Distributions }
213*2c2f96dcSApple OSS Distributions 
214*2c2f96dcSApple OSS Distributions static void
immovable_test_copy_send_thread_self(void)215*2c2f96dcSApple OSS Distributions immovable_test_copy_send_thread_self(void)
216*2c2f96dcSApple OSS Distributions {
217*2c2f96dcSApple OSS Distributions 	kern_return_t kr;
218*2c2f96dcSApple OSS Distributions 	mach_port_t port;
219*2c2f96dcSApple OSS Distributions 	printf("[Crasher]: Copy send main thread's self port\n");
220*2c2f96dcSApple OSS Distributions 	port = mach_thread_self();
221*2c2f96dcSApple OSS Distributions 	kr = attempt_send_immovable_port(port, MACH_MSG_TYPE_COPY_SEND);
222*2c2f96dcSApple OSS Distributions 	printf("[Crasher immovable_test_copy_send_thread_self] attempt_send_immovable_port returned %s \n.", mach_error_string(kr));
223*2c2f96dcSApple OSS Distributions 
224*2c2f96dcSApple OSS Distributions 	mach_port_deallocate(mach_task_self(), port);
225*2c2f96dcSApple OSS Distributions }
226*2c2f96dcSApple OSS Distributions 
227*2c2f96dcSApple OSS Distributions static void
immovable_test_copy_send_task_read(void)228*2c2f96dcSApple OSS Distributions immovable_test_copy_send_task_read(void)
229*2c2f96dcSApple OSS Distributions {
230*2c2f96dcSApple OSS Distributions 	kern_return_t kr;
231*2c2f96dcSApple OSS Distributions 	mach_port_t port;
232*2c2f96dcSApple OSS Distributions 	printf("[Crasher]: Copy send task read port\n");
233*2c2f96dcSApple OSS Distributions 	kr = task_get_special_port(mach_task_self(), TASK_READ_PORT, &port);
234*2c2f96dcSApple OSS Distributions 	assert(kr == 0);
235*2c2f96dcSApple OSS Distributions 	kr = attempt_send_immovable_port(port, MACH_MSG_TYPE_COPY_SEND);
236*2c2f96dcSApple OSS Distributions 	printf("[Crasher immovable_test_copy_send_task_read] attempt_send_immovable_port returned %s \n.", mach_error_string(kr));
237*2c2f96dcSApple OSS Distributions 
238*2c2f96dcSApple OSS Distributions 	mach_port_deallocate(mach_task_self(), port);
239*2c2f96dcSApple OSS Distributions }
240*2c2f96dcSApple OSS Distributions 
241*2c2f96dcSApple OSS Distributions static void
immovable_test_copy_send_task_inspect(void)242*2c2f96dcSApple OSS Distributions immovable_test_copy_send_task_inspect(void)
243*2c2f96dcSApple OSS Distributions {
244*2c2f96dcSApple OSS Distributions 	kern_return_t kr;
245*2c2f96dcSApple OSS Distributions 	mach_port_t port;
246*2c2f96dcSApple OSS Distributions 	printf("[Crasher]: Move send task inspect port\n");
247*2c2f96dcSApple OSS Distributions 	kr = task_get_special_port(mach_task_self(), TASK_INSPECT_PORT, &port);
248*2c2f96dcSApple OSS Distributions 	assert(kr == 0);
249*2c2f96dcSApple OSS Distributions 	kr = attempt_send_immovable_port(port, MACH_MSG_TYPE_MOVE_SEND);
250*2c2f96dcSApple OSS Distributions 	printf("[Crasher immovable_test_copy_send_task_inspect] attempt_send_immovable_port returned %s \n.", mach_error_string(kr));
251*2c2f96dcSApple OSS Distributions }
252*2c2f96dcSApple OSS Distributions 
253*2c2f96dcSApple OSS Distributions static void
immovable_test_move_send_thread_inspect(void)254*2c2f96dcSApple OSS Distributions immovable_test_move_send_thread_inspect(void)
255*2c2f96dcSApple OSS Distributions {
256*2c2f96dcSApple OSS Distributions 	kern_return_t kr;
257*2c2f96dcSApple OSS Distributions 	mach_port_t port;
258*2c2f96dcSApple OSS Distributions 	mach_port_t th_port = mach_thread_self();
259*2c2f96dcSApple OSS Distributions 
260*2c2f96dcSApple OSS Distributions 	printf("[Crasher]: Move send thread inspect port\n");
261*2c2f96dcSApple OSS Distributions 	kr = thread_get_special_port(th_port, THREAD_INSPECT_PORT, &port);
262*2c2f96dcSApple OSS Distributions 	assert(kr == 0);
263*2c2f96dcSApple OSS Distributions 	kr = attempt_send_immovable_port(port, MACH_MSG_TYPE_MOVE_SEND);
264*2c2f96dcSApple OSS Distributions 	printf("[Crasher immovable_test_move_send_thread_inspect] attempt_send_immovable_port returned %s \n.", mach_error_string(kr));
265*2c2f96dcSApple OSS Distributions 
266*2c2f96dcSApple OSS Distributions 	mach_port_deallocate(mach_task_self(), th_port);
267*2c2f96dcSApple OSS Distributions }
268*2c2f96dcSApple OSS Distributions 
269*2c2f96dcSApple OSS Distributions static void
immovable_test_move_send_raw_thread(void)270*2c2f96dcSApple OSS Distributions immovable_test_move_send_raw_thread(void)
271*2c2f96dcSApple OSS Distributions {
272*2c2f96dcSApple OSS Distributions 	kern_return_t kr;
273*2c2f96dcSApple OSS Distributions 	mach_port_t port;
274*2c2f96dcSApple OSS Distributions 
275*2c2f96dcSApple OSS Distributions 	kr = thread_create(mach_task_self(), &port);
276*2c2f96dcSApple OSS Distributions 	assert(kr == 0);
277*2c2f96dcSApple OSS Distributions 	kr = mach_port_deallocate(mach_task_self(), port); /* not pinned, should not crash */
278*2c2f96dcSApple OSS Distributions 
279*2c2f96dcSApple OSS Distributions 	kr = thread_create(mach_task_self(), &port);
280*2c2f96dcSApple OSS Distributions 	assert(kr == 0);
281*2c2f96dcSApple OSS Distributions 	kr = attempt_send_immovable_port(port, MACH_MSG_TYPE_MOVE_SEND); /* immovable, should crash here */
282*2c2f96dcSApple OSS Distributions 	printf("[Crasher immovable_test_move_send_raw_thread] attempt_send_immovable_port returned %s \n.", mach_error_string(kr));
283*2c2f96dcSApple OSS Distributions 
284*2c2f96dcSApple OSS Distributions 	kr = thread_terminate(port);
285*2c2f96dcSApple OSS Distributions 	assert(kr == 0);
286*2c2f96dcSApple OSS Distributions }
287*2c2f96dcSApple OSS Distributions 
288*2c2f96dcSApple OSS Distributions static void
immovable_test_copy_send_thread_read(void)289*2c2f96dcSApple OSS Distributions immovable_test_copy_send_thread_read(void)
290*2c2f96dcSApple OSS Distributions {
291*2c2f96dcSApple OSS Distributions 	kern_return_t kr;
292*2c2f96dcSApple OSS Distributions 	mach_port_t port;
293*2c2f96dcSApple OSS Distributions 	mach_port_t th_port = mach_thread_self();
294*2c2f96dcSApple OSS Distributions 
295*2c2f96dcSApple OSS Distributions 	printf("[Crasher]: Copy send thread read port\n");
296*2c2f96dcSApple OSS Distributions 	kr = thread_get_special_port(th_port, THREAD_READ_PORT, &port);
297*2c2f96dcSApple OSS Distributions 	assert(kr == 0);
298*2c2f96dcSApple OSS Distributions 	kr = attempt_send_immovable_port(port, MACH_MSG_TYPE_COPY_SEND);
299*2c2f96dcSApple OSS Distributions 	printf("[Crasher immovable_test_copy_send_thread_read] attempt_send_immovable_port returned %s \n.", mach_error_string(kr));
300*2c2f96dcSApple OSS Distributions 
301*2c2f96dcSApple OSS Distributions 	mach_port_deallocate(mach_task_self(), port);
302*2c2f96dcSApple OSS Distributions 	mach_port_deallocate(mach_task_self(), th_port);
303*2c2f96dcSApple OSS Distributions }
304*2c2f96dcSApple OSS Distributions 
305*2c2f96dcSApple OSS Distributions static void
cfi_test_no_bit_set(void)306*2c2f96dcSApple OSS Distributions cfi_test_no_bit_set(void)
307*2c2f96dcSApple OSS Distributions {
308*2c2f96dcSApple OSS Distributions 	printf("[Crasher]: Try sending mach_msg2() without setting CFI bits\n");
309*2c2f96dcSApple OSS Distributions 
310*2c2f96dcSApple OSS Distributions 	mach_msg_header_t header;
311*2c2f96dcSApple OSS Distributions 	kern_return_t kr;
312*2c2f96dcSApple OSS Distributions 
313*2c2f96dcSApple OSS Distributions 	header.msgh_local_port = MACH_PORT_NULL;
314*2c2f96dcSApple OSS Distributions 	header.msgh_remote_port = mach_task_self();
315*2c2f96dcSApple OSS Distributions 	header.msgh_id = 3409;
316*2c2f96dcSApple OSS Distributions 	header.msgh_bits = MACH_MSGH_BITS_SET(MACH_MSG_TYPE_COPY_SEND, 0, 0, 0);
317*2c2f96dcSApple OSS Distributions 	header.msgh_size = sizeof(header);
318*2c2f96dcSApple OSS Distributions 
319*2c2f96dcSApple OSS Distributions 	kr = mach_msg2(&header, MACH64_SEND_MSG, header, header.msgh_size, 0, MACH_PORT_NULL,
320*2c2f96dcSApple OSS Distributions 	    0, MACH_MSG_PRIORITY_UNSPECIFIED);
321*2c2f96dcSApple OSS Distributions 	/* crash */
322*2c2f96dcSApple OSS Distributions 	printf("[Crasher cfi_test_no_bit_set]: mach_msg2() returned %d\n", kr);
323*2c2f96dcSApple OSS Distributions }
324*2c2f96dcSApple OSS Distributions 
325*2c2f96dcSApple OSS Distributions static void
cfi_test_two_bits_set(void)326*2c2f96dcSApple OSS Distributions cfi_test_two_bits_set(void)
327*2c2f96dcSApple OSS Distributions {
328*2c2f96dcSApple OSS Distributions 	printf("[Crasher]: Try sending mach_msg2() but setting 2 CFI bits\n");
329*2c2f96dcSApple OSS Distributions 
330*2c2f96dcSApple OSS Distributions 	mach_msg_header_t header;
331*2c2f96dcSApple OSS Distributions 	kern_return_t kr;
332*2c2f96dcSApple OSS Distributions 
333*2c2f96dcSApple OSS Distributions 	header.msgh_local_port = MACH_PORT_NULL;
334*2c2f96dcSApple OSS Distributions 	header.msgh_remote_port = mach_task_self();
335*2c2f96dcSApple OSS Distributions 	header.msgh_id = 3409;
336*2c2f96dcSApple OSS Distributions 	header.msgh_bits = MACH_MSGH_BITS_SET(MACH_MSG_TYPE_COPY_SEND, 0, 0, 0);
337*2c2f96dcSApple OSS Distributions 	header.msgh_size = sizeof(header);
338*2c2f96dcSApple OSS Distributions 
339*2c2f96dcSApple OSS Distributions 	kr = mach_msg2(&header, MACH64_SEND_MSG | MACH64_SEND_ANY | MACH64_SEND_KOBJECT_CALL,
340*2c2f96dcSApple OSS Distributions 	    header, header.msgh_size, 0, MACH_PORT_NULL,
341*2c2f96dcSApple OSS Distributions 	    0, MACH_MSG_PRIORITY_UNSPECIFIED);
342*2c2f96dcSApple OSS Distributions 	/* crash */
343*2c2f96dcSApple OSS Distributions 	printf("[Crasher cfi_test_two_bits_set]: mach_msg2() returned %d\n", kr);
344*2c2f96dcSApple OSS Distributions }
345*2c2f96dcSApple OSS Distributions 
346*2c2f96dcSApple OSS Distributions static void
cfi_test_msg_to_timer_port(void)347*2c2f96dcSApple OSS Distributions cfi_test_msg_to_timer_port(void)
348*2c2f96dcSApple OSS Distributions {
349*2c2f96dcSApple OSS Distributions 	printf("[Crasher]: Try sending mach_msg2() to timer port\n");
350*2c2f96dcSApple OSS Distributions 
351*2c2f96dcSApple OSS Distributions 	mach_port_t timer = MACH_PORT_NULL;
352*2c2f96dcSApple OSS Distributions 	struct oversize_msg {
353*2c2f96dcSApple OSS Distributions 		mach_msg_header_t header;
354*2c2f96dcSApple OSS Distributions 		char data[2048];
355*2c2f96dcSApple OSS Distributions 	} msg;
356*2c2f96dcSApple OSS Distributions 
357*2c2f96dcSApple OSS Distributions 	kern_return_t kr;
358*2c2f96dcSApple OSS Distributions 	natural_t kotype;
359*2c2f96dcSApple OSS Distributions 	mach_vm_address_t addr;
360*2c2f96dcSApple OSS Distributions 
361*2c2f96dcSApple OSS Distributions #define IKOT_TIMER 8
362*2c2f96dcSApple OSS Distributions 	timer = mk_timer_create();
363*2c2f96dcSApple OSS Distributions 	assert(timer != MACH_PORT_NULL);
364*2c2f96dcSApple OSS Distributions 
365*2c2f96dcSApple OSS Distributions 	/* Make sure it's a kobject port */
366*2c2f96dcSApple OSS Distributions 	kr = mach_port_kobject(mach_task_self(), timer, &kotype, &addr);
367*2c2f96dcSApple OSS Distributions 	assert(kr == KERN_SUCCESS);
368*2c2f96dcSApple OSS Distributions 	assert(kotype == IKOT_TIMER);
369*2c2f96dcSApple OSS Distributions 
370*2c2f96dcSApple OSS Distributions 	msg.header.msgh_local_port = MACH_PORT_NULL;
371*2c2f96dcSApple OSS Distributions 	msg.header.msgh_remote_port = timer;
372*2c2f96dcSApple OSS Distributions 	msg.header.msgh_bits = MACH_MSGH_BITS_SET(MACH_MSG_TYPE_MAKE_SEND, 0, 0, 0);
373*2c2f96dcSApple OSS Distributions 	msg.header.msgh_size = sizeof(msg);
374*2c2f96dcSApple OSS Distributions 
375*2c2f96dcSApple OSS Distributions 	/* Timer port must use MACH64_SEND_MQ_CALL */
376*2c2f96dcSApple OSS Distributions 	kr = mach_msg2(&msg, MACH64_SEND_MSG | MACH64_SEND_MQ_CALL,
377*2c2f96dcSApple OSS Distributions 	    msg.header, msg.header.msgh_size, 0, MACH_PORT_NULL,
378*2c2f96dcSApple OSS Distributions 	    0, MACH_MSG_PRIORITY_UNSPECIFIED);
379*2c2f96dcSApple OSS Distributions 	assert(kr == KERN_SUCCESS);
380*2c2f96dcSApple OSS Distributions 	printf("Message sent to timer port successfully\n");
381*2c2f96dcSApple OSS Distributions 
382*2c2f96dcSApple OSS Distributions 	/* Using MACH64_SEND_KOBJECT_CALL should crash */
383*2c2f96dcSApple OSS Distributions 	kr = mach_msg2(&msg, MACH64_SEND_MSG | MACH64_SEND_KOBJECT_CALL,
384*2c2f96dcSApple OSS Distributions 	    msg.header, msg.header.msgh_size, 0, MACH_PORT_NULL,
385*2c2f96dcSApple OSS Distributions 	    0, MACH_MSG_PRIORITY_UNSPECIFIED);
386*2c2f96dcSApple OSS Distributions 	/* crash */
387*2c2f96dcSApple OSS Distributions 	printf("[Crasher cfi_test_timer_port]: mach_msg2() returned %d\n", kr);
388*2c2f96dcSApple OSS Distributions }
389*2c2f96dcSApple OSS Distributions 
390*2c2f96dcSApple OSS Distributions static void
cfi_test_wrong_bit_set(void)391*2c2f96dcSApple OSS Distributions cfi_test_wrong_bit_set(void)
392*2c2f96dcSApple OSS Distributions {
393*2c2f96dcSApple OSS Distributions 	printf("[Crasher]: Try sending mach_msg2() but setting wrong CFI bits\n");
394*2c2f96dcSApple OSS Distributions 
395*2c2f96dcSApple OSS Distributions 	mach_msg_header_t header;
396*2c2f96dcSApple OSS Distributions 	kern_return_t kr;
397*2c2f96dcSApple OSS Distributions 
398*2c2f96dcSApple OSS Distributions 	header.msgh_local_port = MACH_PORT_NULL;
399*2c2f96dcSApple OSS Distributions 	header.msgh_remote_port = mach_task_self();
400*2c2f96dcSApple OSS Distributions 	header.msgh_id = 3409;
401*2c2f96dcSApple OSS Distributions 	header.msgh_bits = MACH_MSGH_BITS_SET(MACH_MSG_TYPE_COPY_SEND, 0, 0, 0);
402*2c2f96dcSApple OSS Distributions 	header.msgh_size = sizeof(header);
403*2c2f96dcSApple OSS Distributions 
404*2c2f96dcSApple OSS Distributions 	/* Using MACH64_SEND_MQ_CALL but destination is a kobject port */
405*2c2f96dcSApple OSS Distributions 	kr = mach_msg2(&header, MACH64_SEND_MSG | MACH64_SEND_MQ_CALL,
406*2c2f96dcSApple OSS Distributions 	    header, header.msgh_size, 0, MACH_PORT_NULL,
407*2c2f96dcSApple OSS Distributions 	    0, MACH_MSG_PRIORITY_UNSPECIFIED);
408*2c2f96dcSApple OSS Distributions 	/* crash */
409*2c2f96dcSApple OSS Distributions 	printf("[Crasher cfi_test_wrong_bit_set]: mach_msg2() returned %d\n", kr);
410*2c2f96dcSApple OSS Distributions }
411*2c2f96dcSApple OSS Distributions 
412*2c2f96dcSApple OSS Distributions int
main(int argc,char * argv[])413*2c2f96dcSApple OSS Distributions main(int argc, char *argv[])
414*2c2f96dcSApple OSS Distributions {
415*2c2f96dcSApple OSS Distributions 	void (*tests[MAX_TEST_NUM])(void) = {
416*2c2f96dcSApple OSS Distributions 		pinned_test_main_thread_mod_ref,
417*2c2f96dcSApple OSS Distributions 		pinned_test_pthread_dealloc,
418*2c2f96dcSApple OSS Distributions 		pinned_test_task_self_dealloc,
419*2c2f96dcSApple OSS Distributions 		pinned_test_task_self_mod_ref,
420*2c2f96dcSApple OSS Distributions 		pinned_test_task_threads_mod_ref,
421*2c2f96dcSApple OSS Distributions 		pinned_test_mach_port_destroy,
422*2c2f96dcSApple OSS Distributions 		pinned_test_move_send_as_remote_port,
423*2c2f96dcSApple OSS Distributions 
424*2c2f96dcSApple OSS Distributions 		immovable_test_move_send_task_self,
425*2c2f96dcSApple OSS Distributions 		immovable_test_copy_send_task_self,
426*2c2f96dcSApple OSS Distributions 		immovable_test_move_send_thread_self,
427*2c2f96dcSApple OSS Distributions 		immovable_test_copy_send_thread_self,
428*2c2f96dcSApple OSS Distributions 		immovable_test_copy_send_task_read,
429*2c2f96dcSApple OSS Distributions 		immovable_test_copy_send_task_inspect,
430*2c2f96dcSApple OSS Distributions 		immovable_test_move_send_thread_inspect,
431*2c2f96dcSApple OSS Distributions 		immovable_test_copy_send_thread_read,
432*2c2f96dcSApple OSS Distributions 		immovable_test_move_send_as_remote_port,
433*2c2f96dcSApple OSS Distributions 		immovable_test_move_send_raw_thread,
434*2c2f96dcSApple OSS Distributions 
435*2c2f96dcSApple OSS Distributions 		cfi_test_no_bit_set,
436*2c2f96dcSApple OSS Distributions 		cfi_test_two_bits_set,
437*2c2f96dcSApple OSS Distributions 		cfi_test_wrong_bit_set,
438*2c2f96dcSApple OSS Distributions 		cfi_test_msg_to_timer_port,
439*2c2f96dcSApple OSS Distributions 	};
440*2c2f96dcSApple OSS Distributions 	printf("[Crasher]: My Pid: %d\n", getpid());
441*2c2f96dcSApple OSS Distributions 
442*2c2f96dcSApple OSS Distributions 	if (argc < 2) {
443*2c2f96dcSApple OSS Distributions 		printf("[Crasher]: Specify a test to run.");
444*2c2f96dcSApple OSS Distributions 		exit(-1);
445*2c2f96dcSApple OSS Distributions 	}
446*2c2f96dcSApple OSS Distributions 
447*2c2f96dcSApple OSS Distributions 	bool third_party_hardened = !strcmp(argv[0], "imm_pinned_control_port_crasher_3P_hardened");
448*2c2f96dcSApple OSS Distributions 	if (third_party_hardened) {
449*2c2f96dcSApple OSS Distributions 		// Ensure that we can set this crasher as a non-platform binary
450*2c2f96dcSApple OSS Distributions 		if (remove_platform_binary() != 0) {
451*2c2f96dcSApple OSS Distributions 			printf("Failed to remove platform binary, exiting\n");
452*2c2f96dcSApple OSS Distributions 			exit(1);
453*2c2f96dcSApple OSS Distributions 		}
454*2c2f96dcSApple OSS Distributions 	}
455*2c2f96dcSApple OSS Distributions 
456*2c2f96dcSApple OSS Distributions 	int test_num = atoi(argv[1]);
457*2c2f96dcSApple OSS Distributions 
458*2c2f96dcSApple OSS Distributions 
459*2c2f96dcSApple OSS Distributions 	if (test_num >= 0 && test_num < MAX_TEST_NUM) {
460*2c2f96dcSApple OSS Distributions 		printf("[Crasher]: Running test num %d\n", test_num);
461*2c2f96dcSApple OSS Distributions 		(*tests[test_num])();
462*2c2f96dcSApple OSS Distributions 	} else {
463*2c2f96dcSApple OSS Distributions 		printf("[Crasher]: Invalid test num: %d. Exiting...\n", test_num);
464*2c2f96dcSApple OSS Distributions 		exit(-1);
465*2c2f96dcSApple OSS Distributions 	}
466*2c2f96dcSApple OSS Distributions 
467*2c2f96dcSApple OSS Distributions 	exit(0);
468*2c2f96dcSApple OSS Distributions }
469