xref: /xnu-11215.61.5/tests/mach_exception_reply.c (revision 4f1223e81cd707a65cc109d0b8ad6653699da3c4)
1*4f1223e8SApple OSS Distributions #include <darwintest.h>
2*4f1223e8SApple OSS Distributions 
3*4f1223e8SApple OSS Distributions #include <pthread.h>
4*4f1223e8SApple OSS Distributions #include <setjmp.h>
5*4f1223e8SApple OSS Distributions #include <signal.h>
6*4f1223e8SApple OSS Distributions #include <stdlib.h>
7*4f1223e8SApple OSS Distributions #include <unistd.h>
8*4f1223e8SApple OSS Distributions #include <mach/mach.h>
9*4f1223e8SApple OSS Distributions #include <pthread/qos_private.h>
10*4f1223e8SApple OSS Distributions #include <mach/mach_voucher.h>
11*4f1223e8SApple OSS Distributions #include <bank/bank_types.h>
12*4f1223e8SApple OSS Distributions 
13*4f1223e8SApple OSS Distributions T_GLOBAL_META(T_META_RUN_CONCURRENTLY(true),
14*4f1223e8SApple OSS Distributions     T_META_NAMESPACE("xnu.ipc"),
15*4f1223e8SApple OSS Distributions     T_META_RADAR_COMPONENT_NAME("xnu"),
16*4f1223e8SApple OSS Distributions     T_META_RADAR_COMPONENT_VERSION("IPC"));
17*4f1223e8SApple OSS Distributions 
18*4f1223e8SApple OSS Distributions #define MSG      1024
19*4f1223e8SApple OSS Distributions #define PG_ALLOC 4096
20*4f1223e8SApple OSS Distributions 
21*4f1223e8SApple OSS Distributions typedef enum {
22*4f1223e8SApple OSS Distributions 	ReplyWithNoError,
23*4f1223e8SApple OSS Distributions 	ReplyWithReplyPort,
24*4f1223e8SApple OSS Distributions 	ReplyWithReplyPortMove,
25*4f1223e8SApple OSS Distributions 	ReplyWithReplyPortCplxBit,
26*4f1223e8SApple OSS Distributions 	ReplyWithReplyPortMoveCplxBit,
27*4f1223e8SApple OSS Distributions 	ReplyWithPortDesc,
28*4f1223e8SApple OSS Distributions 	ReplyWithOOLDesc,
29*4f1223e8SApple OSS Distributions 	ReplyWithVoucher,
30*4f1223e8SApple OSS Distributions 	ReplyWithVoucherGarbage
31*4f1223e8SApple OSS Distributions } ReplyType;
32*4f1223e8SApple OSS Distributions 
33*4f1223e8SApple OSS Distributions struct exc_thread_arg {
34*4f1223e8SApple OSS Distributions 	ReplyType    rt;
35*4f1223e8SApple OSS Distributions 	mach_port_t  port;
36*4f1223e8SApple OSS Distributions };
37*4f1223e8SApple OSS Distributions 
38*4f1223e8SApple OSS Distributions static const char *
reply_type_str(ReplyType rt)39*4f1223e8SApple OSS Distributions reply_type_str(ReplyType rt)
40*4f1223e8SApple OSS Distributions {
41*4f1223e8SApple OSS Distributions 	switch (rt) {
42*4f1223e8SApple OSS Distributions 	case ReplyWithNoError:
43*4f1223e8SApple OSS Distributions 		return "ReplyWithNoError";
44*4f1223e8SApple OSS Distributions 	case ReplyWithReplyPort:
45*4f1223e8SApple OSS Distributions 		return "ReplyWithReplyPort";
46*4f1223e8SApple OSS Distributions 	case ReplyWithReplyPortMove:
47*4f1223e8SApple OSS Distributions 		return "ReplyWithReplyPortMove";
48*4f1223e8SApple OSS Distributions 	case ReplyWithReplyPortCplxBit:
49*4f1223e8SApple OSS Distributions 		return "ReplyWithReplyPortCplxBit";
50*4f1223e8SApple OSS Distributions 	case ReplyWithReplyPortMoveCplxBit:
51*4f1223e8SApple OSS Distributions 		return "ReplyWithReplyPortMoveCplxBit";
52*4f1223e8SApple OSS Distributions 	case ReplyWithPortDesc:
53*4f1223e8SApple OSS Distributions 		return "ReplyWithPortDesc";
54*4f1223e8SApple OSS Distributions 	case ReplyWithOOLDesc:
55*4f1223e8SApple OSS Distributions 		return "ReplyWithOOLDesc";
56*4f1223e8SApple OSS Distributions 	case ReplyWithVoucher:
57*4f1223e8SApple OSS Distributions 		return "ReplyWithVoucher";
58*4f1223e8SApple OSS Distributions 	case ReplyWithVoucherGarbage:
59*4f1223e8SApple OSS Distributions 		return "ReplyWithVoucherGarbage";
60*4f1223e8SApple OSS Distributions 	}
61*4f1223e8SApple OSS Distributions }
62*4f1223e8SApple OSS Distributions 
63*4f1223e8SApple OSS Distributions static mach_voucher_t
create_task_voucher(void)64*4f1223e8SApple OSS Distributions create_task_voucher(void)
65*4f1223e8SApple OSS Distributions {
66*4f1223e8SApple OSS Distributions 	static mach_voucher_attr_recipe_data_t task_create_recipe = {
67*4f1223e8SApple OSS Distributions 		.key = MACH_VOUCHER_ATTR_KEY_BANK,
68*4f1223e8SApple OSS Distributions 		.command = MACH_VOUCHER_ATTR_BANK_CREATE,
69*4f1223e8SApple OSS Distributions 	};
70*4f1223e8SApple OSS Distributions 	mach_voucher_t voucher = MACH_PORT_NULL;
71*4f1223e8SApple OSS Distributions 	kern_return_t kr;
72*4f1223e8SApple OSS Distributions 
73*4f1223e8SApple OSS Distributions 	kr = host_create_mach_voucher(mach_host_self(),
74*4f1223e8SApple OSS Distributions 	    (mach_voucher_attr_raw_recipe_array_t)&task_create_recipe,
75*4f1223e8SApple OSS Distributions 	    sizeof(task_create_recipe),
76*4f1223e8SApple OSS Distributions 	    &voucher);
77*4f1223e8SApple OSS Distributions 
78*4f1223e8SApple OSS Distributions 	T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "host_create_mach_voucher");
79*4f1223e8SApple OSS Distributions 	return voucher;
80*4f1223e8SApple OSS Distributions }
81*4f1223e8SApple OSS Distributions 
82*4f1223e8SApple OSS Distributions static void *
handle_exceptions(void * arg)83*4f1223e8SApple OSS Distributions handle_exceptions(void *arg)
84*4f1223e8SApple OSS Distributions {
85*4f1223e8SApple OSS Distributions 	struct exc_thread_arg *ta = (struct exc_thread_arg *)arg;
86*4f1223e8SApple OSS Distributions 	mach_port_t ePort = ta->port;
87*4f1223e8SApple OSS Distributions 	ReplyType reply_type = ta->rt;
88*4f1223e8SApple OSS Distributions 
89*4f1223e8SApple OSS Distributions 	char msg_store[MSG + MAX_TRAILER_SIZE];
90*4f1223e8SApple OSS Distributions 	char reply_store[MSG];
91*4f1223e8SApple OSS Distributions 	mach_msg_header_t *msg = (mach_msg_header_t *)msg_store;
92*4f1223e8SApple OSS Distributions 	vm_address_t page;
93*4f1223e8SApple OSS Distributions 	kern_return_t kr;
94*4f1223e8SApple OSS Distributions 
95*4f1223e8SApple OSS Distributions 	kr = vm_allocate(mach_task_self(), &page, PG_ALLOC, VM_FLAGS_ANYWHERE);
96*4f1223e8SApple OSS Distributions 	T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "ool page allocation of %d bytes", PG_ALLOC);
97*4f1223e8SApple OSS Distributions 
98*4f1223e8SApple OSS Distributions 	mach_voucher_t voucher = create_task_voucher();
99*4f1223e8SApple OSS Distributions 
100*4f1223e8SApple OSS Distributions 	while (1) {
101*4f1223e8SApple OSS Distributions 		bzero(msg, sizeof(msg_store));
102*4f1223e8SApple OSS Distributions 
103*4f1223e8SApple OSS Distributions 		msg->msgh_local_port = ePort;
104*4f1223e8SApple OSS Distributions 		msg->msgh_size = MSG;
105*4f1223e8SApple OSS Distributions 		kr = mach_msg_receive(msg);
106*4f1223e8SApple OSS Distributions 		T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "exception msg recv");
107*4f1223e8SApple OSS Distributions 
108*4f1223e8SApple OSS Distributions 		bzero(reply_store, sizeof(reply_store));
109*4f1223e8SApple OSS Distributions 
110*4f1223e8SApple OSS Distributions 		switch (reply_type) {
111*4f1223e8SApple OSS Distributions 		case ReplyWithNoError: {
112*4f1223e8SApple OSS Distributions #pragma pack(4)
113*4f1223e8SApple OSS Distributions 			typedef struct {
114*4f1223e8SApple OSS Distributions 				mach_msg_header_t hdr;
115*4f1223e8SApple OSS Distributions 				NDR_record_t ndr;
116*4f1223e8SApple OSS Distributions 				kern_return_t kr;
117*4f1223e8SApple OSS Distributions 			} reply_fmt_t;
118*4f1223e8SApple OSS Distributions #pragma pack()
119*4f1223e8SApple OSS Distributions 			reply_fmt_t *reply = (reply_fmt_t *)reply_store;
120*4f1223e8SApple OSS Distributions 
121*4f1223e8SApple OSS Distributions 			reply->hdr.msgh_bits = MACH_MSGH_BITS_SET(MACH_MSG_TYPE_MOVE_SEND_ONCE, 0, 0, 0);
122*4f1223e8SApple OSS Distributions 			reply->hdr.msgh_remote_port = msg->msgh_remote_port;
123*4f1223e8SApple OSS Distributions 			reply->hdr.msgh_local_port = MACH_PORT_NULL;
124*4f1223e8SApple OSS Distributions 			reply->hdr.msgh_size = sizeof(*reply);
125*4f1223e8SApple OSS Distributions 			reply->hdr.msgh_id = msg->msgh_id + 100;
126*4f1223e8SApple OSS Distributions 			break;
127*4f1223e8SApple OSS Distributions 		}
128*4f1223e8SApple OSS Distributions 
129*4f1223e8SApple OSS Distributions 		case ReplyWithReplyPort: {
130*4f1223e8SApple OSS Distributions #pragma pack(4)
131*4f1223e8SApple OSS Distributions 			typedef struct {
132*4f1223e8SApple OSS Distributions 				mach_msg_header_t hdr;
133*4f1223e8SApple OSS Distributions 				NDR_record_t ndr;
134*4f1223e8SApple OSS Distributions 				kern_return_t kr;
135*4f1223e8SApple OSS Distributions 			} reply_fmt_t;
136*4f1223e8SApple OSS Distributions #pragma pack()
137*4f1223e8SApple OSS Distributions 			reply_fmt_t *reply = (reply_fmt_t *)reply_store;
138*4f1223e8SApple OSS Distributions 
139*4f1223e8SApple OSS Distributions 			reply->hdr.msgh_bits = MACH_MSGH_BITS_SET(MACH_MSG_TYPE_MOVE_SEND_ONCE, MACH_MSG_TYPE_COPY_SEND, 0, 0);
140*4f1223e8SApple OSS Distributions 			reply->hdr.msgh_remote_port = msg->msgh_remote_port;
141*4f1223e8SApple OSS Distributions 			reply->hdr.msgh_local_port = ePort; /* Bogus */
142*4f1223e8SApple OSS Distributions 			reply->hdr.msgh_size = sizeof(*reply);
143*4f1223e8SApple OSS Distributions 			reply->hdr.msgh_id = msg->msgh_id + 100;
144*4f1223e8SApple OSS Distributions 			break;
145*4f1223e8SApple OSS Distributions 		}
146*4f1223e8SApple OSS Distributions 
147*4f1223e8SApple OSS Distributions 		case ReplyWithReplyPortMove: {
148*4f1223e8SApple OSS Distributions #pragma pack(4)
149*4f1223e8SApple OSS Distributions 			typedef struct {
150*4f1223e8SApple OSS Distributions 				mach_msg_header_t hdr;
151*4f1223e8SApple OSS Distributions 				NDR_record_t ndr;
152*4f1223e8SApple OSS Distributions 				kern_return_t kr;
153*4f1223e8SApple OSS Distributions 			} reply_fmt_t;
154*4f1223e8SApple OSS Distributions #pragma pack()
155*4f1223e8SApple OSS Distributions 			reply_fmt_t *reply = (reply_fmt_t *)reply_store;
156*4f1223e8SApple OSS Distributions 
157*4f1223e8SApple OSS Distributions 			reply->hdr.msgh_bits = MACH_MSGH_BITS_SET(MACH_MSG_TYPE_MOVE_SEND_ONCE, MACH_MSG_TYPE_MOVE_SEND, 0, 0);
158*4f1223e8SApple OSS Distributions 			reply->hdr.msgh_remote_port = msg->msgh_remote_port;
159*4f1223e8SApple OSS Distributions 			reply->hdr.msgh_local_port = ePort; /* Bogus */
160*4f1223e8SApple OSS Distributions 			reply->hdr.msgh_size = sizeof(*reply);
161*4f1223e8SApple OSS Distributions 			reply->hdr.msgh_id = msg->msgh_id + 100;
162*4f1223e8SApple OSS Distributions 			break;
163*4f1223e8SApple OSS Distributions 		}
164*4f1223e8SApple OSS Distributions 
165*4f1223e8SApple OSS Distributions 		case ReplyWithReplyPortCplxBit: {
166*4f1223e8SApple OSS Distributions #pragma pack(4)
167*4f1223e8SApple OSS Distributions 			typedef struct {
168*4f1223e8SApple OSS Distributions 				mach_msg_header_t hdr;
169*4f1223e8SApple OSS Distributions 				mach_msg_body_t body;
170*4f1223e8SApple OSS Distributions 			} reply_fmt_t;
171*4f1223e8SApple OSS Distributions #pragma pack()
172*4f1223e8SApple OSS Distributions 			reply_fmt_t *reply = (reply_fmt_t *)reply_store;
173*4f1223e8SApple OSS Distributions 
174*4f1223e8SApple OSS Distributions 			reply->hdr.msgh_bits = MACH_MSGH_BITS_SET(MACH_MSG_TYPE_MOVE_SEND_ONCE, MACH_MSG_TYPE_COPY_SEND, 0, MACH_MSGH_BITS_COMPLEX);
175*4f1223e8SApple OSS Distributions 			reply->hdr.msgh_remote_port = msg->msgh_remote_port;
176*4f1223e8SApple OSS Distributions 			reply->hdr.msgh_local_port = ePort; /* Bogus */
177*4f1223e8SApple OSS Distributions 			reply->hdr.msgh_size = sizeof(*reply);
178*4f1223e8SApple OSS Distributions 			reply->hdr.msgh_id = msg->msgh_id + 100;
179*4f1223e8SApple OSS Distributions 			reply->body.msgh_descriptor_count = 0;
180*4f1223e8SApple OSS Distributions 			break;
181*4f1223e8SApple OSS Distributions 		}
182*4f1223e8SApple OSS Distributions 
183*4f1223e8SApple OSS Distributions 		case ReplyWithReplyPortMoveCplxBit: {
184*4f1223e8SApple OSS Distributions #pragma pack(4)
185*4f1223e8SApple OSS Distributions 			typedef struct {
186*4f1223e8SApple OSS Distributions 				mach_msg_header_t hdr;
187*4f1223e8SApple OSS Distributions 				mach_msg_body_t body;
188*4f1223e8SApple OSS Distributions 			} reply_fmt_t;
189*4f1223e8SApple OSS Distributions #pragma pack()
190*4f1223e8SApple OSS Distributions 			reply_fmt_t *reply = (reply_fmt_t *)reply_store;
191*4f1223e8SApple OSS Distributions 
192*4f1223e8SApple OSS Distributions 			reply->hdr.msgh_bits = MACH_MSGH_BITS_SET(MACH_MSG_TYPE_MOVE_SEND_ONCE, MACH_MSG_TYPE_MOVE_SEND, 0, MACH_MSGH_BITS_COMPLEX);
193*4f1223e8SApple OSS Distributions 			reply->hdr.msgh_remote_port = msg->msgh_remote_port;
194*4f1223e8SApple OSS Distributions 			reply->hdr.msgh_local_port = ePort; /* Bogus */
195*4f1223e8SApple OSS Distributions 			reply->hdr.msgh_size = sizeof(*reply);
196*4f1223e8SApple OSS Distributions 			reply->hdr.msgh_id = msg->msgh_id + 100;
197*4f1223e8SApple OSS Distributions 			reply->body.msgh_descriptor_count = 0;
198*4f1223e8SApple OSS Distributions 			break;
199*4f1223e8SApple OSS Distributions 		}
200*4f1223e8SApple OSS Distributions 
201*4f1223e8SApple OSS Distributions 		case ReplyWithPortDesc: {
202*4f1223e8SApple OSS Distributions #pragma pack(4)
203*4f1223e8SApple OSS Distributions 			typedef struct {
204*4f1223e8SApple OSS Distributions 				mach_msg_header_t hdr;
205*4f1223e8SApple OSS Distributions 				mach_msg_body_t body;
206*4f1223e8SApple OSS Distributions 				mach_msg_port_descriptor_t port;
207*4f1223e8SApple OSS Distributions 			} reply_fmt_t;
208*4f1223e8SApple OSS Distributions #pragma pack()
209*4f1223e8SApple OSS Distributions 			reply_fmt_t *reply = (reply_fmt_t *)reply_store;
210*4f1223e8SApple OSS Distributions 
211*4f1223e8SApple OSS Distributions 			reply->hdr.msgh_bits = MACH_MSGH_BITS_SET(MACH_MSG_TYPE_MOVE_SEND_ONCE, 0, 0, MACH_MSGH_BITS_COMPLEX);
212*4f1223e8SApple OSS Distributions 			reply->hdr.msgh_remote_port = msg->msgh_remote_port;
213*4f1223e8SApple OSS Distributions 			reply->hdr.msgh_local_port = MACH_PORT_NULL;
214*4f1223e8SApple OSS Distributions 			reply->hdr.msgh_size = sizeof(*reply);
215*4f1223e8SApple OSS Distributions 			reply->hdr.msgh_id = msg->msgh_id + 100;
216*4f1223e8SApple OSS Distributions 			reply->body.msgh_descriptor_count = 1;
217*4f1223e8SApple OSS Distributions 			reply->port.type = MACH_MSG_PORT_DESCRIPTOR;
218*4f1223e8SApple OSS Distributions 			reply->port.name = ePort;
219*4f1223e8SApple OSS Distributions 			reply->port.disposition = MACH_MSG_TYPE_COPY_SEND;
220*4f1223e8SApple OSS Distributions 			break;
221*4f1223e8SApple OSS Distributions 		}
222*4f1223e8SApple OSS Distributions 
223*4f1223e8SApple OSS Distributions 		case ReplyWithOOLDesc: {
224*4f1223e8SApple OSS Distributions #pragma pack(4)
225*4f1223e8SApple OSS Distributions 			typedef struct {
226*4f1223e8SApple OSS Distributions 				mach_msg_header_t hdr;
227*4f1223e8SApple OSS Distributions 				mach_msg_body_t body;
228*4f1223e8SApple OSS Distributions 				mach_msg_ool_descriptor_t ool;
229*4f1223e8SApple OSS Distributions 			} reply_fmt_t;
230*4f1223e8SApple OSS Distributions #pragma pack()
231*4f1223e8SApple OSS Distributions 			reply_fmt_t *reply = (reply_fmt_t *)reply_store;
232*4f1223e8SApple OSS Distributions 
233*4f1223e8SApple OSS Distributions 			reply->hdr.msgh_bits = MACH_MSGH_BITS_SET(MACH_MSG_TYPE_MOVE_SEND_ONCE, 0, 0, MACH_MSGH_BITS_COMPLEX);
234*4f1223e8SApple OSS Distributions 			reply->hdr.msgh_remote_port = msg->msgh_remote_port;
235*4f1223e8SApple OSS Distributions 			reply->hdr.msgh_local_port = MACH_PORT_NULL;
236*4f1223e8SApple OSS Distributions 			reply->hdr.msgh_size = sizeof(*reply);
237*4f1223e8SApple OSS Distributions 			reply->hdr.msgh_id = msg->msgh_id + 100;
238*4f1223e8SApple OSS Distributions 			reply->body.msgh_descriptor_count = 1;
239*4f1223e8SApple OSS Distributions 			reply->ool.type = MACH_MSG_OOL_DESCRIPTOR;
240*4f1223e8SApple OSS Distributions 			reply->ool.address = (void *)page;
241*4f1223e8SApple OSS Distributions 			reply->ool.size = PG_ALLOC;
242*4f1223e8SApple OSS Distributions 			reply->ool.deallocate = 0;
243*4f1223e8SApple OSS Distributions 			reply->ool.copy = MACH_MSG_VIRTUAL_COPY;
244*4f1223e8SApple OSS Distributions 			break;
245*4f1223e8SApple OSS Distributions 		}
246*4f1223e8SApple OSS Distributions 
247*4f1223e8SApple OSS Distributions 		case ReplyWithVoucher: {
248*4f1223e8SApple OSS Distributions #pragma pack(4)
249*4f1223e8SApple OSS Distributions 			typedef struct {
250*4f1223e8SApple OSS Distributions 				mach_msg_header_t hdr;
251*4f1223e8SApple OSS Distributions 				NDR_record_t ndr;
252*4f1223e8SApple OSS Distributions 				kern_return_t kr;
253*4f1223e8SApple OSS Distributions 			} reply_fmt_t;
254*4f1223e8SApple OSS Distributions #pragma pack()
255*4f1223e8SApple OSS Distributions 			reply_fmt_t *reply = (reply_fmt_t *)reply_store;
256*4f1223e8SApple OSS Distributions 
257*4f1223e8SApple OSS Distributions 			reply->hdr.msgh_remote_port = msg->msgh_remote_port;
258*4f1223e8SApple OSS Distributions 			reply->hdr.msgh_local_port = MACH_PORT_NULL;
259*4f1223e8SApple OSS Distributions 			reply->hdr.msgh_size = sizeof(*reply);
260*4f1223e8SApple OSS Distributions 			reply->hdr.msgh_id = msg->msgh_id + 100;
261*4f1223e8SApple OSS Distributions 			reply->kr = KERN_SUCCESS;
262*4f1223e8SApple OSS Distributions 
263*4f1223e8SApple OSS Distributions 			/* try to send a voucher */
264*4f1223e8SApple OSS Distributions 			reply->hdr.msgh_bits = MACH_MSGH_BITS_SET(MACH_MSG_TYPE_MOVE_SEND_ONCE,
265*4f1223e8SApple OSS Distributions 			    0,
266*4f1223e8SApple OSS Distributions 			    MACH_MSG_TYPE_MOVE_SEND,
267*4f1223e8SApple OSS Distributions 			    0);
268*4f1223e8SApple OSS Distributions 			reply->hdr.msgh_voucher_port = voucher;
269*4f1223e8SApple OSS Distributions 			voucher = MACH_VOUCHER_NULL;
270*4f1223e8SApple OSS Distributions 			break;
271*4f1223e8SApple OSS Distributions 		}
272*4f1223e8SApple OSS Distributions 
273*4f1223e8SApple OSS Distributions 		case ReplyWithVoucherGarbage: {
274*4f1223e8SApple OSS Distributions #pragma pack(4)
275*4f1223e8SApple OSS Distributions 			typedef struct {
276*4f1223e8SApple OSS Distributions 				mach_msg_header_t hdr;
277*4f1223e8SApple OSS Distributions 				NDR_record_t ndr;
278*4f1223e8SApple OSS Distributions 				kern_return_t kr;
279*4f1223e8SApple OSS Distributions 			} reply_fmt_t;
280*4f1223e8SApple OSS Distributions #pragma pack()
281*4f1223e8SApple OSS Distributions 			reply_fmt_t *reply = (reply_fmt_t *)reply_store;
282*4f1223e8SApple OSS Distributions 
283*4f1223e8SApple OSS Distributions 			reply->hdr.msgh_remote_port = msg->msgh_remote_port;
284*4f1223e8SApple OSS Distributions 			reply->hdr.msgh_local_port = MACH_PORT_NULL;
285*4f1223e8SApple OSS Distributions 			reply->hdr.msgh_size = sizeof(*reply);
286*4f1223e8SApple OSS Distributions 			reply->hdr.msgh_id = msg->msgh_id + 100;
287*4f1223e8SApple OSS Distributions 			reply->kr = KERN_SUCCESS;
288*4f1223e8SApple OSS Distributions 
289*4f1223e8SApple OSS Distributions 			/* don't claim to send a voucher */
290*4f1223e8SApple OSS Distributions 			reply->hdr.msgh_bits = MACH_MSGH_BITS_SET(MACH_MSG_TYPE_MOVE_SEND_ONCE,
291*4f1223e8SApple OSS Distributions 			    0, 0, 0);
292*4f1223e8SApple OSS Distributions 			/* but put some bits in the field */
293*4f1223e8SApple OSS Distributions 			reply->hdr.msgh_voucher_port = (mach_voucher_t)0xdead;
294*4f1223e8SApple OSS Distributions 			break;
295*4f1223e8SApple OSS Distributions 		}
296*4f1223e8SApple OSS Distributions 
297*4f1223e8SApple OSS Distributions 		default:
298*4f1223e8SApple OSS Distributions 			T_ASSERT_FAIL("Invalid ReplyType: %d", reply_type);
299*4f1223e8SApple OSS Distributions 			T_END;
300*4f1223e8SApple OSS Distributions 		}
301*4f1223e8SApple OSS Distributions 
302*4f1223e8SApple OSS Distributions 		if (voucher) {
303*4f1223e8SApple OSS Distributions 			kr = mach_port_mod_refs(mach_task_self(), voucher,
304*4f1223e8SApple OSS Distributions 			    MACH_PORT_RIGHT_SEND, -1);
305*4f1223e8SApple OSS Distributions 			T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "destroy voucher");
306*4f1223e8SApple OSS Distributions 		}
307*4f1223e8SApple OSS Distributions 
308*4f1223e8SApple OSS Distributions 		T_LOG("sending exception reply of type (%s)", reply_type_str(reply_type));
309*4f1223e8SApple OSS Distributions 		kr = mach_msg_send((mach_msg_header_t *)reply_store);
310*4f1223e8SApple OSS Distributions 		T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "exception reply msg send");
311*4f1223e8SApple OSS Distributions 
312*4f1223e8SApple OSS Distributions 		T_PASS("Successfully delivered exception reply message of type %s", reply_type_str(reply_type));
313*4f1223e8SApple OSS Distributions 		T_END;
314*4f1223e8SApple OSS Distributions 		return NULL;
315*4f1223e8SApple OSS Distributions 	}
316*4f1223e8SApple OSS Distributions }
317*4f1223e8SApple OSS Distributions 
318*4f1223e8SApple OSS Distributions static sigjmp_buf jb;
319*4f1223e8SApple OSS Distributions static int *bad_pointer = NULL;
320*4f1223e8SApple OSS Distributions static int s_sigmask = 0;
321*4f1223e8SApple OSS Distributions 
322*4f1223e8SApple OSS Distributions static void
signal_handler(int sig,siginfo_t * sip __unused,void * ucontext __unused)323*4f1223e8SApple OSS Distributions signal_handler(int sig, siginfo_t *sip __unused, void *ucontext __unused)
324*4f1223e8SApple OSS Distributions {
325*4f1223e8SApple OSS Distributions 	if (sigmask(sig) & s_sigmask) { /* TODO: check that the fault was generated by us */
326*4f1223e8SApple OSS Distributions 		siglongjmp(jb, sig);
327*4f1223e8SApple OSS Distributions 	} else {
328*4f1223e8SApple OSS Distributions 		siglongjmp(jb, -sig);
329*4f1223e8SApple OSS Distributions 	}
330*4f1223e8SApple OSS Distributions }
331*4f1223e8SApple OSS Distributions 
332*4f1223e8SApple OSS Distributions static int
handle_signals(void)333*4f1223e8SApple OSS Distributions handle_signals(void)
334*4f1223e8SApple OSS Distributions {
335*4f1223e8SApple OSS Distributions 	int mask = 0;
336*4f1223e8SApple OSS Distributions 
337*4f1223e8SApple OSS Distributions 	struct sigaction sa = {
338*4f1223e8SApple OSS Distributions 		.sa_sigaction = signal_handler,
339*4f1223e8SApple OSS Distributions 		.sa_flags = SA_SIGINFO
340*4f1223e8SApple OSS Distributions 	};
341*4f1223e8SApple OSS Distributions 	sigfillset(&sa.sa_mask);
342*4f1223e8SApple OSS Distributions 
343*4f1223e8SApple OSS Distributions 	T_QUIET; T_ASSERT_POSIX_ZERO(sigaction(SIGTRAP, &sa, NULL), NULL);
344*4f1223e8SApple OSS Distributions 	mask |= sigmask(SIGTRAP);
345*4f1223e8SApple OSS Distributions 
346*4f1223e8SApple OSS Distributions 	T_QUIET; T_ASSERT_POSIX_ZERO(sigaction(SIGSEGV, &sa, NULL), NULL);
347*4f1223e8SApple OSS Distributions 	mask |= sigmask(SIGSEGV);
348*4f1223e8SApple OSS Distributions 
349*4f1223e8SApple OSS Distributions 	T_QUIET; T_ASSERT_POSIX_ZERO(sigaction(SIGILL, &sa, NULL), NULL);
350*4f1223e8SApple OSS Distributions 	mask |= sigmask(SIGILL);
351*4f1223e8SApple OSS Distributions 
352*4f1223e8SApple OSS Distributions 	return mask;
353*4f1223e8SApple OSS Distributions }
354*4f1223e8SApple OSS Distributions 
355*4f1223e8SApple OSS Distributions static void
test_exc_reply_type(ReplyType reply_type)356*4f1223e8SApple OSS Distributions test_exc_reply_type(ReplyType reply_type)
357*4f1223e8SApple OSS Distributions {
358*4f1223e8SApple OSS Distributions 	kern_return_t kr;
359*4f1223e8SApple OSS Distributions 	task_t me = mach_task_self();
360*4f1223e8SApple OSS Distributions 	thread_t self = mach_thread_self();
361*4f1223e8SApple OSS Distributions 	pthread_t handler_thread;
362*4f1223e8SApple OSS Distributions 	pthread_attr_t  attr;
363*4f1223e8SApple OSS Distributions 	mach_port_t ePort;
364*4f1223e8SApple OSS Distributions 
365*4f1223e8SApple OSS Distributions 	s_sigmask = handle_signals();
366*4f1223e8SApple OSS Distributions 	T_LOG("task self = 0x%x, thread self = 0x%x\n", me, self);
367*4f1223e8SApple OSS Distributions 
368*4f1223e8SApple OSS Distributions 	kr = mach_port_allocate(me, MACH_PORT_RIGHT_RECEIVE, &ePort);
369*4f1223e8SApple OSS Distributions 	T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "allocate receive right");
370*4f1223e8SApple OSS Distributions 
371*4f1223e8SApple OSS Distributions 	kr = mach_port_insert_right(me, ePort, ePort, MACH_MSG_TYPE_MAKE_SEND);
372*4f1223e8SApple OSS Distributions 	T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "insert right into port=[%d]", ePort);
373*4f1223e8SApple OSS Distributions 
374*4f1223e8SApple OSS Distributions 	kr = thread_set_exception_ports(self, EXC_MASK_ALL, ePort, EXCEPTION_DEFAULT, THREAD_STATE_NONE);
375*4f1223e8SApple OSS Distributions 	T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "set exception ports on self=[%d], handler=[%d]", self, ePort);
376*4f1223e8SApple OSS Distributions 
377*4f1223e8SApple OSS Distributions 	pthread_attr_init(&attr);
378*4f1223e8SApple OSS Distributions 	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
379*4f1223e8SApple OSS Distributions 	struct exc_thread_arg *ta = (struct exc_thread_arg *)malloc(sizeof(*ta));
380*4f1223e8SApple OSS Distributions 	T_QUIET; T_ASSERT_NOTNULL(ta, "exception handler thread args allocation");
381*4f1223e8SApple OSS Distributions 	ta->port = ePort;
382*4f1223e8SApple OSS Distributions 	ta->rt = reply_type;
383*4f1223e8SApple OSS Distributions 
384*4f1223e8SApple OSS Distributions 	T_QUIET; T_ASSERT_POSIX_SUCCESS(pthread_create(&handler_thread, &attr, handle_exceptions, (void *)ta),
385*4f1223e8SApple OSS Distributions 	    "pthread creation");
386*4f1223e8SApple OSS Distributions 
387*4f1223e8SApple OSS Distributions 	pthread_attr_destroy(&attr);
388*4f1223e8SApple OSS Distributions 
389*4f1223e8SApple OSS Distributions 	/* cause exception! */
390*4f1223e8SApple OSS Distributions 	int x = sigsetjmp(jb, 0); //s_sigmask);
391*4f1223e8SApple OSS Distributions 	if (x == 0) {
392*4f1223e8SApple OSS Distributions 		*bad_pointer = 0;
393*4f1223e8SApple OSS Distributions 	} else if (x < 0) {
394*4f1223e8SApple OSS Distributions 		T_FAIL("Unexpected state on return-from-exception");
395*4f1223e8SApple OSS Distributions 		T_END;
396*4f1223e8SApple OSS Distributions 	} else {
397*4f1223e8SApple OSS Distributions 		T_PASS("Successfully recovered from exception");
398*4f1223e8SApple OSS Distributions 		T_END;
399*4f1223e8SApple OSS Distributions 	}
400*4f1223e8SApple OSS Distributions 	T_FAIL("Unexpected end of test!");
401*4f1223e8SApple OSS Distributions 	T_END;
402*4f1223e8SApple OSS Distributions }
403*4f1223e8SApple OSS Distributions 
404*4f1223e8SApple OSS Distributions T_DECL(mach_exc_ReplyNoError, "exception server reply with no error",
405*4f1223e8SApple OSS Distributions     T_META_CHECK_LEAKS(false), T_META_IGNORECRASHES(".*mach_exception_reply.*"), T_META_TAG_VM_PREFERRED)
406*4f1223e8SApple OSS Distributions {
407*4f1223e8SApple OSS Distributions 	test_exc_reply_type(ReplyWithNoError);
408*4f1223e8SApple OSS Distributions }
409*4f1223e8SApple OSS Distributions T_DECL(mach_exc_ReplyWithReplyPort, "exception server reply with reply port",
410*4f1223e8SApple OSS Distributions     T_META_CHECK_LEAKS(false), T_META_IGNORECRASHES(".*mach_exception_reply.*"), T_META_TAG_VM_PREFERRED)
411*4f1223e8SApple OSS Distributions {
412*4f1223e8SApple OSS Distributions 	test_exc_reply_type(ReplyWithReplyPort);
413*4f1223e8SApple OSS Distributions }
414*4f1223e8SApple OSS Distributions T_DECL(mach_exc_ReplyWithReplyPortMove, "exception server reply with reply port as MOVE_SEND",
415*4f1223e8SApple OSS Distributions     T_META_CHECK_LEAKS(false), T_META_IGNORECRASHES(".*mach_exception_reply.*"), T_META_TAG_VM_PREFERRED)
416*4f1223e8SApple OSS Distributions {
417*4f1223e8SApple OSS Distributions 	test_exc_reply_type(ReplyWithReplyPortMove);
418*4f1223e8SApple OSS Distributions }
419*4f1223e8SApple OSS Distributions T_DECL(mach_exc_ReplyWithReplyPortCplxBit, "exception server reply with reply port and complex bit set",
420*4f1223e8SApple OSS Distributions     T_META_CHECK_LEAKS(false), T_META_IGNORECRASHES(".*mach_exception_reply.*"), T_META_TAG_VM_PREFERRED)
421*4f1223e8SApple OSS Distributions {
422*4f1223e8SApple OSS Distributions 	test_exc_reply_type(ReplyWithReplyPortCplxBit);
423*4f1223e8SApple OSS Distributions }
424*4f1223e8SApple OSS Distributions T_DECL(mach_exc_ReplyWithReplyPortMoveCplxBit, "exception server reply with reply port as MOVE_SEND and complex bit set",
425*4f1223e8SApple OSS Distributions     T_META_CHECK_LEAKS(false), T_META_IGNORECRASHES(".*mach_exception_reply.*"), T_META_TAG_VM_PREFERRED)
426*4f1223e8SApple OSS Distributions {
427*4f1223e8SApple OSS Distributions 	test_exc_reply_type(ReplyWithReplyPortMoveCplxBit);
428*4f1223e8SApple OSS Distributions }
429*4f1223e8SApple OSS Distributions T_DECL(mach_exc_ReplyWithOOLPort, "exception server reply with OOL port descriptor",
430*4f1223e8SApple OSS Distributions     T_META_CHECK_LEAKS(false), T_META_IGNORECRASHES(".*mach_exception_reply.*"), T_META_TAG_VM_PREFERRED)
431*4f1223e8SApple OSS Distributions {
432*4f1223e8SApple OSS Distributions 	test_exc_reply_type(ReplyWithPortDesc);
433*4f1223e8SApple OSS Distributions }
434*4f1223e8SApple OSS Distributions T_DECL(mach_exc_ReplyWithOOLDesc, "exception server reply with OOL memory descriptor",
435*4f1223e8SApple OSS Distributions     T_META_CHECK_LEAKS(false), T_META_IGNORECRASHES(".*mach_exception_reply.*"), T_META_TAG_VM_PREFERRED)
436*4f1223e8SApple OSS Distributions {
437*4f1223e8SApple OSS Distributions 	test_exc_reply_type(ReplyWithOOLDesc);
438*4f1223e8SApple OSS Distributions }
439*4f1223e8SApple OSS Distributions T_DECL(mach_exc_ReplyWithVoucher, "exception server reply with a voucher",
440*4f1223e8SApple OSS Distributions     T_META_CHECK_LEAKS(false), T_META_IGNORECRASHES(".*mach_exception_reply.*"), T_META_TAG_VM_PREFERRED)
441*4f1223e8SApple OSS Distributions {
442*4f1223e8SApple OSS Distributions 	test_exc_reply_type(ReplyWithVoucher);
443*4f1223e8SApple OSS Distributions }
444*4f1223e8SApple OSS Distributions T_DECL(mach_exc_ReplyWithVoucherGarbage, "exception server reply with bits in msgh_voucher_port",
445*4f1223e8SApple OSS Distributions     T_META_CHECK_LEAKS(false), T_META_IGNORECRASHES(".*mach_exception_reply.*"), T_META_TAG_VM_PREFERRED)
446*4f1223e8SApple OSS Distributions {
447*4f1223e8SApple OSS Distributions 	test_exc_reply_type(ReplyWithVoucherGarbage);
448*4f1223e8SApple OSS Distributions }
449