1 /* $NetBSD: mach_task.c,v 1.70 2008/04/24 18:39:23 ad Exp $ */
4 * Copyright (c) 2002-2003, 2008 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
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>
40 #include <sys/systm.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>
63 #include <compat/darwin/darwin_exec.h>
66 #define ISSET(t, f) ((t) & (f))
69 update_exception_port(struct mach_emuldata
*, int exc
, struct mach_port
*);
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);
89 case MACH_TASK_HOST_PORT
:
90 mr
= mach_right_get(med
->med_host
, l
, MACH_PORT_TYPE_SEND
, 0);
93 case MACH_TASK_BOOTSTRAP_PORT
:
94 mr
= mach_right_get(med
->med_bootstrap
,
95 l
, MACH_PORT_TYPE_SEND
, 0);
98 case MACH_TASK_WIRED_LEDGER_PORT
:
99 case MACH_TASK_PAGED_LEDGER_PORT
:
101 uprintf("mach_task_get_special_port(): unimpl. port %d\n",
102 req
->req_which_port
);
103 return mach_msg_error(args
, EINVAL
);
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
);
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];
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...
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
);
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
;
179 struct mach_right
*mr
;
180 struct mach_port
*mp
;
181 struct mach_emuldata
*med
;
183 mn
= req
->req_special_port
.name
;
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
);
207 case MACH_TASK_HOST_PORT
:
209 med
->med_host
= mr
->mr_port
;
210 if (mr
->mr_port
!= NULL
)
211 MACH_PORT_REF(mr
->mr_port
);
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
);
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
;
232 printf("*** New bootstrap port %p, "
235 mach_bootstrap_port
->mp_recv
,
236 mach_bootstrap_port
->mp_recv
->mr_sethead
);
237 #endif /* DEBUG_DARWIN */
240 #endif /* COMPAT_DARWIN */
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
);
253 mach_set_trailer(rep
, *msglen
);
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
;
268 struct mach_emuldata
*med
;
269 struct mach_lwp_emuldata
*mle
;
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
);
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
);
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
;
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
;
327 for (i
= 0; i
<= MACH_EXC_MAX
; i
++) {
328 if (med
->med_exc
[i
] == NULL
)
331 if (med
->med_exc
[i
]->mp_datatype
!= MACH_MP_EXC_INFO
) {
333 printf("Exception port without mach_exc_info\n");
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
;
350 *msglen
= sizeof(*rep
);
351 mach_set_trailer(rep
, *msglen
);
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
;
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
;
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
);
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");
391 mei
= malloc(sizeof(*mei
), M_EMULDATA
, M_WAITOK
);
392 mei
->mei_flavor
= req
->req_flavor
;
393 mei
->mei_behavior
= req
->req_behavior
;
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
);
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
);
427 *msglen
= sizeof(*rep
);
428 mach_set_header(rep
, req
, *msglen
);
432 mach_set_trailer(rep
, *msglen
);
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
;
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
;
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
);
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
);
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
;
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
);
496 /* XXX a few statistics missing here */
497 case MACH_TASK_EVENTS_INFO
: {
498 struct mach_task_events_info
*mtei
;
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
);
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
);
525 uprintf("mach_task_info: unsupported flavor %d\n",
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
);
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
;
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
) {
562 return mach_msg_error(args
, 0);
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
);
577 mach_set_trailer(rep
, *msglen
);
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 */
595 if (med
->med_suspend
> 0)
596 return mach_msg_error(args
, 0); /* XXX error code */
599 /* XXX We should also wake up the stopped thread... */
601 printf("resuming pid %d\n", tp
->p_pid
);
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
);
614 mach_set_trailer(rep
, *msglen
);
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
;
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
);
645 mach_sys_task_for_pid(struct lwp
*l
, const struct mach_sys_task_for_pid_args
*uap
, register_t
*retval
)
648 syscallarg(mach_port_t) target_tport;
650 syscallarg(mach_port_t) *t;
652 struct mach_right
*mr
;
653 struct mach_emuldata
*med
;
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
)
668 if ((t
= pfind(SCARG(uap
, pid
))) == NULL
)
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)
677 /* This will only work on a Mach process */
678 if ((t
->p_emul
!= &emul_mach
) &&
680 (t
->p_emul
!= &emul_darwin
) &&
687 if ((mr
= mach_right_get(med
->med_kernel
, l
,
688 MACH_PORT_TYPE_SEND
, 0)) == NULL
)
691 if ((error
= copyout(&mr
->mr_name
, SCARG(uap
, t
),
692 sizeof(mr
->mr_name
))) != 0)