1 /* $NetBSD: mach_task.c,v 1.54 2005/02/26 23:10:20 perry Exp $ */
2
3 /*-
4 * Copyright (c) 2002-2003 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Emmanuel Dreyfus
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the NetBSD
21 * Foundation, Inc. and its contributors.
22 * 4. Neither the name of The NetBSD Foundation nor the names of its
23 * contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 */
38
39 #include "opt_ktrace.h"
40 #include "opt_compat_darwin.h"
41
42 #include <sys/cdefs.h>
43 __KERNEL_RCSID(0, "$NetBSD: mach_task.c,v 1.54 2005/02/26 23:10:20 perry Exp $");
44
45 #include <sys/types.h>
46 #include <sys/param.h>
47 #include <sys/exec.h>
48 #include <sys/systm.h>
49 #include <sys/proc.h>
50 #include <sys/ktrace.h>
51 #include <sys/resourcevar.h>
52 #include <sys/malloc.h>
53 #include <sys/sa.h>
54 #include <sys/mount.h>
55 #include <sys/ktrace.h>
56 #include <sys/syscallargs.h>
57
58 #include <uvm/uvm_extern.h>
59 #include <uvm/uvm_param.h>
60
61 #include <compat/mach/mach_types.h>
62 #include <compat/mach/mach_message.h>
63 #include <compat/mach/mach_clock.h>
64 #include <compat/mach/mach_errno.h>
65 #include <compat/mach/mach_exec.h>
66 #include <compat/mach/mach_port.h>
67 #include <compat/mach/mach_task.h>
68 #include <compat/mach/mach_services.h>
69 #include <compat/mach/mach_syscallargs.h>
70
71 #ifdef COMPAT_DARWIN
72 #include <compat/darwin/darwin_exec.h>
73 #endif
74
75 #define ISSET(t, f) ((t) & (f))
76
77 static void
78 update_exception_port(struct mach_emuldata *, int exc, struct mach_port *);
79
80 int
81 mach_task_get_special_port(args)
82 struct mach_trap_args *args;
83 {
84 mach_task_get_special_port_request_t *req = args->smsg;
85 mach_task_get_special_port_reply_t *rep = args->rmsg;
86 size_t *msglen = args->rsize;
87 struct lwp *l = args->l;
88 struct lwp *tl = args->tl;
89 struct mach_emuldata *med;
90 struct mach_right *mr;
91
92 med = (struct mach_emuldata *)tl->l_proc->p_emuldata;
93
94 switch (req->req_which_port) {
95 case MACH_TASK_KERNEL_PORT:
96 mr = mach_right_get(med->med_kernel, l, MACH_PORT_TYPE_SEND, 0);
97 break;
98
99 case MACH_TASK_HOST_PORT:
100 mr = mach_right_get(med->med_host, l, MACH_PORT_TYPE_SEND, 0);
101 break;
102
103 case MACH_TASK_BOOTSTRAP_PORT:
104 mr = mach_right_get(med->med_bootstrap,
105 l, MACH_PORT_TYPE_SEND, 0);
106 break;
107
108 case MACH_TASK_WIRED_LEDGER_PORT:
109 case MACH_TASK_PAGED_LEDGER_PORT:
110 default:
111 uprintf("mach_task_get_special_port(): unimpl. port %d\n",
112 req->req_which_port);
113 return mach_msg_error(args, EINVAL);
114 break;
115 }
116
117 *msglen = sizeof(*rep);
118 mach_set_header(rep, req, *msglen);
119 mach_add_port_desc(rep, mr->mr_name);
120 mach_set_trailer(rep, *msglen);
121
122 return 0;
123 }
124
125 int
126 mach_ports_lookup(args)
127 struct mach_trap_args *args;
128 {
129 mach_ports_lookup_request_t *req = args->smsg;
130 mach_ports_lookup_reply_t *rep = args->rmsg;
131 size_t *msglen = args->rsize;
132 struct lwp *l = args->l;
133 struct lwp *tl = args->tl;
134 struct proc *p = l->l_proc;
135 struct mach_emuldata *med;
136 struct mach_right *mr;
137 mach_port_name_t mnp[7];
138 void *uaddr;
139 int error;
140 int count;
141
142 /*
143 * This is some out of band data sent with the reply. In the
144 * encountered situation, the out of band data has always been null
145 * filled. We have to see more of this in order to fully understand
146 * how this trap works.
147 */
148 med = (struct mach_emuldata *)tl->l_proc->p_emuldata;
149 mnp[0] = (mach_port_name_t)MACH_PORT_DEAD;
150 mnp[3] = (mach_port_name_t)MACH_PORT_DEAD;
151 mnp[5] = (mach_port_name_t)MACH_PORT_DEAD;
152 mnp[6] = (mach_port_name_t)MACH_PORT_DEAD;
153
154 mr = mach_right_get(med->med_kernel, l, MACH_PORT_TYPE_SEND, 0);
155 mnp[MACH_TASK_KERNEL_PORT] = mr->mr_name;
156 mr = mach_right_get(med->med_host, l, MACH_PORT_TYPE_SEND, 0);
157 mnp[MACH_TASK_HOST_PORT] = mr->mr_name;
158 mr = mach_right_get(med->med_bootstrap, l, MACH_PORT_TYPE_SEND, 0);
159 mnp[MACH_TASK_BOOTSTRAP_PORT] = mr->mr_name;
160
161 /*
162 * On Darwin, the data seems always null...
163 */
164 uaddr = NULL;
165 if ((error = mach_ool_copyout(p, &mnp[0],
166 &uaddr, sizeof(mnp), MACH_OOL_TRACE)) != 0)
167 return mach_msg_error(args, error);
168
169 count = 3; /* XXX Shouldn't this be 7? */
170
171 *msglen = sizeof(*rep);
172 mach_set_header(rep, req, *msglen);
173 mach_add_ool_ports_desc(rep, uaddr, count);
174
175 rep->rep_init_port_set_count = count;
176
177 mach_set_trailer(rep, *msglen);
178
179 return 0;
180 }
181
182 int
183 mach_task_set_special_port(args)
184 struct mach_trap_args *args;
185 {
186 mach_task_set_special_port_request_t *req = args->smsg;
187 mach_task_set_special_port_reply_t *rep = args->rmsg;
188 size_t *msglen = args->rsize;
189 struct lwp *l = args->l;
190 struct lwp *tl = args->tl;
191 mach_port_t mn;
192 struct mach_right *mr;
193 struct mach_port *mp;
194 struct mach_emuldata *med;
195
196 mn = req->req_special_port.name;
197
198 /* Null port ? */
199 if (mn == 0)
200 return mach_msg_error(args, 0);
201
202 /* Does the inserted port exists? */
203 if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == 0)
204 return mach_msg_error(args, EPERM);
205
206 if (mr->mr_type == MACH_PORT_TYPE_DEAD_NAME)
207 return mach_msg_error(args, EINVAL);
208
209 med = (struct mach_emuldata *)tl->l_proc->p_emuldata;
210
211 switch (req->req_which_port) {
212 case MACH_TASK_KERNEL_PORT:
213 mp = med->med_kernel;
214 med->med_kernel = mr->mr_port;
215 if (mr->mr_port != NULL)
216 MACH_PORT_REF(mr->mr_port);
217 MACH_PORT_UNREF(mp);
218 break;
219
220 case MACH_TASK_HOST_PORT:
221 mp = med->med_host;
222 med->med_host = mr->mr_port;
223 if (mr->mr_port != NULL)
224 MACH_PORT_REF(mr->mr_port);
225 MACH_PORT_UNREF(mp);
226 break;
227
228 case MACH_TASK_BOOTSTRAP_PORT:
229 mp = med->med_bootstrap;
230 med->med_bootstrap = mr->mr_port;
231 if (mr->mr_port != NULL)
232 MACH_PORT_REF(mr->mr_port);
233 MACH_PORT_UNREF(mp);
234 #ifdef COMPAT_DARWIN
235 /*
236 * mach_init sets the bootstrap port for any new process.
237 */
238 {
239 struct darwin_emuldata *ded;
240
241 ded = tl->l_proc->p_emuldata;
242 if (ded->ded_fakepid == 1) {
243 mach_bootstrap_port = med->med_bootstrap;
244 #ifdef DEBUG_DARWIN
245 printf("*** New bootstrap port %p, "
246 "recv %p [%p]\n",
247 mach_bootstrap_port,
248 mach_bootstrap_port->mp_recv,
249 mach_bootstrap_port->mp_recv->mr_sethead);
250 #endif /* DEBUG_DARWIN */
251 }
252 }
253 #endif /* COMPAT_DARWIN */
254 break;
255
256 default:
257 uprintf("mach_task_set_special_port: unimplemented port %d\n",
258 req->req_which_port);
259 }
260
261 *msglen = sizeof(*rep);
262 mach_set_header(rep, req, *msglen);
263
264 rep->rep_retval = 0;
265
266 mach_set_trailer(rep, *msglen);
267
268 return 0;
269 }
270
271 int
272 mach_task_threads(args)
273 struct mach_trap_args *args;
274 {
275 mach_task_threads_request_t *req = args->smsg;
276 mach_task_threads_reply_t *rep = args->rmsg;
277 size_t *msglen = args->rsize;
278 struct lwp *l = args->l;
279 struct lwp *tl = args->tl;
280 struct proc *tp = tl->l_proc;
281 struct lwp *cl;
282 struct mach_emuldata *med;
283 struct mach_lwp_emuldata *mle;
284 int error;
285 void *uaddr;
286 size_t size;
287 int i = 0;
288 struct mach_right *mr;
289 mach_port_name_t *mnp;
290
291 med = tp->p_emuldata;
292 size = tp->p_nlwps * sizeof(*mnp);
293 mnp = malloc(size, M_TEMP, M_WAITOK);
294 uaddr = NULL;
295
296 LIST_FOREACH(cl, &tp->p_lwps, l_sibling) {
297 mle = cl->l_emuldata;
298 mr = mach_right_get(mle->mle_kernel, l, MACH_PORT_TYPE_SEND, 0);
299 mnp[i++] = mr->mr_name;
300 }
301
302 /* This will free mnp */
303 if ((error = mach_ool_copyout(l->l_proc, mnp, &uaddr,
304 size, MACH_OOL_TRACE|MACH_OOL_FREE)) != 0)
305 return mach_msg_error(args, error);
306
307 *msglen = sizeof(*rep);
308 mach_set_header(rep, req, *msglen);
309 mach_add_ool_ports_desc(rep, uaddr, tp->p_nlwps);
310
311 rep->rep_count = tp->p_nlwps;
312
313 mach_set_trailer(rep, *msglen);
314
315 return 0;
316 }
317
318 int
319 mach_task_get_exception_ports(args)
320 struct mach_trap_args *args;
321 {
322 mach_task_get_exception_ports_request_t *req = args->smsg;
323 mach_task_get_exception_ports_reply_t *rep = args->rmsg;
324 struct lwp *l = args->l;
325 struct lwp *tl = args->tl;
326 size_t *msglen = args->rsize;
327 struct mach_emuldata *med;
328 struct mach_right *mr;
329 struct mach_exc_info *mei;
330 int i, j, count;
331
332 med = tl->l_proc->p_emuldata;
333
334 /* It always returns an array of 32 ports even if only 9 can be used */
335 count = sizeof(rep->rep_old_handler) / sizeof(rep->rep_old_handler[0]);
336
337 mach_set_header(rep, req, *msglen);
338
339 rep->rep_masks_count = count;
340
341 j = 0;
342 for (i = 0; i <= MACH_EXC_MAX; i++) {
343 if (med->med_exc[i] == NULL)
344 continue;
345
346 if (med->med_exc[i]->mp_datatype != MACH_MP_EXC_INFO) {
347 #ifdef DIAGNOSTIC
348 printf("Exception port without mach_exc_info\n");
349 #endif
350 continue;
351 }
352 mei = med->med_exc[i]->mp_data;
353
354 mr = mach_right_get(med->med_exc[i], l, MACH_PORT_TYPE_SEND, 0);
355
356 mach_add_port_desc(rep, mr->mr_name);
357
358 rep->rep_masks[j] = 1 << i;
359 rep->rep_old_behaviors[j] = mei->mei_behavior;
360 rep->rep_old_flavors[j] = mei->mei_flavor;
361
362 j++;
363 }
364
365 *msglen = sizeof(*rep);
366 mach_set_trailer(rep, *msglen);
367
368 return 0;
369 }
370
371 static void
372 update_exception_port(med, exc, mp)
373 struct mach_emuldata *med;
374 int exc;
375 struct mach_port *mp;
376 {
377 if (med->med_exc[exc] != NULL)
378 MACH_PORT_UNREF(med->med_exc[exc]);
379 med->med_exc[exc] = mp;
380 MACH_PORT_REF(mp);
381
382 return;
383 }
384
385 int
386 mach_task_set_exception_ports(args)
387 struct mach_trap_args *args;
388 {
389 mach_task_set_exception_ports_request_t *req = args->smsg;
390 mach_task_set_exception_ports_reply_t *rep = args->rmsg;
391 struct lwp *l = args->l;
392 struct lwp *tl = args->tl;
393 size_t *msglen = args->rsize;
394 struct mach_emuldata *med;
395 mach_port_name_t mn;
396 struct mach_right *mr;
397 struct mach_port *mp;
398 struct mach_exc_info *mei;
399
400 mn = req->req_new_port.name;
401 if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_SEND)) == 0)
402 return mach_msg_error(args, EPERM);
403
404 mp = mr->mr_port;
405 #ifdef DIAGNOSTIC
406 if ((mp->mp_datatype != MACH_MP_EXC_INFO) &&
407 (mp->mp_datatype != MACH_MP_NONE))
408 printf("mach_task_set_exception_ports: data exists\n");
409 #endif
410 mei = malloc(sizeof(*mei), M_EMULDATA, M_WAITOK);
411 mei->mei_flavor = req->req_flavor;
412 mei->mei_behavior = req->req_behavior;
413
414 mp->mp_data = mei;
415 mp->mp_flags |= MACH_MP_DATA_ALLOCATED;
416 mp->mp_datatype = MACH_MP_EXC_INFO;
417
418 med = tl->l_proc->p_emuldata;
419 if (req->req_mask & MACH_EXC_MASK_BAD_ACCESS)
420 update_exception_port(med, MACH_EXC_BAD_ACCESS, mp);
421 if (req->req_mask & MACH_EXC_MASK_BAD_INSTRUCTION)
422 update_exception_port(med, MACH_EXC_BAD_INSTRUCTION, mp);
423 if (req->req_mask & MACH_EXC_MASK_ARITHMETIC)
424 update_exception_port(med, MACH_EXC_ARITHMETIC, mp);
425 if (req->req_mask & MACH_EXC_MASK_EMULATION)
426 update_exception_port(med, MACH_EXC_EMULATION, mp);
427 if (req->req_mask & MACH_EXC_MASK_SOFTWARE)
428 update_exception_port(med, MACH_EXC_SOFTWARE, mp);
429 if (req->req_mask & MACH_EXC_MASK_BREAKPOINT)
430 update_exception_port(med, MACH_EXC_BREAKPOINT, mp);
431 if (req->req_mask & MACH_EXC_MASK_SYSCALL)
432 update_exception_port(med, MACH_EXC_SYSCALL, mp);
433 if (req->req_mask & MACH_EXC_MASK_MACH_SYSCALL)
434 update_exception_port(med, MACH_EXC_MACH_SYSCALL, mp);
435 if (req->req_mask & MACH_EXC_MASK_RPC_ALERT)
436 update_exception_port(med, MACH_EXC_RPC_ALERT, mp);
437
438 #ifdef DEBUG_MACH
439 if (req->req_mask & (MACH_EXC_ARITHMETIC |
440 MACH_EXC_EMULATION | MACH_EXC_MASK_SYSCALL |
441 MACH_EXC_MASK_MACH_SYSCALL | MACH_EXC_RPC_ALERT))
442 printf("mach_set_exception_ports: some exceptions are "
443 "not supported (mask %x)\n", req->req_mask);
444 #endif
445
446 *msglen = sizeof(*rep);
447 mach_set_header(rep, req, *msglen);
448
449 rep->rep_retval = 0;
450
451 mach_set_trailer(rep, *msglen);
452
453 return 0;
454 }
455
456 int
457 mach_task_info(args)
458 struct mach_trap_args *args;
459 {
460 mach_task_info_request_t *req = args->smsg;
461 mach_task_info_reply_t *rep = args->rmsg;
462 struct lwp *tl = args->tl;
463 size_t *msglen = args->rsize;
464 int count;
465 struct proc *tp = tl->l_proc;
466
467 switch(req->req_flavor) {
468 case MACH_TASK_BASIC_INFO: {
469 struct mach_task_basic_info *mtbi;
470 struct rusage *ru;
471
472 count = sizeof(*mtbi) / sizeof(rep->rep_info[0]);
473 if (req->req_count < count)
474 return mach_msg_error(args, ENOBUFS);
475
476 ru = &tp->p_stats->p_ru;
477 mtbi = (struct mach_task_basic_info *)&rep->rep_info[0];
478
479 mtbi->mtbi_suspend_count = ru->ru_nvcsw + ru->ru_nivcsw;
480 mtbi->mtbi_virtual_size = ru->ru_ixrss;
481 mtbi->mtbi_resident_size = ru->ru_maxrss;
482 mtbi->mtbi_user_time.seconds = ru->ru_utime.tv_sec;
483 mtbi->mtbi_user_time.microseconds = ru->ru_utime.tv_usec;
484 mtbi->mtbi_system_time.seconds = ru->ru_stime.tv_sec;
485 mtbi->mtbi_system_time.microseconds = ru->ru_stime.tv_usec;
486 mtbi->mtbi_policy = 0;
487
488 *msglen = sizeof(*rep) - sizeof(rep->rep_info) + sizeof(*mtbi);
489 break;
490 }
491
492 /* XXX this is supposed to be about threads, not processes... */
493 case MACH_TASK_THREAD_TIMES_INFO: {
494 struct mach_task_thread_times_info *mttti;
495 struct rusage *ru;
496
497 count = sizeof(*mttti) / sizeof(rep->rep_info[0]);
498 if (req->req_count < count)
499 return mach_msg_error(args, ENOBUFS);
500
501 ru = &tp->p_stats->p_ru;
502 mttti = (struct mach_task_thread_times_info *)&rep->rep_info[0];
503
504 mttti->mttti_user_time.seconds = ru->ru_utime.tv_sec;
505 mttti->mttti_user_time.microseconds = ru->ru_utime.tv_usec;
506 mttti->mttti_system_time.seconds = ru->ru_stime.tv_sec;
507 mttti->mttti_system_time.microseconds = ru->ru_stime.tv_usec;
508
509 *msglen = sizeof(*rep) - sizeof(rep->rep_info) + sizeof(*mttti);
510 break;
511 }
512
513 /* XXX a few statistics missing here */
514 case MACH_TASK_EVENTS_INFO: {
515 struct mach_task_events_info *mtei;
516 struct rusage *ru;
517
518 count = sizeof(*mtei) / sizeof(rep->rep_info[0]);
519 if (req->req_count < count)
520 return mach_msg_error(args, ENOBUFS);
521
522 mtei = (struct mach_task_events_info *)&rep->rep_info[0];
523 ru = &tp->p_stats->p_ru;
524
525 mtei->mtei_faults = ru->ru_majflt;
526 mtei->mtei_pageins = ru->ru_minflt;
527 mtei->mtei_cow_faults = 0; /* XXX */
528 mtei->mtei_message_sent = ru->ru_msgsnd;
529 mtei->mtei_message_received = ru->ru_msgrcv;
530 mtei->mtei_syscalls_mach = 0; /* XXX */
531 mtei->mtei_syscalls_unix = 0; /* XXX */
532 mtei->mtei_csw = 0; /* XXX */
533
534 *msglen = sizeof(*rep) - sizeof(rep->rep_info) + sizeof(*mtei);
535 break;
536 }
537
538 default:
539 uprintf("mach_task_info: unsupported flavor %d\n",
540 req->req_flavor);
541 return mach_msg_error(args, EINVAL);
542 };
543
544 mach_set_header(rep, req, *msglen);
545
546 rep->rep_count = count;
547
548 mach_set_trailer(rep, *msglen);
549
550 return 0;
551 }
552
553 int
554 mach_task_suspend(args)
555 struct mach_trap_args *args;
556 {
557 mach_task_suspend_request_t *req = args->smsg;
558 mach_task_suspend_reply_t *rep = args->rmsg;
559 size_t *msglen = args->rsize;
560 struct lwp *tl = args->tl;
561 struct lwp *lp;
562 struct mach_emuldata *med;
563 struct proc *tp = tl->l_proc;
564
565 med = tp->p_emuldata;
566 med->med_suspend++; /* XXX Mach also has a per thread semaphore */
567
568 LIST_FOREACH(lp, &tp->p_lwps, l_sibling) {
569 switch(lp->l_stat) {
570 case LSONPROC:
571 case LSRUN:
572 case LSSLEEP:
573 case LSSUSPENDED:
574 case LSZOMB:
575 case LSDEAD:
576 break;
577 default:
578 return mach_msg_error(args, 0);
579 break;
580 }
581 }
582 proc_stop(tp, 0);
583
584 *msglen = sizeof(*rep);
585 mach_set_header(rep, req, *msglen);
586
587 rep->rep_retval = 0;
588
589 mach_set_trailer(rep, *msglen);
590
591 return 0;
592 }
593
594 int
595 mach_task_resume(args)
596 struct mach_trap_args *args;
597 {
598 mach_task_resume_request_t *req = args->smsg;
599 mach_task_resume_reply_t *rep = args->rmsg;
600 size_t *msglen = args->rsize;
601 struct lwp *tl = args->tl;
602 struct mach_emuldata *med;
603 struct proc *tp = tl->l_proc;
604
605 med = tp->p_emuldata;
606 med->med_suspend--; /* XXX Mach also has a per thread semaphore */
607 #if 0
608 if (med->med_suspend > 0)
609 return mach_msg_error(args, 0); /* XXX error code */
610 #endif
611
612 /* XXX We should also wake up the stopped thread... */
613 #ifdef DEBUG_MACH
614 printf("resuming pid %d\n", tp->p_pid);
615 #endif
616 (void)proc_unstop(tp);
617
618 *msglen = sizeof(*rep);
619 mach_set_header(rep, req, *msglen);
620
621 rep->rep_retval = 0;
622
623 mach_set_trailer(rep, *msglen);
624
625 return 0;
626 }
627
628 int
629 mach_task_terminate(args)
630 struct mach_trap_args *args;
631 {
632 mach_task_resume_request_t *req = args->smsg;
633 mach_task_resume_reply_t *rep = args->rmsg;
634 size_t *msglen = args->rsize;
635 struct lwp *tl = args->tl;
636 struct sys_exit_args cup;
637 register_t retval;
638 int error;
639
640
641 SCARG(&cup, rval) = 0;
642 error = sys_exit(tl, &cup, &retval);
643
644 *msglen = sizeof(*rep);
645 mach_set_header(rep, req, *msglen);
646
647 rep->rep_retval = native_to_mach_errno[error];
648
649 mach_set_trailer(rep, *msglen);
650
651 return 0;
652 }
653
654 int
655 mach_sys_task_for_pid(l, v, retval)
656 struct lwp *l;
657 void *v;
658 register_t *retval;
659 {
660 struct mach_sys_task_for_pid_args /* {
661 syscallarg(mach_port_t) target_tport;
662 syscallarg(int) pid;
663 syscallarg(mach_port_t) *t;
664 } */ *uap = v;
665 struct mach_right *mr;
666 struct mach_emuldata *med;
667 struct proc *p = l->l_proc;
668 struct proc *t;
669 int error;
670
671 /*
672 * target_tport is used because the task may be on
673 * a different host. (target_tport, pid) is unique.
674 * We don't support multiple-host configuration
675 * yet, so this parameter should be useless.
676 * However, we still validate it.
677 */
678 if ((mr = mach_right_check(SCARG(uap, target_tport),
679 l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL)
680 return EPERM;
681
682 if ((t = pfind(SCARG(uap, pid))) == NULL)
683 return ESRCH;
684
685 /* Allowed only if the UID match, if setuid, or if superuser */
686 if ((t->p_cred->p_ruid != p->p_cred->p_ruid ||
687 ISSET(t->p_flag, P_SUGID)) &&
688 (error = suser(p->p_ucred, &p->p_acflag)) != 0)
689 return (error);
690
691 /* This will only work on a Mach process */
692 if ((t->p_emul != &emul_mach) &&
693 #ifdef COMPAT_DARWIN
694 (t->p_emul != &emul_darwin) &&
695 #endif
696 1)
697 return EINVAL;
698
699 med = t->p_emuldata;
700
701 if ((mr = mach_right_get(med->med_kernel, l,
702 MACH_PORT_TYPE_SEND, 0)) == NULL)
703 return EINVAL;
704
705 if ((error = copyout(&mr->mr_name, SCARG(uap, t),
706 sizeof(mr->mr_name))) != 0)
707 return error;
708
709 return 0;
710 }
711
Cache object: 508c31c30e7f1ef29e2fd523c8e0aaa5
|