1*27b03b36SApple OSS Distributions /*
2*27b03b36SApple OSS Distributions * prioritize process launch: Tests prioritized process launch across posix spawn and exec.
3*27b03b36SApple OSS Distributions */
4*27b03b36SApple OSS Distributions
5*27b03b36SApple OSS Distributions #include <dispatch/dispatch.h>
6*27b03b36SApple OSS Distributions #include <pthread.h>
7*27b03b36SApple OSS Distributions #include <launch.h>
8*27b03b36SApple OSS Distributions #include <mach/mach.h>
9*27b03b36SApple OSS Distributions #include <mach/message.h>
10*27b03b36SApple OSS Distributions #include <mach/mach_voucher.h>
11*27b03b36SApple OSS Distributions #include <pthread/workqueue_private.h>
12*27b03b36SApple OSS Distributions #include <voucher/ipc_pthread_priority_types.h>
13*27b03b36SApple OSS Distributions #include <servers/bootstrap.h>
14*27b03b36SApple OSS Distributions #include <stdlib.h>
15*27b03b36SApple OSS Distributions #include <sys/event.h>
16*27b03b36SApple OSS Distributions #include <stdio.h>
17*27b03b36SApple OSS Distributions #include <unistd.h>
18*27b03b36SApple OSS Distributions #include <crt_externs.h>
19*27b03b36SApple OSS Distributions #include <signal.h>
20*27b03b36SApple OSS Distributions #include <sys/types.h>
21*27b03b36SApple OSS Distributions #include <sys/sysctl.h>
22*27b03b36SApple OSS Distributions #include <libkern/OSAtomic.h>
23*27b03b36SApple OSS Distributions #include <sys/wait.h>
24*27b03b36SApple OSS Distributions #include <spawn.h>
25*27b03b36SApple OSS Distributions #include <spawn_private.h>
26*27b03b36SApple OSS Distributions #include <string.h>
27*27b03b36SApple OSS Distributions
28*27b03b36SApple OSS Distributions
29*27b03b36SApple OSS Distributions mach_port_t
30*27b03b36SApple OSS Distributions receive(
31*27b03b36SApple OSS Distributions mach_port_t rcv_port,
32*27b03b36SApple OSS Distributions mach_port_t notify_port);
33*27b03b36SApple OSS Distributions
34*27b03b36SApple OSS Distributions static int
get_pri(thread_t thread_port)35*27b03b36SApple OSS Distributions get_pri(thread_t thread_port)
36*27b03b36SApple OSS Distributions {
37*27b03b36SApple OSS Distributions kern_return_t kr;
38*27b03b36SApple OSS Distributions
39*27b03b36SApple OSS Distributions thread_extended_info_data_t extended_info;
40*27b03b36SApple OSS Distributions mach_msg_type_number_t count = THREAD_EXTENDED_INFO_COUNT;
41*27b03b36SApple OSS Distributions kr = thread_info(thread_port, THREAD_EXTENDED_INFO,
42*27b03b36SApple OSS Distributions (thread_info_t)&extended_info, &count);
43*27b03b36SApple OSS Distributions
44*27b03b36SApple OSS Distributions if (kr != KERN_SUCCESS) {
45*27b03b36SApple OSS Distributions printf("thread info failed to get current priority of the thread\n");
46*27b03b36SApple OSS Distributions }
47*27b03b36SApple OSS Distributions return extended_info.pth_priority;
48*27b03b36SApple OSS Distributions }
49*27b03b36SApple OSS Distributions
50*27b03b36SApple OSS Distributions static void
set_thread_name(const char * fn_name)51*27b03b36SApple OSS Distributions set_thread_name(const char *fn_name)
52*27b03b36SApple OSS Distributions {
53*27b03b36SApple OSS Distributions char name[50] = "";
54*27b03b36SApple OSS Distributions
55*27b03b36SApple OSS Distributions thread_t thread_port = pthread_mach_thread_np(pthread_self());
56*27b03b36SApple OSS Distributions
57*27b03b36SApple OSS Distributions int pri = get_pri(thread_port);
58*27b03b36SApple OSS Distributions
59*27b03b36SApple OSS Distributions snprintf(name, sizeof(name), "%s at pri %2d", fn_name, pri);
60*27b03b36SApple OSS Distributions pthread_setname_np(name);
61*27b03b36SApple OSS Distributions }
62*27b03b36SApple OSS Distributions
63*27b03b36SApple OSS Distributions static void
send(mach_port_t send_port,mach_port_t reply_port,mach_port_t msg_port,mach_msg_option_t options,int send_disposition)64*27b03b36SApple OSS Distributions send(
65*27b03b36SApple OSS Distributions mach_port_t send_port,
66*27b03b36SApple OSS Distributions mach_port_t reply_port,
67*27b03b36SApple OSS Distributions mach_port_t msg_port,
68*27b03b36SApple OSS Distributions mach_msg_option_t options,
69*27b03b36SApple OSS Distributions int send_disposition)
70*27b03b36SApple OSS Distributions {
71*27b03b36SApple OSS Distributions kern_return_t ret = 0;
72*27b03b36SApple OSS Distributions
73*27b03b36SApple OSS Distributions struct {
74*27b03b36SApple OSS Distributions mach_msg_header_t header;
75*27b03b36SApple OSS Distributions mach_msg_body_t body;
76*27b03b36SApple OSS Distributions mach_msg_port_descriptor_t port_descriptor;
77*27b03b36SApple OSS Distributions } send_msg = {
78*27b03b36SApple OSS Distributions .header = {
79*27b03b36SApple OSS Distributions .msgh_remote_port = send_port,
80*27b03b36SApple OSS Distributions .msgh_local_port = reply_port,
81*27b03b36SApple OSS Distributions .msgh_bits = MACH_MSGH_BITS_SET(send_disposition,
82*27b03b36SApple OSS Distributions reply_port ? MACH_MSG_TYPE_MAKE_SEND_ONCE : 0,
83*27b03b36SApple OSS Distributions MACH_MSG_TYPE_MOVE_SEND,
84*27b03b36SApple OSS Distributions MACH_MSGH_BITS_COMPLEX),
85*27b03b36SApple OSS Distributions .msgh_id = 0x100,
86*27b03b36SApple OSS Distributions .msgh_size = sizeof(send_msg),
87*27b03b36SApple OSS Distributions },
88*27b03b36SApple OSS Distributions .body = {
89*27b03b36SApple OSS Distributions .msgh_descriptor_count = 1,
90*27b03b36SApple OSS Distributions },
91*27b03b36SApple OSS Distributions .port_descriptor = {
92*27b03b36SApple OSS Distributions .name = msg_port,
93*27b03b36SApple OSS Distributions .disposition = MACH_MSG_TYPE_MOVE_RECEIVE,
94*27b03b36SApple OSS Distributions .type = MACH_MSG_PORT_DESCRIPTOR,
95*27b03b36SApple OSS Distributions },
96*27b03b36SApple OSS Distributions };
97*27b03b36SApple OSS Distributions
98*27b03b36SApple OSS Distributions if (msg_port == MACH_PORT_NULL) {
99*27b03b36SApple OSS Distributions send_msg.body.msgh_descriptor_count = 0;
100*27b03b36SApple OSS Distributions }
101*27b03b36SApple OSS Distributions
102*27b03b36SApple OSS Distributions ret = mach_msg(&(send_msg.header),
103*27b03b36SApple OSS Distributions MACH_SEND_MSG |
104*27b03b36SApple OSS Distributions MACH_SEND_TIMEOUT |
105*27b03b36SApple OSS Distributions MACH_SEND_OVERRIDE |
106*27b03b36SApple OSS Distributions options,
107*27b03b36SApple OSS Distributions send_msg.header.msgh_size,
108*27b03b36SApple OSS Distributions 0,
109*27b03b36SApple OSS Distributions MACH_PORT_NULL,
110*27b03b36SApple OSS Distributions 10000,
111*27b03b36SApple OSS Distributions 0);
112*27b03b36SApple OSS Distributions
113*27b03b36SApple OSS Distributions if (ret != KERN_SUCCESS) {
114*27b03b36SApple OSS Distributions printf("mach_msg_send failed with error %d\n", ret);
115*27b03b36SApple OSS Distributions }
116*27b03b36SApple OSS Distributions }
117*27b03b36SApple OSS Distributions
118*27b03b36SApple OSS Distributions mach_port_t
receive(mach_port_t rcv_port,mach_port_t notify_port)119*27b03b36SApple OSS Distributions receive(
120*27b03b36SApple OSS Distributions mach_port_t rcv_port,
121*27b03b36SApple OSS Distributions mach_port_t notify_port)
122*27b03b36SApple OSS Distributions {
123*27b03b36SApple OSS Distributions kern_return_t ret = 0;
124*27b03b36SApple OSS Distributions mach_port_t service_port;
125*27b03b36SApple OSS Distributions
126*27b03b36SApple OSS Distributions struct {
127*27b03b36SApple OSS Distributions mach_msg_header_t header;
128*27b03b36SApple OSS Distributions mach_msg_body_t body;
129*27b03b36SApple OSS Distributions mach_msg_port_descriptor_t port_descriptor;
130*27b03b36SApple OSS Distributions mach_msg_trailer_t trailer;
131*27b03b36SApple OSS Distributions } rcv_msg = {
132*27b03b36SApple OSS Distributions .header =
133*27b03b36SApple OSS Distributions {
134*27b03b36SApple OSS Distributions .msgh_remote_port = MACH_PORT_NULL,
135*27b03b36SApple OSS Distributions .msgh_local_port = rcv_port,
136*27b03b36SApple OSS Distributions .msgh_size = sizeof(rcv_msg),
137*27b03b36SApple OSS Distributions },
138*27b03b36SApple OSS Distributions };
139*27b03b36SApple OSS Distributions
140*27b03b36SApple OSS Distributions printf("Client: Starting sync receive\n");
141*27b03b36SApple OSS Distributions
142*27b03b36SApple OSS Distributions ret = mach_msg(&(rcv_msg.header),
143*27b03b36SApple OSS Distributions MACH_RCV_MSG | MACH_RCV_LARGE |
144*27b03b36SApple OSS Distributions (notify_port ? MACH_RCV_SYNC_WAIT : 0),
145*27b03b36SApple OSS Distributions 0,
146*27b03b36SApple OSS Distributions rcv_msg.header.msgh_size,
147*27b03b36SApple OSS Distributions rcv_port,
148*27b03b36SApple OSS Distributions 0,
149*27b03b36SApple OSS Distributions notify_port);
150*27b03b36SApple OSS Distributions
151*27b03b36SApple OSS Distributions printf("mach msg rcv returned %d\n", ret);
152*27b03b36SApple OSS Distributions
153*27b03b36SApple OSS Distributions
154*27b03b36SApple OSS Distributions if (rcv_msg.body.msgh_descriptor_count != 1) {
155*27b03b36SApple OSS Distributions if (notify_port) {
156*27b03b36SApple OSS Distributions printf("Did not receive a service port in mach msg %d\n", rcv_msg.body.msgh_descriptor_count);
157*27b03b36SApple OSS Distributions }
158*27b03b36SApple OSS Distributions return MACH_PORT_NULL;
159*27b03b36SApple OSS Distributions }
160*27b03b36SApple OSS Distributions
161*27b03b36SApple OSS Distributions service_port = rcv_msg.port_descriptor.name;
162*27b03b36SApple OSS Distributions return service_port;
163*27b03b36SApple OSS Distributions }
164*27b03b36SApple OSS Distributions
165*27b03b36SApple OSS Distributions int
main(int argc,char * argv[])166*27b03b36SApple OSS Distributions main(int argc __attribute__((unused)), char *argv[])
167*27b03b36SApple OSS Distributions {
168*27b03b36SApple OSS Distributions int priority;
169*27b03b36SApple OSS Distributions set_thread_name(__FUNCTION__);
170*27b03b36SApple OSS Distributions
171*27b03b36SApple OSS Distributions /* Check for priority */
172*27b03b36SApple OSS Distributions priority = get_pri(mach_thread_self());
173*27b03b36SApple OSS Distributions printf("The priority of child is %d\n", priority);
174*27b03b36SApple OSS Distributions
175*27b03b36SApple OSS Distributions if (strcmp(argv[1], "EXIT") == 0) {
176*27b03b36SApple OSS Distributions printf("Helper process exiting\n");
177*27b03b36SApple OSS Distributions exit(priority);
178*27b03b36SApple OSS Distributions } else if (strcmp(argv[1], "EXEC") == 0) {
179*27b03b36SApple OSS Distributions int ret;
180*27b03b36SApple OSS Distributions
181*27b03b36SApple OSS Distributions printf("Helper process execing\n");
182*27b03b36SApple OSS Distributions /* exec the same binary with EXIT arg */
183*27b03b36SApple OSS Distributions char *binary = "prioritize_process_launch_helper";
184*27b03b36SApple OSS Distributions char *new_argv[] = {binary, "EXIT", NULL};
185*27b03b36SApple OSS Distributions ret = execve(binary, new_argv, NULL);
186*27b03b36SApple OSS Distributions exit(ret);
187*27b03b36SApple OSS Distributions } else if (strcmp(argv[1], "SETEXEC") == 0) {
188*27b03b36SApple OSS Distributions int ret;
189*27b03b36SApple OSS Distributions int child_pid;
190*27b03b36SApple OSS Distributions posix_spawnattr_t attr;
191*27b03b36SApple OSS Distributions
192*27b03b36SApple OSS Distributions ret = posix_spawnattr_init(&attr);
193*27b03b36SApple OSS Distributions if (ret != 0) {
194*27b03b36SApple OSS Distributions printf("posix_spawnattr_init failed \n");
195*27b03b36SApple OSS Distributions exit(ret);
196*27b03b36SApple OSS Distributions }
197*27b03b36SApple OSS Distributions ret = posix_spawnattr_setflags(&attr, POSIX_SPAWN_SETEXEC);
198*27b03b36SApple OSS Distributions if (ret != 0) {
199*27b03b36SApple OSS Distributions printf("posix_spawnattr_setflags failed \n");
200*27b03b36SApple OSS Distributions exit(ret);
201*27b03b36SApple OSS Distributions }
202*27b03b36SApple OSS Distributions
203*27b03b36SApple OSS Distributions printf("Helper process doing posix_spawn set_exec\n");
204*27b03b36SApple OSS Distributions /* set exec the same binary with EXIT arg */
205*27b03b36SApple OSS Distributions char *binary = "prioritize_process_launch_helper";
206*27b03b36SApple OSS Distributions char *new_argv[] = {binary, "EXIT", NULL};
207*27b03b36SApple OSS Distributions
208*27b03b36SApple OSS Distributions ret = posix_spawn(&child_pid, binary, NULL, &attr, new_argv, NULL);
209*27b03b36SApple OSS Distributions exit(ret);
210*27b03b36SApple OSS Distributions } else if (strcmp(argv[1], "SETEXEC_PORTS") == 0) {
211*27b03b36SApple OSS Distributions int ret;
212*27b03b36SApple OSS Distributions int child_pid;
213*27b03b36SApple OSS Distributions posix_spawnattr_t attr;
214*27b03b36SApple OSS Distributions mach_port_t port;
215*27b03b36SApple OSS Distributions
216*27b03b36SApple OSS Distributions kern_return_t kr = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &port);
217*27b03b36SApple OSS Distributions if (kr != KERN_SUCCESS) {
218*27b03b36SApple OSS Distributions printf("mach_port_allocate failed with error %d\n", kr);
219*27b03b36SApple OSS Distributions exit(kr);
220*27b03b36SApple OSS Distributions }
221*27b03b36SApple OSS Distributions
222*27b03b36SApple OSS Distributions kr = mach_port_insert_right(mach_task_self(), port, port, MACH_MSG_TYPE_MAKE_SEND);
223*27b03b36SApple OSS Distributions if (kr != KERN_SUCCESS) {
224*27b03b36SApple OSS Distributions printf("mach_port_insert_right failed with error %d\n", kr);
225*27b03b36SApple OSS Distributions exit(kr);
226*27b03b36SApple OSS Distributions }
227*27b03b36SApple OSS Distributions
228*27b03b36SApple OSS Distributions ret = posix_spawnattr_init(&attr);
229*27b03b36SApple OSS Distributions if (ret != 0) {
230*27b03b36SApple OSS Distributions printf("posix_spawnattr_init failed \n");
231*27b03b36SApple OSS Distributions exit(ret);
232*27b03b36SApple OSS Distributions }
233*27b03b36SApple OSS Distributions
234*27b03b36SApple OSS Distributions ret = posix_spawnattr_setflags(&attr, POSIX_SPAWN_SETEXEC);
235*27b03b36SApple OSS Distributions if (ret != 0) {
236*27b03b36SApple OSS Distributions printf("posix_spawnattr_setflags failed \n");
237*27b03b36SApple OSS Distributions exit(ret);
238*27b03b36SApple OSS Distributions }
239*27b03b36SApple OSS Distributions
240*27b03b36SApple OSS Distributions ret = posix_spawnattr_set_importancewatch_port_np(&attr, 1, &port);
241*27b03b36SApple OSS Distributions if (ret != 0) {
242*27b03b36SApple OSS Distributions printf("posix_spawnattr_set_importance_port_np failed \n");
243*27b03b36SApple OSS Distributions exit(ret);
244*27b03b36SApple OSS Distributions }
245*27b03b36SApple OSS Distributions
246*27b03b36SApple OSS Distributions printf("Helper process doing posix_spawn set_exec\n");
247*27b03b36SApple OSS Distributions /* set exec the same binary with EXIT arg */
248*27b03b36SApple OSS Distributions char *binary = "prioritize_process_launch_helper";
249*27b03b36SApple OSS Distributions char *new_argv[] = {binary, "EXIT", NULL};
250*27b03b36SApple OSS Distributions
251*27b03b36SApple OSS Distributions ret = posix_spawn(&child_pid, binary, NULL, &attr, new_argv, NULL);
252*27b03b36SApple OSS Distributions printf("spawned failed with error %d\n", ret);
253*27b03b36SApple OSS Distributions exit(ret);
254*27b03b36SApple OSS Distributions } else if (strcmp(argv[1], "WAIT") == 0) {
255*27b03b36SApple OSS Distributions do {
256*27b03b36SApple OSS Distributions sleep(1);
257*27b03b36SApple OSS Distributions priority = get_pri(mach_thread_self());
258*27b03b36SApple OSS Distributions } while (priority == 47);
259*27b03b36SApple OSS Distributions exit(priority);
260*27b03b36SApple OSS Distributions } else if (strcmp(argv[1], "MULTIWAIT") == 0) {
261*27b03b36SApple OSS Distributions do {
262*27b03b36SApple OSS Distributions sleep(1);
263*27b03b36SApple OSS Distributions priority = get_pri(mach_thread_self());
264*27b03b36SApple OSS Distributions } while (priority == 47);
265*27b03b36SApple OSS Distributions printf("The priority came down to %d\n", priority);
266*27b03b36SApple OSS Distributions do {
267*27b03b36SApple OSS Distributions sleep(1);
268*27b03b36SApple OSS Distributions priority = get_pri(mach_thread_self());
269*27b03b36SApple OSS Distributions } while (priority == 37);
270*27b03b36SApple OSS Distributions printf("The priority came down to %d\n", priority);
271*27b03b36SApple OSS Distributions exit(priority);
272*27b03b36SApple OSS Distributions } else if (strcmp(argv[1], "MSGSYNC") == 0) {
273*27b03b36SApple OSS Distributions int ret_val = 31;
274*27b03b36SApple OSS Distributions mach_port_array_t port_array = NULL;
275*27b03b36SApple OSS Distributions unsigned int portCnt = 0;
276*27b03b36SApple OSS Distributions mach_port_t send_port;
277*27b03b36SApple OSS Distributions mach_port_t special_reply_port;
278*27b03b36SApple OSS Distributions mach_port_t service_port;
279*27b03b36SApple OSS Distributions kern_return_t kr;
280*27b03b36SApple OSS Distributions
281*27b03b36SApple OSS Distributions priority = get_pri(mach_thread_self());
282*27b03b36SApple OSS Distributions printf("The priority of spawned binary is to %d\n", priority);
283*27b03b36SApple OSS Distributions if (priority != 47) {
284*27b03b36SApple OSS Distributions ret_val = 0;
285*27b03b36SApple OSS Distributions }
286*27b03b36SApple OSS Distributions
287*27b03b36SApple OSS Distributions /* Get the stashed send right using mach_ports_lookup */
288*27b03b36SApple OSS Distributions kr = mach_ports_lookup(mach_task_self(), &port_array, &portCnt);
289*27b03b36SApple OSS Distributions if (kr != KERN_SUCCESS) {
290*27b03b36SApple OSS Distributions printf("mach_ports_lookup failed with return value %d and port count %d\n", kr, portCnt);
291*27b03b36SApple OSS Distributions exit(0);
292*27b03b36SApple OSS Distributions }
293*27b03b36SApple OSS Distributions
294*27b03b36SApple OSS Distributions send_port = port_array[0];
295*27b03b36SApple OSS Distributions special_reply_port = thread_get_special_reply_port();
296*27b03b36SApple OSS Distributions if (!MACH_PORT_VALID(special_reply_port)) {
297*27b03b36SApple OSS Distributions printf("Failed to special reply port for thread\n");
298*27b03b36SApple OSS Distributions exit(0);
299*27b03b36SApple OSS Distributions }
300*27b03b36SApple OSS Distributions
301*27b03b36SApple OSS Distributions /* Perform a Sync bootstrap checkin */
302*27b03b36SApple OSS Distributions send(send_port, special_reply_port, MACH_PORT_NULL, MACH_SEND_SYNC_BOOTSTRAP_CHECKIN, MACH_MSG_TYPE_COPY_SEND);
303*27b03b36SApple OSS Distributions sleep(2);
304*27b03b36SApple OSS Distributions
305*27b03b36SApple OSS Distributions /* Make sure we are still boosted */
306*27b03b36SApple OSS Distributions priority = get_pri(mach_thread_self());
307*27b03b36SApple OSS Distributions printf("The priority of spawned binary is to %d\n", priority);
308*27b03b36SApple OSS Distributions if (priority != 47) {
309*27b03b36SApple OSS Distributions ret_val = 0;
310*27b03b36SApple OSS Distributions }
311*27b03b36SApple OSS Distributions
312*27b03b36SApple OSS Distributions /* Receive the service port */
313*27b03b36SApple OSS Distributions service_port = receive(special_reply_port, send_port);
314*27b03b36SApple OSS Distributions
315*27b03b36SApple OSS Distributions /* Make sure we are still boosted */
316*27b03b36SApple OSS Distributions priority = get_pri(mach_thread_self());
317*27b03b36SApple OSS Distributions printf("The priority of spawned binary is to %d\n", priority);
318*27b03b36SApple OSS Distributions if (priority != 47) {
319*27b03b36SApple OSS Distributions ret_val = 0;
320*27b03b36SApple OSS Distributions }
321*27b03b36SApple OSS Distributions
322*27b03b36SApple OSS Distributions /* Try to receive on service port */
323*27b03b36SApple OSS Distributions receive(service_port, MACH_PORT_NULL);
324*27b03b36SApple OSS Distributions
325*27b03b36SApple OSS Distributions /* Make sure we are no longer boosted */
326*27b03b36SApple OSS Distributions priority = get_pri(mach_thread_self());
327*27b03b36SApple OSS Distributions printf("The priority of spawned binary is to %d\n", priority);
328*27b03b36SApple OSS Distributions if (priority != 31) {
329*27b03b36SApple OSS Distributions ret_val = 0;
330*27b03b36SApple OSS Distributions }
331*27b03b36SApple OSS Distributions exit(ret_val);
332*27b03b36SApple OSS Distributions }
333*27b03b36SApple OSS Distributions
334*27b03b36SApple OSS Distributions exit(0);
335*27b03b36SApple OSS Distributions }
336