Sync usage with man page.
[netbsd-mini2440.git] / sys / compat / mach / mach_task.c
blob64e72f45679c0a8b36c0eedbe905273aea717a00
1 /* $NetBSD: mach_task.c,v 1.70 2008/04/24 18:39:23 ad Exp $ */
3 /*-
4 * Copyright (c) 2002-2003, 2008 The NetBSD Foundation, Inc.
5 * All rights reserved.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Emmanuel Dreyfus
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.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
32 #include "opt_compat_darwin.h"
34 #include <sys/cdefs.h>
35 __KERNEL_RCSID(0, "$NetBSD: mach_task.c,v 1.70 2008/04/24 18:39:23 ad Exp $");
37 #include <sys/types.h>
38 #include <sys/param.h>
39 #include <sys/exec.h>
40 #include <sys/systm.h>
41 #include <sys/proc.h>
42 #include <sys/ktrace.h>
43 #include <sys/resourcevar.h>
44 #include <sys/malloc.h>
45 #include <sys/mount.h>
46 #include <sys/syscallargs.h>
47 #include <sys/kauth.h>
49 #include <uvm/uvm_extern.h>
50 #include <uvm/uvm_param.h>
52 #include <compat/mach/mach_types.h>
53 #include <compat/mach/mach_message.h>
54 #include <compat/mach/mach_clock.h>
55 #include <compat/mach/mach_errno.h>
56 #include <compat/mach/mach_exec.h>
57 #include <compat/mach/mach_port.h>
58 #include <compat/mach/mach_task.h>
59 #include <compat/mach/mach_services.h>
60 #include <compat/mach/mach_syscallargs.h>
62 #ifdef COMPAT_DARWIN
63 #include <compat/darwin/darwin_exec.h>
64 #endif
66 #define ISSET(t, f) ((t) & (f))
68 static void
69 update_exception_port(struct mach_emuldata *, int exc, struct mach_port *);
71 int
72 mach_task_get_special_port(struct mach_trap_args *args)
74 mach_task_get_special_port_request_t *req = args->smsg;
75 mach_task_get_special_port_reply_t *rep = args->rmsg;
76 size_t *msglen = args->rsize;
77 struct lwp *l = args->l;
78 struct lwp *tl = args->tl;
79 struct mach_emuldata *med;
80 struct mach_right *mr;
82 med = (struct mach_emuldata *)tl->l_proc->p_emuldata;
84 switch (req->req_which_port) {
85 case MACH_TASK_KERNEL_PORT:
86 mr = mach_right_get(med->med_kernel, l, MACH_PORT_TYPE_SEND, 0);
87 break;
89 case MACH_TASK_HOST_PORT:
90 mr = mach_right_get(med->med_host, l, MACH_PORT_TYPE_SEND, 0);
91 break;
93 case MACH_TASK_BOOTSTRAP_PORT:
94 mr = mach_right_get(med->med_bootstrap,
95 l, MACH_PORT_TYPE_SEND, 0);
96 break;
98 case MACH_TASK_WIRED_LEDGER_PORT:
99 case MACH_TASK_PAGED_LEDGER_PORT:
100 default:
101 uprintf("mach_task_get_special_port(): unimpl. port %d\n",
102 req->req_which_port);
103 return mach_msg_error(args, EINVAL);
104 break;
107 *msglen = sizeof(*rep);
108 mach_set_header(rep, req, *msglen);
109 mach_add_port_desc(rep, mr->mr_name);
110 mach_set_trailer(rep, *msglen);
112 return 0;
116 mach_ports_lookup(struct mach_trap_args *args)
118 mach_ports_lookup_request_t *req = args->smsg;
119 mach_ports_lookup_reply_t *rep = args->rmsg;
120 size_t *msglen = args->rsize;
121 struct lwp *l = args->l;
122 struct lwp *tl = args->tl;
123 struct mach_emuldata *med;
124 struct mach_right *mr;
125 mach_port_name_t mnp[7];
126 void *uaddr;
127 int error;
128 int count;
131 * This is some out of band data sent with the reply. In the
132 * encountered situation, the out of band data has always been null
133 * filled. We have to see more of this in order to fully understand
134 * how this trap works.
136 med = (struct mach_emuldata *)tl->l_proc->p_emuldata;
137 mnp[0] = (mach_port_name_t)MACH_PORT_DEAD;
138 mnp[3] = (mach_port_name_t)MACH_PORT_DEAD;
139 mnp[5] = (mach_port_name_t)MACH_PORT_DEAD;
140 mnp[6] = (mach_port_name_t)MACH_PORT_DEAD;
142 mr = mach_right_get(med->med_kernel, l, MACH_PORT_TYPE_SEND, 0);
143 mnp[MACH_TASK_KERNEL_PORT] = mr->mr_name;
144 mr = mach_right_get(med->med_host, l, MACH_PORT_TYPE_SEND, 0);
145 mnp[MACH_TASK_HOST_PORT] = mr->mr_name;
146 mr = mach_right_get(med->med_bootstrap, l, MACH_PORT_TYPE_SEND, 0);
147 mnp[MACH_TASK_BOOTSTRAP_PORT] = mr->mr_name;
150 * On Darwin, the data seems always null...
152 uaddr = NULL;
153 if ((error = mach_ool_copyout(l, &mnp[0],
154 &uaddr, sizeof(mnp), MACH_OOL_TRACE)) != 0)
155 return mach_msg_error(args, error);
157 count = 3; /* XXX Shouldn't this be 7? */
159 *msglen = sizeof(*rep);
160 mach_set_header(rep, req, *msglen);
161 mach_add_ool_ports_desc(rep, uaddr, count);
163 rep->rep_init_port_set_count = count;
165 mach_set_trailer(rep, *msglen);
167 return 0;
171 mach_task_set_special_port(struct mach_trap_args *args)
173 mach_task_set_special_port_request_t *req = args->smsg;
174 mach_task_set_special_port_reply_t *rep = args->rmsg;
175 size_t *msglen = args->rsize;
176 struct lwp *l = args->l;
177 struct lwp *tl = args->tl;
178 mach_port_t mn;
179 struct mach_right *mr;
180 struct mach_port *mp;
181 struct mach_emuldata *med;
183 mn = req->req_special_port.name;
185 /* Null port ? */
186 if (mn == 0)
187 return mach_msg_error(args, 0);
189 /* Does the inserted port exists? */
190 if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == 0)
191 return mach_msg_error(args, EPERM);
193 if (mr->mr_type == MACH_PORT_TYPE_DEAD_NAME)
194 return mach_msg_error(args, EINVAL);
196 med = (struct mach_emuldata *)tl->l_proc->p_emuldata;
198 switch (req->req_which_port) {
199 case MACH_TASK_KERNEL_PORT:
200 mp = med->med_kernel;
201 med->med_kernel = mr->mr_port;
202 if (mr->mr_port != NULL)
203 MACH_PORT_REF(mr->mr_port);
204 MACH_PORT_UNREF(mp);
205 break;
207 case MACH_TASK_HOST_PORT:
208 mp = med->med_host;
209 med->med_host = mr->mr_port;
210 if (mr->mr_port != NULL)
211 MACH_PORT_REF(mr->mr_port);
212 MACH_PORT_UNREF(mp);
213 break;
215 case MACH_TASK_BOOTSTRAP_PORT:
216 mp = med->med_bootstrap;
217 med->med_bootstrap = mr->mr_port;
218 if (mr->mr_port != NULL)
219 MACH_PORT_REF(mr->mr_port);
220 MACH_PORT_UNREF(mp);
221 #ifdef COMPAT_DARWIN
223 * mach_init sets the bootstrap port for any new process.
226 struct darwin_emuldata *ded;
228 ded = tl->l_proc->p_emuldata;
229 if (ded->ded_fakepid == 1) {
230 mach_bootstrap_port = med->med_bootstrap;
231 #ifdef DEBUG_DARWIN
232 printf("*** New bootstrap port %p, "
233 "recv %p [%p]\n",
234 mach_bootstrap_port,
235 mach_bootstrap_port->mp_recv,
236 mach_bootstrap_port->mp_recv->mr_sethead);
237 #endif /* DEBUG_DARWIN */
240 #endif /* COMPAT_DARWIN */
241 break;
243 default:
244 uprintf("mach_task_set_special_port: unimplemented port %d\n",
245 req->req_which_port);
248 *msglen = sizeof(*rep);
249 mach_set_header(rep, req, *msglen);
251 rep->rep_retval = 0;
253 mach_set_trailer(rep, *msglen);
255 return 0;
259 mach_task_threads(struct mach_trap_args *args)
261 mach_task_threads_request_t *req = args->smsg;
262 mach_task_threads_reply_t *rep = args->rmsg;
263 size_t *msglen = args->rsize;
264 struct lwp *l = args->l;
265 struct lwp *tl = args->tl;
266 struct proc *tp = tl->l_proc;
267 struct lwp *cl;
268 struct mach_emuldata *med;
269 struct mach_lwp_emuldata *mle;
270 int error;
271 void *uaddr;
272 size_t size;
273 int i = 0;
274 struct mach_right *mr;
275 mach_port_name_t *mnp;
277 med = tp->p_emuldata;
278 size = tp->p_nlwps * sizeof(*mnp);
279 mnp = malloc(size, M_TEMP, M_WAITOK);
280 uaddr = NULL;
282 LIST_FOREACH(cl, &tp->p_lwps, l_sibling) {
283 mle = cl->l_emuldata;
284 mr = mach_right_get(mle->mle_kernel, l, MACH_PORT_TYPE_SEND, 0);
285 mnp[i++] = mr->mr_name;
288 /* This will free mnp */
289 if ((error = mach_ool_copyout(l, mnp, &uaddr,
290 size, MACH_OOL_TRACE|MACH_OOL_FREE)) != 0)
291 return mach_msg_error(args, error);
293 *msglen = sizeof(*rep);
294 mach_set_header(rep, req, *msglen);
295 mach_add_ool_ports_desc(rep, uaddr, tp->p_nlwps);
297 rep->rep_count = tp->p_nlwps;
299 mach_set_trailer(rep, *msglen);
301 return 0;
305 mach_task_get_exception_ports(struct mach_trap_args *args)
307 mach_task_get_exception_ports_request_t *req = args->smsg;
308 mach_task_get_exception_ports_reply_t *rep = args->rmsg;
309 struct lwp *l = args->l;
310 struct lwp *tl = args->tl;
311 size_t *msglen = args->rsize;
312 struct mach_emuldata *med;
313 struct mach_right *mr;
314 struct mach_exc_info *mei;
315 int i, j, count;
317 med = tl->l_proc->p_emuldata;
319 /* It always returns an array of 32 ports even if only 9 can be used */
320 count = sizeof(rep->rep_old_handler) / sizeof(rep->rep_old_handler[0]);
322 mach_set_header(rep, req, *msglen);
324 rep->rep_masks_count = count;
326 j = 0;
327 for (i = 0; i <= MACH_EXC_MAX; i++) {
328 if (med->med_exc[i] == NULL)
329 continue;
331 if (med->med_exc[i]->mp_datatype != MACH_MP_EXC_INFO) {
332 #ifdef DIAGNOSTIC
333 printf("Exception port without mach_exc_info\n");
334 #endif
335 continue;
337 mei = med->med_exc[i]->mp_data;
339 mr = mach_right_get(med->med_exc[i], l, MACH_PORT_TYPE_SEND, 0);
341 mach_add_port_desc(rep, mr->mr_name);
343 rep->rep_masks[j] = 1 << i;
344 rep->rep_old_behaviors[j] = mei->mei_behavior;
345 rep->rep_old_flavors[j] = mei->mei_flavor;
347 j++;
350 *msglen = sizeof(*rep);
351 mach_set_trailer(rep, *msglen);
353 return 0;
356 static void
357 update_exception_port(struct mach_emuldata *med, int exc, struct mach_port *mp)
359 if (med->med_exc[exc] != NULL)
360 MACH_PORT_UNREF(med->med_exc[exc]);
361 med->med_exc[exc] = mp;
362 MACH_PORT_REF(mp);
364 return;
368 mach_task_set_exception_ports(struct mach_trap_args *args)
370 mach_task_set_exception_ports_request_t *req = args->smsg;
371 mach_task_set_exception_ports_reply_t *rep = args->rmsg;
372 struct lwp *l = args->l;
373 struct lwp *tl = args->tl;
374 size_t *msglen = args->rsize;
375 struct mach_emuldata *med;
376 mach_port_name_t mn;
377 struct mach_right *mr;
378 struct mach_port *mp;
379 struct mach_exc_info *mei;
381 mn = req->req_new_port.name;
382 if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_SEND)) == 0)
383 return mach_msg_error(args, EPERM);
385 mp = mr->mr_port;
386 #ifdef DIAGNOSTIC
387 if ((mp->mp_datatype != MACH_MP_EXC_INFO) &&
388 (mp->mp_datatype != MACH_MP_NONE))
389 printf("mach_task_set_exception_ports: data exists\n");
390 #endif
391 mei = malloc(sizeof(*mei), M_EMULDATA, M_WAITOK);
392 mei->mei_flavor = req->req_flavor;
393 mei->mei_behavior = req->req_behavior;
395 mp->mp_data = mei;
396 mp->mp_flags |= MACH_MP_DATA_ALLOCATED;
397 mp->mp_datatype = MACH_MP_EXC_INFO;
399 med = tl->l_proc->p_emuldata;
400 if (req->req_mask & MACH_EXC_MASK_BAD_ACCESS)
401 update_exception_port(med, MACH_EXC_BAD_ACCESS, mp);
402 if (req->req_mask & MACH_EXC_MASK_BAD_INSTRUCTION)
403 update_exception_port(med, MACH_EXC_BAD_INSTRUCTION, mp);
404 if (req->req_mask & MACH_EXC_MASK_ARITHMETIC)
405 update_exception_port(med, MACH_EXC_ARITHMETIC, mp);
406 if (req->req_mask & MACH_EXC_MASK_EMULATION)
407 update_exception_port(med, MACH_EXC_EMULATION, mp);
408 if (req->req_mask & MACH_EXC_MASK_SOFTWARE)
409 update_exception_port(med, MACH_EXC_SOFTWARE, mp);
410 if (req->req_mask & MACH_EXC_MASK_BREAKPOINT)
411 update_exception_port(med, MACH_EXC_BREAKPOINT, mp);
412 if (req->req_mask & MACH_EXC_MASK_SYSCALL)
413 update_exception_port(med, MACH_EXC_SYSCALL, mp);
414 if (req->req_mask & MACH_EXC_MASK_MACH_SYSCALL)
415 update_exception_port(med, MACH_EXC_MACH_SYSCALL, mp);
416 if (req->req_mask & MACH_EXC_MASK_RPC_ALERT)
417 update_exception_port(med, MACH_EXC_RPC_ALERT, mp);
419 #ifdef DEBUG_MACH
420 if (req->req_mask & (MACH_EXC_ARITHMETIC |
421 MACH_EXC_EMULATION | MACH_EXC_MASK_SYSCALL |
422 MACH_EXC_MASK_MACH_SYSCALL | MACH_EXC_RPC_ALERT))
423 printf("mach_set_exception_ports: some exceptions are "
424 "not supported (mask %x)\n", req->req_mask);
425 #endif
427 *msglen = sizeof(*rep);
428 mach_set_header(rep, req, *msglen);
430 rep->rep_retval = 0;
432 mach_set_trailer(rep, *msglen);
434 return 0;
438 mach_task_info(struct mach_trap_args *args)
440 mach_task_info_request_t *req = args->smsg;
441 mach_task_info_reply_t *rep = args->rmsg;
442 struct lwp *tl = args->tl;
443 size_t *msglen = args->rsize;
444 int count;
445 struct proc *tp = tl->l_proc;
447 switch(req->req_flavor) {
448 case MACH_TASK_BASIC_INFO: {
449 struct mach_task_basic_info *mtbi;
450 struct rusage ru;
452 count = sizeof(*mtbi) / sizeof(rep->rep_info[0]);
453 if (req->req_count < count)
454 return mach_msg_error(args, ENOBUFS);
456 ru = tp->p_stats->p_ru;
457 mtbi = (struct mach_task_basic_info *)&rep->rep_info[0];
458 mutex_enter(tp->p_lock);
459 rulwps(tp, &ru);
460 mutex_exit(tp->p_lock);
462 mtbi->mtbi_suspend_count = ru.ru_nvcsw + ru.ru_nivcsw;
463 mtbi->mtbi_virtual_size = ru.ru_ixrss;
464 mtbi->mtbi_resident_size = ru.ru_maxrss;
465 mtbi->mtbi_user_time.seconds = ru.ru_utime.tv_sec;
466 mtbi->mtbi_user_time.microseconds = ru.ru_utime.tv_usec;
467 mtbi->mtbi_system_time.seconds = ru.ru_stime.tv_sec;
468 mtbi->mtbi_system_time.microseconds = ru.ru_stime.tv_usec;
469 mtbi->mtbi_policy = 0;
471 *msglen = sizeof(*rep) - sizeof(rep->rep_info) + sizeof(*mtbi);
472 break;
475 /* XXX this is supposed to be about threads, not processes... */
476 case MACH_TASK_THREAD_TIMES_INFO: {
477 struct mach_task_thread_times_info *mttti;
478 struct rusage ru;
480 count = sizeof(*mttti) / sizeof(rep->rep_info[0]);
481 if (req->req_count < count)
482 return mach_msg_error(args, ENOBUFS);
484 ru = tp->p_stats->p_ru;
485 mttti = (struct mach_task_thread_times_info *)&rep->rep_info[0];
487 mttti->mttti_user_time.seconds = ru.ru_utime.tv_sec;
488 mttti->mttti_user_time.microseconds = ru.ru_utime.tv_usec;
489 mttti->mttti_system_time.seconds = ru.ru_stime.tv_sec;
490 mttti->mttti_system_time.microseconds = ru.ru_stime.tv_usec;
492 *msglen = sizeof(*rep) - sizeof(rep->rep_info) + sizeof(*mttti);
493 break;
496 /* XXX a few statistics missing here */
497 case MACH_TASK_EVENTS_INFO: {
498 struct mach_task_events_info *mtei;
499 struct rusage ru;
501 count = sizeof(*mtei) / sizeof(rep->rep_info[0]);
502 if (req->req_count < count)
503 return mach_msg_error(args, ENOBUFS);
505 mtei = (struct mach_task_events_info *)&rep->rep_info[0];
506 ru = tp->p_stats->p_ru;
507 mutex_enter(tp->p_lock);
508 rulwps(tp, &ru);
509 mutex_exit(tp->p_lock);
511 mtei->mtei_faults = ru.ru_majflt;
512 mtei->mtei_pageins = ru.ru_minflt;
513 mtei->mtei_cow_faults = 0; /* XXX */
514 mtei->mtei_message_sent = ru.ru_msgsnd;
515 mtei->mtei_message_received = ru.ru_msgrcv;
516 mtei->mtei_syscalls_mach = 0; /* XXX */
517 mtei->mtei_syscalls_unix = 0; /* XXX */
518 mtei->mtei_csw = 0; /* XXX */
520 *msglen = sizeof(*rep) - sizeof(rep->rep_info) + sizeof(*mtei);
521 break;
524 default:
525 uprintf("mach_task_info: unsupported flavor %d\n",
526 req->req_flavor);
527 return mach_msg_error(args, EINVAL);
530 mach_set_header(rep, req, *msglen);
532 rep->rep_count = count;
534 mach_set_trailer(rep, *msglen);
536 return 0;
540 mach_task_suspend(struct mach_trap_args *args)
542 mach_task_suspend_request_t *req = args->smsg;
543 mach_task_suspend_reply_t *rep = args->rmsg;
544 size_t *msglen = args->rsize;
545 struct lwp *tl = args->tl;
546 struct lwp *lp;
547 struct mach_emuldata *med;
548 struct proc *tp = tl->l_proc;
550 med = tp->p_emuldata;
551 med->med_suspend++; /* XXX Mach also has a per thread semaphore */
553 LIST_FOREACH(lp, &tp->p_lwps, l_sibling) {
554 switch(lp->l_stat) {
555 case LSONPROC:
556 case LSRUN:
557 case LSSLEEP:
558 case LSSUSPENDED:
559 case LSZOMB:
560 break;
561 default:
562 return mach_msg_error(args, 0);
563 break;
566 mutex_enter(proc_lock);
567 mutex_enter(tp->p_lock);
568 proc_stop(tp, 0, SIGSTOP);
569 mutex_enter(tp->p_lock);
570 mutex_enter(proc_lock);
572 *msglen = sizeof(*rep);
573 mach_set_header(rep, req, *msglen);
575 rep->rep_retval = 0;
577 mach_set_trailer(rep, *msglen);
579 return 0;
583 mach_task_resume(struct mach_trap_args *args)
585 mach_task_resume_request_t *req = args->smsg;
586 mach_task_resume_reply_t *rep = args->rmsg;
587 size_t *msglen = args->rsize;
588 struct lwp *tl = args->tl;
589 struct mach_emuldata *med;
590 struct proc *tp = tl->l_proc;
592 med = tp->p_emuldata;
593 med->med_suspend--; /* XXX Mach also has a per thread semaphore */
594 #if 0
595 if (med->med_suspend > 0)
596 return mach_msg_error(args, 0); /* XXX error code */
597 #endif
599 /* XXX We should also wake up the stopped thread... */
600 #ifdef DEBUG_MACH
601 printf("resuming pid %d\n", tp->p_pid);
602 #endif
603 mutex_enter(proc_lock);
604 mutex_enter(tp->p_lock);
605 (void)proc_unstop(tp);
606 mutex_enter(tp->p_lock);
607 mutex_enter(proc_lock);
609 *msglen = sizeof(*rep);
610 mach_set_header(rep, req, *msglen);
612 rep->rep_retval = 0;
614 mach_set_trailer(rep, *msglen);
616 return 0;
620 mach_task_terminate(struct mach_trap_args *args)
622 mach_task_resume_request_t *req = args->smsg;
623 mach_task_resume_reply_t *rep = args->rmsg;
624 size_t *msglen = args->rsize;
625 struct lwp *tl = args->tl;
626 struct sys_exit_args cup;
627 register_t retval;
628 int error;
631 SCARG(&cup, rval) = 0;
632 error = sys_exit(tl, &cup, &retval);
634 *msglen = sizeof(*rep);
635 mach_set_header(rep, req, *msglen);
637 rep->rep_retval = native_to_mach_errno[error];
639 mach_set_trailer(rep, *msglen);
641 return 0;
645 mach_sys_task_for_pid(struct lwp *l, const struct mach_sys_task_for_pid_args *uap, register_t *retval)
647 /* {
648 syscallarg(mach_port_t) target_tport;
649 syscallarg(int) pid;
650 syscallarg(mach_port_t) *t;
651 } */
652 struct mach_right *mr;
653 struct mach_emuldata *med;
654 struct proc *t;
655 int error;
658 * target_tport is used because the task may be on
659 * a different host. (target_tport, pid) is unique.
660 * We don't support multiple-host configuration
661 * yet, so this parameter should be useless.
662 * However, we still validate it.
664 if ((mr = mach_right_check(SCARG(uap, target_tport),
665 l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL)
666 return EPERM;
668 if ((t = pfind(SCARG(uap, pid))) == NULL)
669 return ESRCH;
671 /* Allowed only if the UID match, if setuid, or if superuser */
672 if ((kauth_cred_getuid(t->p_cred) != kauth_cred_getuid(l->l_cred) ||
673 ISSET(t->p_flag, PK_SUGID)) && (error = kauth_authorize_generic(l->l_cred,
674 KAUTH_GENERIC_ISSUSER, NULL)) != 0)
675 return (error);
677 /* This will only work on a Mach process */
678 if ((t->p_emul != &emul_mach) &&
679 #ifdef COMPAT_DARWIN
680 (t->p_emul != &emul_darwin) &&
681 #endif
683 return EINVAL;
685 med = t->p_emuldata;
687 if ((mr = mach_right_get(med->med_kernel, l,
688 MACH_PORT_TYPE_SEND, 0)) == NULL)
689 return EINVAL;
691 if ((error = copyout(&mr->mr_name, SCARG(uap, t),
692 sizeof(mr->mr_name))) != 0)
693 return error;
695 return 0;