2 * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/kernel.h>
36 #include <sys/malloc.h>
37 #include <sys/proc_internal.h>
38 #include <sys/kauth.h>
39 #include <sys/file_internal.h>
40 #include <sys/vnode_internal.h>
41 #include <sys/unistd.h>
43 #include <sys/ioctl.h>
44 #include <sys/namei.h>
46 #include <sys/disklabel.h>
48 #include <sys/sysctl.h>
50 #include <sys/aio_kern.h>
52 #include <bsm/audit_kernel.h>
54 #include <mach/machine.h>
55 #include <mach/mach_types.h>
56 #include <mach/vm_param.h>
57 #include <kern/task.h>
58 #include <kern/lock.h>
59 #include <kern/kalloc.h>
60 #include <vm/vm_kern.h>
61 #include <vm/vm_map.h>
62 #include <mach/host_info.h>
63 #include <mach/task_info.h>
64 #include <mach/thread_info.h>
65 #include <mach/vm_region.h>
67 #include <sys/mount_internal.h>
68 #include <sys/proc_info.h>
69 #include <sys/bsdtask_info.h>
70 #include <sys/kdebug.h>
71 #include <sys/sysproto.h>
72 #include <sys/msgbuf.h>
74 #include <sys/msgbuf.h>
76 #include <machine/machine_routines.h>
78 #include <vm/vm_protos.h>
86 int proc_info_internal(int callnum
, int pid
, int flavor
, uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, register_t
* retval
);
88 /* protos for proc_info calls */
89 int proc_listpids(uint32_t type
, uint32_t tyoneinfo
, user_addr_t buffer
, uint32_t buffersize
, register_t
* retval
);
90 int proc_pidinfo(int pid
, int flavor
, uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, register_t
* retval
);
91 int proc_pidfdinfo(int pid
, int flavor
,int fd
, user_addr_t buffer
, uint32_t buffersize
, register_t
* retval
);
92 int proc_kernmsgbuf(user_addr_t buffer
, uint32_t buffersize
, register_t
* retval
);
94 /* protos for procpidinfo calls */
95 int proc_pidfdlist(proc_t p
, user_addr_t buffer
, uint32_t buffersize
, register_t
*retval
);
96 int proc_pidbsdinfo(proc_t p
, struct proc_bsdinfo
*pbsd
);
97 int proc_pidtaskinfo(proc_t p
, struct proc_taskinfo
*ptinfo
);
98 int proc_pidallinfo(proc_t p
, int flavor
, uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, register_t
*retval
);
99 int proc_pidthreadinfo(proc_t p
, uint64_t arg
, struct proc_threadinfo
*pthinfo
);
100 int proc_pidthreadpathinfo(proc_t p
, uint64_t arg
, struct proc_threadwithpathinfo
*pinfo
);
101 int proc_pidlistthreads(proc_t p
, user_addr_t buffer
, uint32_t buffersize
, register_t
*retval
);
102 int proc_pidregioninfo(proc_t p
, uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, register_t
*retval
);
103 int proc_pidregionpathinfo(proc_t p
, uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, register_t
*retval
);
104 int proc_pidvnodepathinfo(proc_t p
, uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, register_t
*retval
);
105 int proc_pidpathinfo(proc_t p
, uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, register_t
*retval
);
108 /* protos for proc_pidfdinfo calls */
109 int pid_vnodeinfo(vnode_t vp
, uint32_t vid
, struct fileproc
* fp
, int closeonexec
, user_addr_t buffer
, uint32_t buffersize
, register_t
* retval
);
110 int pid_vnodeinfopath(vnode_t vp
, uint32_t vid
, struct fileproc
* fp
, int closeonexec
, user_addr_t buffer
, uint32_t buffersize
, register_t
* retval
);
111 int pid_socketinfo(socket_t so
, struct fileproc
*fp
, int closeonexec
, user_addr_t buffer
, uint32_t buffersize
, register_t
* retval
);
112 int pid_pseminfo(struct psemnode
* psem
, struct fileproc
* fp
, int closeonexec
, user_addr_t buffer
, uint32_t buffersize
, register_t
* retval
);
113 int pid_pshminfo(struct pshmnode
* pshm
, struct fileproc
* fp
, int closeonexec
, user_addr_t buffer
, uint32_t buffersize
, register_t
* retval
);
114 int pid_pipeinfo(struct pipe
* p
, struct fileproc
* fp
, int closeonexec
, user_addr_t buffer
, uint32_t buffersize
, register_t
* retval
);
115 int pid_kqueueinfo(struct kqueue
* kq
, struct fileproc
* fp
, int closeonexec
, user_addr_t buffer
, uint32_t buffersize
, register_t
* retval
);
116 int pid_atalkinfo(struct atalk
* at
, struct fileproc
* fp
, int closeonexec
, user_addr_t buffer
, uint32_t buffersize
, register_t
* retval
);
119 /* protos for misc */
121 int fill_vnodeinfo(vnode_t vp
, struct vnode_info
*vinfo
);
122 void fill_fileinfo(struct fileproc
* fp
, int closeonexec
, struct proc_fileinfo
* finfo
);
123 static int proc_security_policy(proc_t p
);
124 static void munge_vinfo_stat(struct stat64
*sbp
, struct vinfo_stat
*vsbp
);
126 /***************************** proc_info ********************/
129 proc_info(__unused
struct proc
*p
, struct proc_info_args
* uap
, register_t
*retval
)
131 return(proc_info_internal(uap
->callnum
, uap
->pid
, uap
->flavor
, uap
->arg
, uap
->buffer
, uap
->buffersize
, retval
));
136 proc_info_internal(int callnum
, int pid
, int flavor
, uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, register_t
* retval
)
140 case 1: /* proc_listpids */
141 /* pid contains type and flavor contains typeinfo */
142 return(proc_listpids(pid
, flavor
, buffer
, buffersize
, retval
));
143 case 2: /* proc_pidinfo */
144 return(proc_pidinfo(pid
, flavor
, arg
, buffer
, buffersize
, retval
));
145 case 3: /* proc_pidfdinfo */
146 return(proc_pidfdinfo(pid
, flavor
, (int)arg
, buffer
, buffersize
, retval
));
147 case 4: /* proc_kernmsgbuf */
148 return(proc_kernmsgbuf(buffer
, buffersize
, retval
));
156 /******************* proc_listpids routine ****************/
158 proc_listpids(uint32_t type
, uint32_t typeinfo
, user_addr_t buffer
, uint32_t buffersize
, register_t
* retval
)
160 int numprocs
, wantpids
;
167 /* if the buffer is null, return num of procs */
168 if (buffer
== (user_addr_t
)0) {
169 *retval
= ((nprocs
+20) * sizeof(int));
173 if (buffersize
< sizeof(int)) {
176 wantpids
= buffersize
/sizeof(int);
177 numprocs
= nprocs
+20;
178 if (numprocs
> wantpids
)
181 kbuf
= (char *)kalloc((vm_size_t
)(numprocs
* sizeof(int)));
184 bzero(kbuf
, sizeof(int));
191 LIST_FOREACH(p
, &allproc
, p_list
) {
195 if (p
->p_pgrpid
!= (pid_t
)typeinfo
)
202 /* racy but list lock is held */
203 if ((p
->p_flag
& P_CONTROLT
) == 0 ||
204 (p
->p_pgrp
== NULL
) || (p
->p_pgrp
->pg_session
== NULL
) ||
205 p
->p_pgrp
->pg_session
->s_ttyp
== NULL
||
206 p
->p_pgrp
->pg_session
->s_ttyp
->t_dev
!= (dev_t
)typeinfo
)
210 if (p
->p_ucred
== NULL
)
213 kauth_cred_t my_cred
;
216 my_cred
= kauth_cred_proc_ref(p
);
217 uid
= kauth_cred_getuid(my_cred
);
218 kauth_cred_unref(&my_cred
);
219 if (uid
!= (uid_t
)typeinfo
)
224 if (p
->p_ucred
== NULL
)
227 kauth_cred_t my_cred
;
230 my_cred
= kauth_cred_proc_ref(p
);
231 uid
= my_cred
->cr_ruid
;
232 kauth_cred_unref(&my_cred
);
233 if (uid
!= (uid_t
)typeinfo
)
242 /* Do we have permission to look into this ? */
243 if (proc_security_policy(p
) != 0) {
256 LIST_FOREACH(p
, &zombproc
, p_list
) {
268 error
= copyout((caddr_t
)ptr
, buffer
, n
* sizeof(int));
270 *retval
= (n
* sizeof(int));
271 kfree((void *)kbuf
, (vm_size_t
)(numprocs
* sizeof(int)));
277 /********************************** proc_pidinfo routines ********************************/
280 proc_pidfdlist(proc_t p
, user_addr_t buffer
, uint32_t buffersize
, register_t
*retval
)
284 struct proc_fdinfo
* pfd
;
285 struct fileproc
* fp
;
290 numfds
= p
->p_fd
->fd_nfiles
;
292 if (buffer
== (user_addr_t
) 0) {
294 *retval
= (numfds
* sizeof(struct proc_fdinfo
));
298 /* buffersize is big enough atleast for one struct */
299 needfds
= buffersize
/sizeof(struct proc_fdinfo
);
301 if (numfds
> needfds
)
304 kbuf
= (char *)kalloc((vm_size_t
)(numfds
* sizeof(struct proc_fdinfo
)));
307 bzero(kbuf
, numfds
* sizeof(struct proc_fdinfo
));
311 pfd
= (struct proc_fdinfo
*)kbuf
;
313 for (n
= 0; ((n
< numfds
) && (n
< p
->p_fd
->fd_nfiles
)); n
++) {
314 if (((fp
= p
->p_fd
->fd_ofiles
[n
]) != 0)
315 && ((p
->p_fd
->fd_ofileflags
[n
] & UF_RESERVED
) == 0)) {
317 pfd
->proc_fdtype
= fp
->f_fglob
->fg_type
;
324 error
= copyout(kbuf
, buffer
, count
* sizeof(struct proc_fdinfo
));
325 kfree((void *)kbuf
, (vm_size_t
)(numfds
* sizeof(struct proc_fdinfo
)));
327 *retval
= (count
* sizeof(struct proc_fdinfo
));
333 proc_pidbsdinfo(proc_t p
, struct proc_bsdinfo
* pbsd
)
335 register struct tty
*tp
;
336 struct session
*sessionp
= NULL
;
338 kauth_cred_t my_cred
;
341 sessionp
= proc_session(p
);
343 my_cred
= kauth_cred_proc_ref(p
);
344 bzero(pbsd
, sizeof(struct proc_bsdinfo
));
345 pbsd
->pbi_status
= p
->p_stat
;
346 pbsd
->pbi_xstatus
= p
->p_xstat
;
347 pbsd
->pbi_pid
= p
->p_pid
;
348 pbsd
->pbi_ppid
= p
->p_ppid
;
349 pbsd
->pbi_uid
= my_cred
->cr_uid
;
350 pbsd
->pbi_gid
= my_cred
->cr_gid
;
351 pbsd
->pbi_ruid
= my_cred
->cr_ruid
;
352 pbsd
->pbi_rgid
= my_cred
->cr_rgid
;
353 pbsd
->pbi_svuid
= my_cred
->cr_svuid
;
354 pbsd
->pbi_svgid
= my_cred
->cr_svgid
;
355 kauth_cred_unref(&my_cred
);
357 pbsd
->pbi_nice
= p
->p_nice
;
358 pbsd
->pbi_start
= p
->p_start
;
359 bcopy(&p
->p_comm
, &pbsd
->pbi_comm
[0], MAXCOMLEN
);
360 bcopy(&p
->p_name
, &pbsd
->pbi_name
[0], 2* MAXCOMLEN
);
363 if ((p
->p_flag
& P_SYSTEM
) == P_SYSTEM
)
364 pbsd
->pbi_flags
|= PROC_FLAG_SYSTEM
;
365 if ((p
->p_lflag
& P_LTRACED
) == P_LTRACED
)
366 pbsd
->pbi_flags
|= PROC_FLAG_TRACED
;
367 if ((p
->p_lflag
& P_LEXIT
) == P_LEXIT
)
368 pbsd
->pbi_flags
|= PROC_FLAG_INEXIT
;
369 if ((p
->p_lflag
& P_LPPWAIT
) == P_LPPWAIT
)
370 pbsd
->pbi_flags
|= PROC_FLAG_PPWAIT
;
371 if ((p
->p_flag
& P_LP64
) == P_LP64
)
372 pbsd
->pbi_flags
|= PROC_FLAG_LP64
;
373 if ((p
->p_flag
& P_CONTROLT
) == P_CONTROLT
)
374 pbsd
->pbi_flags
|= PROC_FLAG_CONTROLT
;
375 if ((p
->p_flag
& P_THCWD
) == P_THCWD
)
376 pbsd
->pbi_flags
|= PROC_FLAG_THCWD
;
378 if (SESS_LEADER(p
, sessionp
))
379 pbsd
->pbi_flags
|= PROC_FLAG_SLEADER
;
380 if ((sessionp
!= SESSION_NULL
) && sessionp
->s_ttyvp
)
381 pbsd
->pbi_flags
|= PROC_FLAG_CTTY
;
383 pbsd
->pbi_nfiles
= p
->p_fd
->fd_nfiles
;
384 if (pg
!= PGRP_NULL
) {
385 pbsd
->pbi_pgid
= p
->p_pgrpid
;
386 pbsd
->pbi_pjobc
= pg
->pg_jobc
;
387 if ((p
->p_flag
& P_CONTROLT
) && (sessionp
!= SESSION_NULL
) && (tp
= sessionp
->s_ttyp
)) {
388 pbsd
->e_tdev
= tp
->t_dev
;
389 pbsd
->e_tpgid
= sessionp
->s_ttypgrpid
;
392 if (sessionp
!= SESSION_NULL
)
393 session_rele(sessionp
);
402 proc_pidtaskinfo(proc_t p
, struct proc_taskinfo
* ptinfo
)
408 bzero(ptinfo
, sizeof(struct proc_taskinfo
));
409 fill_taskprocinfo(task
, (struct proc_taskinfo_internal
*)ptinfo
);
417 proc_pidthreadinfo(proc_t p
, uint64_t arg
, struct proc_threadinfo
*pthinfo
)
420 uint64_t threadaddr
= (uint64_t)arg
;
422 bzero(pthinfo
, sizeof(struct proc_threadinfo
));
424 error
= fill_taskthreadinfo(p
->task
, threadaddr
, (struct proc_threadinfo_internal
*)pthinfo
, NULL
, NULL
);
434 bsd_threadcdir(void * uth
, void *vptr
, int *vidp
)
436 struct uthread
* ut
= (struct uthread
*)uth
;
438 vnode_t
*vpp
= (vnode_t
*)vptr
;
452 proc_pidthreadpathinfo(proc_t p
, uint64_t arg
, struct proc_threadwithpathinfo
*pinfo
)
457 uint64_t threadaddr
= (uint64_t)arg
;
460 bzero(pinfo
, sizeof(struct proc_threadwithpathinfo
));
462 error
= fill_taskthreadinfo(p
->task
, threadaddr
, (struct proc_threadinfo_internal
*)&pinfo
->pt
, (void *)&vp
, &vid
);
466 if ((vp
!= NULLVP
) && ((vnode_getwithvid(vp
, vid
)) == 0)) {
467 error
= fill_vnodeinfo(vp
, &pinfo
->pvip
.vip_vi
) ;
470 vn_getpath(vp
, &pinfo
->pvip
.vip_path
[0], &count
);
471 pinfo
->pvip
.vip_path
[MAXPATHLEN
-1] = 0;
481 proc_pidlistthreads(proc_t p
, user_addr_t buffer
, uint32_t buffersize
, register_t
*retval
)
490 count
= buffersize
/(sizeof(uint64_t));
491 numthreads
= get_numthreads(p
->task
);
495 if (numthreads
> count
)
498 kbuf
= (void *)kalloc(numthreads
* sizeof(uint64_t));
501 bzero(kbuf
, numthreads
* sizeof(uint64_t));
503 ret
= fill_taskthreadlist(p
->task
, kbuf
, numthreads
);
505 error
= copyout(kbuf
, buffer
, ret
);
506 kfree(kbuf
, numthreads
* sizeof(uint64_t));
515 proc_pidregioninfo(proc_t p
, uint64_t arg
, user_addr_t buffer
, __unused
uint32_t buffersize
, register_t
*retval
)
517 struct proc_regioninfo preginfo
;
520 bzero(&preginfo
, sizeof(struct proc_regioninfo
));
521 ret
= fill_procregioninfo( p
->task
, arg
, (struct proc_regioninfo_internal
*)&preginfo
, (uint32_t *)0, (uint32_t *)0);
524 error
= copyout(&preginfo
, buffer
, sizeof(struct proc_regioninfo
));
526 *retval
= sizeof(struct proc_regioninfo
);
532 proc_pidregionpathinfo(proc_t p
, uint64_t arg
, user_addr_t buffer
, __unused
uint32_t buffersize
, register_t
*retval
)
534 struct proc_regionwithpathinfo preginfo
;
536 uint32_t vnodeaddr
= 0;
541 bzero(&preginfo
, sizeof(struct proc_regionwithpathinfo
));
543 ret
= fill_procregioninfo( p
->task
, arg
, (struct proc_regioninfo_internal
*)&preginfo
.prp_prinfo
, (uint32_t *)&vnodeaddr
, (uint32_t *)&vnodeid
);
547 vp
= (vnode_t
)vnodeaddr
;
548 if ((vnode_getwithvid(vp
, vnodeid
)) == 0) {
549 /* FILL THE VNODEINFO */
550 error
= fill_vnodeinfo(vp
, &preginfo
.prp_vip
.vip_vi
);
552 vn_getpath(vp
, &preginfo
.prp_vip
.vip_path
[0], &count
);
553 /* Always make sure it is null terminated */
554 preginfo
.prp_vip
.vip_path
[MAXPATHLEN
-1] = 0;
558 error
= copyout(&preginfo
, buffer
, sizeof(struct proc_regionwithpathinfo
));
560 *retval
= sizeof(struct proc_regionwithpathinfo
);
565 * Path is relative to current process directory; may different from current
569 proc_pidvnodepathinfo(proc_t p
, __unused
uint64_t arg
, user_addr_t buffer
, __unused
uint32_t buffersize
, register_t
*retval
)
571 struct proc_vnodepathinfo pvninfo
;
573 vnode_t vncdirvp
= NULLVP
;
575 vnode_t vnrdirvp
= NULLVP
;
579 bzero(&pvninfo
, sizeof(struct proc_vnodepathinfo
));
582 if (p
->p_fd
->fd_cdir
) {
583 vncdirvp
= p
->p_fd
->fd_cdir
;
584 vncdirid
= p
->p_fd
->fd_cdir
->v_id
;
586 if (p
->p_fd
->fd_rdir
) {
587 vnrdirvp
= p
->p_fd
->fd_rdir
;
588 vnrdirid
= p
->p_fd
->fd_rdir
->v_id
;
592 if (vncdirvp
!= NULLVP
) {
593 if ((error
= vnode_getwithvid(vncdirvp
, vncdirid
)) == 0) {
594 /* FILL THE VNODEINFO */
595 error
= fill_vnodeinfo(vncdirvp
, &pvninfo
.pvi_cdir
.vip_vi
);
598 vn_getpath(vncdirvp
, &pvninfo
.pvi_cdir
.vip_path
[0], &count
);
599 pvninfo
.pvi_cdir
.vip_path
[MAXPATHLEN
-1] = 0;
607 if ((error
== 0) && (vnrdirvp
!= NULLVP
)) {
608 if ((error
= vnode_getwithvid(vnrdirvp
, vnrdirid
)) == 0) {
609 /* FILL THE VNODEINFO */
610 error
= fill_vnodeinfo(vnrdirvp
, &pvninfo
.pvi_rdir
.vip_vi
);
613 vn_getpath(vnrdirvp
, &pvninfo
.pvi_rdir
.vip_path
[0], &count
);
614 pvninfo
.pvi_rdir
.vip_path
[MAXPATHLEN
-1] = 0;
622 error
= copyout(&pvninfo
, buffer
, sizeof(struct proc_vnodepathinfo
));
624 *retval
= sizeof(struct proc_vnodepathinfo
);
631 proc_pidpathinfo(proc_t p
, __unused
uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, __unused register_t
*retval
)
635 vnode_t nvp
= NULLVP
;
636 int len
= buffersize
;
644 buf
= (char *)kalloc(buffersize
);
649 vid
= vnode_vid(tvp
);
650 error
= vnode_getwithvid(tvp
, vid
);
652 error
= vn_getpath(tvp
, buf
, &len
);
655 error
= vnode_lookup(buf
, 0, &nvp
, vfs_context_current());
656 if ((error
== 0) && ( nvp
!= NULLVP
))
659 error
= copyout(buf
, buffer
, len
);
663 kfree(buf
, buffersize
);
668 /********************************** proc_pidinfo ********************************/
672 proc_pidinfo(int pid
, int flavor
, uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, register_t
* retval
)
674 struct proc
* p
= PROC_NULL
;
682 case PROC_PIDLISTFDS
:
683 size
= PROC_PIDLISTFD_SIZE
;
684 if (buffer
== (user_addr_t
)0)
687 case PROC_PIDTBSDINFO
:
688 size
= PROC_PIDTBSDINFO_SIZE
;
690 case PROC_PIDTASKINFO
:
691 size
= PROC_PIDTASKINFO_SIZE
;
693 case PROC_PIDTASKALLINFO
:
694 size
= PROC_PIDTASKALLINFO_SIZE
;
696 case PROC_PIDTHREADINFO
:
697 size
= PROC_PIDTHREADINFO_SIZE
;
699 case PROC_PIDLISTTHREADS
:
700 size
= PROC_PIDLISTTHREADS_SIZE
;
702 case PROC_PIDREGIONINFO
:
703 size
= PROC_PIDREGIONINFO_SIZE
;
705 case PROC_PIDREGIONPATHINFO
:
706 size
= PROC_PIDREGIONPATHINFO_SIZE
;
708 case PROC_PIDVNODEPATHINFO
:
709 size
= PROC_PIDVNODEPATHINFO_SIZE
;
711 case PROC_PIDTHREADPATHINFO
:
712 size
= PROC_PIDTHREADPATHINFO_SIZE
;
714 case PROC_PIDPATHINFO
:
721 if (buffersize
< size
)
724 if ((flavor
== PROC_PIDPATHINFO
) && (buffersize
> PROC_PIDPATHINFO_MAXSIZE
)) {
728 if ((flavor
!= PROC_PIDTBSDINFO
) && (flavor
!= PROC_PIDPATHINFO
)) {
729 if ((p
= proc_find(pid
)) == PROC_NULL
) {
735 /* Do we have permission to look into this ? */
736 if ((error
= proc_security_policy(p
)) != 0) {
742 case PROC_PIDLISTFDS
: {
743 error
= proc_pidfdlist(p
, buffer
, buffersize
, retval
);
747 case PROC_PIDTBSDINFO
: {
748 struct proc_bsdinfo pbsd
;
753 if (p
== PROC_NULL
) {
762 /* Do we have permission to look into this ? */
763 if ((error
= proc_security_policy(p
)) != 0) {
768 error
= proc_pidbsdinfo(p
, &pbsd
);
772 error
= copyout(&pbsd
, buffer
, sizeof(struct proc_bsdinfo
));
774 *retval
= sizeof(struct proc_bsdinfo
);
779 case PROC_PIDTASKINFO
: {
780 struct proc_taskinfo ptinfo
;
782 error
= proc_pidtaskinfo(p
, &ptinfo
);
784 error
= copyout(&ptinfo
, buffer
, sizeof(struct proc_taskinfo
));
786 *retval
= sizeof(struct proc_taskinfo
);
791 case PROC_PIDTASKALLINFO
: {
792 struct proc_taskallinfo pall
;
794 error
= proc_pidbsdinfo(p
, &pall
.pbsd
);
795 error
= proc_pidtaskinfo(p
, &pall
.ptinfo
);
797 error
= copyout(&pall
, buffer
, sizeof(struct proc_taskallinfo
));
799 *retval
= sizeof(struct proc_taskallinfo
);
804 case PROC_PIDTHREADINFO
:{
805 struct proc_threadinfo pthinfo
;
807 error
= proc_pidthreadinfo(p
, arg
, &pthinfo
);
809 error
= copyout(&pthinfo
, buffer
, sizeof(struct proc_threadinfo
));
811 *retval
= sizeof(struct proc_threadinfo
);
816 case PROC_PIDLISTTHREADS
:{
817 error
= proc_pidlistthreads(p
, buffer
, buffersize
, retval
);
821 case PROC_PIDREGIONINFO
:{
822 error
= proc_pidregioninfo(p
, arg
, buffer
, buffersize
, retval
);
827 case PROC_PIDREGIONPATHINFO
:{
828 error
= proc_pidregionpathinfo(p
, arg
, buffer
, buffersize
, retval
);
832 case PROC_PIDVNODEPATHINFO
:{
833 error
= proc_pidvnodepathinfo(p
, arg
, buffer
, buffersize
, retval
);
838 case PROC_PIDTHREADPATHINFO
:{
839 struct proc_threadwithpathinfo pinfo
;
841 error
= proc_pidthreadpathinfo(p
, arg
, &pinfo
);
843 error
= copyout((caddr_t
)&pinfo
, buffer
, sizeof(struct proc_threadwithpathinfo
));
845 *retval
= sizeof(struct proc_threadwithpathinfo
);
850 case PROC_PIDPATHINFO
: {
852 if (p
== PROC_NULL
) {
857 error
= proc_pidpathinfo(p
, arg
, buffer
, buffersize
, retval
);
873 pid_vnodeinfo(vnode_t vp
, uint32_t vid
, struct fileproc
* fp
, int closeonexec
, user_addr_t buffer
, __unused
uint32_t buffersize
, register_t
* retval
)
875 struct vnode_fdinfo vfi
;
878 if ((error
= vnode_getwithvid(vp
, vid
)) != 0) {
881 bzero(&vfi
, sizeof(struct vnode_fdinfo
));
882 fill_fileinfo(fp
, closeonexec
, &vfi
.pfi
);
883 error
= fill_vnodeinfo(vp
, &vfi
.pvi
);
886 error
= copyout((caddr_t
)&vfi
, buffer
, sizeof(struct vnode_fdinfo
));
888 *retval
= sizeof(struct vnode_fdinfo
);
894 pid_vnodeinfopath(vnode_t vp
, uint32_t vid
, struct fileproc
* fp
, int closeonexec
, user_addr_t buffer
, __unused
uint32_t buffersize
, register_t
* retval
)
896 struct vnode_fdinfowithpath vfip
;
899 if ((error
= vnode_getwithvid(vp
, vid
)) != 0) {
902 bzero(&vfip
, sizeof(struct vnode_fdinfowithpath
));
903 fill_fileinfo(fp
, closeonexec
, &vfip
.pfi
);
904 error
= fill_vnodeinfo(vp
, &vfip
.pvip
.vip_vi
) ;
907 vn_getpath(vp
, &vfip
.pvip
.vip_path
[0], &count
);
908 vfip
.pvip
.vip_path
[MAXPATHLEN
-1] = 0;
910 error
= copyout((caddr_t
)&vfip
, buffer
, sizeof(struct vnode_fdinfowithpath
));
912 *retval
= sizeof(struct vnode_fdinfowithpath
);
919 fill_fileinfo(struct fileproc
* fp
, int closeonexec
, struct proc_fileinfo
* fproc
)
921 fproc
->fi_openflags
= fp
->f_fglob
->fg_flag
;
922 fproc
->fi_status
= 0;
923 fproc
->fi_offset
= fp
->f_fglob
->fg_offset
;
924 fproc
->fi_type
= fp
->f_fglob
->fg_type
;
925 if (fp
->f_fglob
->fg_count
)
926 fproc
->fi_status
|= PROC_FP_SHARED
;
927 if (closeonexec
!= 0)
928 fproc
->fi_status
|= PROC_FP_CLEXEC
;
934 fill_vnodeinfo(vnode_t vp
, struct vnode_info
*vinfo
)
936 vfs_context_t context
;
940 context
= vfs_context_create((vfs_context_t
)0);
941 error
= vn_stat(vp
, &sb
, NULL
, 1, context
);
942 (void)vfs_context_rele(context
);
944 munge_vinfo_stat(&sb
, &vinfo
->vi_stat
);
949 if (vp
->v_mount
!= dead_mountp
) {
950 vinfo
->vi_fsid
= vp
->v_mount
->mnt_vfsstat
.f_fsid
;
952 vinfo
->vi_fsid
.val
[0] = 0;
953 vinfo
->vi_fsid
.val
[1] = 0;
955 vinfo
->vi_type
= vp
->v_type
;
961 pid_socketinfo(socket_t so
, struct fileproc
*fp
, int closeonexec
, user_addr_t buffer
, __unused
uint32_t buffersize
, register_t
* retval
)
964 struct socket_fdinfo s
;
967 bzero(&s
, sizeof(struct socket_fdinfo
));
968 fill_fileinfo(fp
, closeonexec
, &s
.pfi
);
969 if ((error
= fill_socketinfo(so
, &s
.psi
)) == 0) {
970 if ((error
= copyout(&s
, buffer
, sizeof(struct socket_fdinfo
))) == 0)
971 *retval
= sizeof(struct socket_fdinfo
);
981 pid_pseminfo(struct psemnode
*psem
, struct fileproc
*fp
, int closeonexec
, user_addr_t buffer
, __unused
uint32_t buffersize
, register_t
* retval
)
983 struct psem_fdinfo pseminfo
;
986 bzero(&pseminfo
, sizeof(struct psem_fdinfo
));
987 fill_fileinfo(fp
, closeonexec
, &pseminfo
.pfi
);
989 if ((error
= fill_pseminfo(psem
, &pseminfo
.pseminfo
)) == 0) {
990 if ((error
= copyout(&pseminfo
, buffer
, sizeof(struct psem_fdinfo
))) == 0)
991 *retval
= sizeof(struct psem_fdinfo
);
998 pid_pshminfo(struct pshmnode
*pshm
, struct fileproc
*fp
, int closeonexec
, user_addr_t buffer
, __unused
uint32_t buffersize
, register_t
* retval
)
1000 struct pshm_fdinfo pshminfo
;
1003 bzero(&pshminfo
, sizeof(struct pshm_fdinfo
));
1004 fill_fileinfo(fp
, closeonexec
, &pshminfo
.pfi
);
1006 if ((error
= fill_pshminfo(pshm
, &pshminfo
.pshminfo
)) == 0) {
1007 if ((error
= copyout(&pshminfo
, buffer
, sizeof(struct pshm_fdinfo
))) == 0)
1008 *retval
= sizeof(struct pshm_fdinfo
);
1015 pid_pipeinfo(struct pipe
* p
, struct fileproc
*fp
, int closeonexec
, user_addr_t buffer
, __unused
uint32_t buffersize
, register_t
* retval
)
1017 struct pipe_fdinfo pipeinfo
;
1020 bzero(&pipeinfo
, sizeof(struct pipe_fdinfo
));
1021 fill_fileinfo(fp
, closeonexec
, &pipeinfo
.pfi
);
1022 if ((error
= fill_pipeinfo(p
, &pipeinfo
.pipeinfo
)) == 0) {
1023 if ((error
= copyout(&pipeinfo
, buffer
, sizeof(struct pipe_fdinfo
))) == 0)
1024 *retval
= sizeof(struct pipe_fdinfo
);
1031 pid_kqueueinfo(struct kqueue
* kq
, struct fileproc
*fp
, int closeonexec
, user_addr_t buffer
, __unused
uint32_t buffersize
, register_t
* retval
)
1033 struct kqueue_fdinfo kqinfo
;
1036 bzero(&kqinfo
, sizeof(struct kqueue_fdinfo
));
1038 fill_fileinfo(fp
, closeonexec
, &kqinfo
.pfi
);
1040 if ((error
= fill_kqueueinfo(kq
, &kqinfo
.kqueueinfo
)) == 0) {
1041 if ((error
= copyout(&kqinfo
, buffer
, sizeof(struct kqueue_fdinfo
))) == 0)
1042 *retval
= sizeof(struct kqueue_fdinfo
);
1049 pid_atalkinfo(__unused
struct atalk
* at
, __unused
struct fileproc
*fp
, __unused
int closeonexec
, __unused user_addr_t buffer
, __unused
uint32_t buffersize
, __unused register_t
* retval
)
1056 /************************** proc_pidfdinfo routine ***************************/
1058 proc_pidfdinfo(int pid
, int flavor
, int fd
, user_addr_t buffer
, uint32_t buffersize
, register_t
* retval
)
1061 int error
= ENOTSUP
;
1062 struct fileproc
* fp
;
1064 int closeonexec
= 0;
1067 case PROC_PIDFDVNODEINFO
:
1068 size
= PROC_PIDFDVNODEINFO_SIZE
;
1070 case PROC_PIDFDVNODEPATHINFO
:
1071 size
= PROC_PIDFDVNODEPATHINFO_SIZE
;
1073 case PROC_PIDFDSOCKETINFO
:
1074 size
= PROC_PIDFDSOCKETINFO_SIZE
;
1076 case PROC_PIDFDPSEMINFO
:
1077 size
= PROC_PIDFDPSEMINFO_SIZE
;
1079 case PROC_PIDFDPSHMINFO
:
1080 size
= PROC_PIDFDPSHMINFO_SIZE
;
1082 case PROC_PIDFDPIPEINFO
:
1083 size
= PROC_PIDFDPIPEINFO_SIZE
;
1085 case PROC_PIDFDKQUEUEINFO
:
1086 size
= PROC_PIDFDKQUEUEINFO_SIZE
;
1088 case PROC_PIDFDATALKINFO
:
1089 size
= PROC_PIDFDATALKINFO_SIZE
;
1097 if (buffersize
< size
)
1100 if ((p
= proc_find(pid
)) == PROC_NULL
) {
1104 /* Do we have permission to look into this ? */
1105 if ((error
= proc_security_policy(p
)) != 0) {
1110 case PROC_PIDFDVNODEINFO
: {
1114 if ((error
= fp_getfvpandvid(p
, fd
, &fp
, &vp
, &vid
)) !=0) {
1117 /* no need to be under the fdlock */
1118 closeonexec
= p
->p_fd
->fd_ofileflags
[fd
] & UF_EXCLOSE
;
1119 error
= pid_vnodeinfo(vp
, vid
, fp
, closeonexec
, buffer
, buffersize
, retval
);
1123 case PROC_PIDFDVNODEPATHINFO
: {
1127 if ((error
= fp_getfvpandvid(p
, fd
, &fp
, &vp
, &vid
)) !=0) {
1131 /* no need to be under the fdlock */
1132 closeonexec
= p
->p_fd
->fd_ofileflags
[fd
] & UF_EXCLOSE
;
1133 error
= pid_vnodeinfopath(vp
, vid
, fp
, closeonexec
, buffer
, buffersize
, retval
);
1137 case PROC_PIDFDSOCKETINFO
: {
1140 if ((error
= fp_getfsock(p
, fd
, &fp
, &so
)) !=0) {
1143 /* no need to be under the fdlock */
1144 closeonexec
= p
->p_fd
->fd_ofileflags
[fd
] & UF_EXCLOSE
;
1145 error
= pid_socketinfo(so
, fp
, closeonexec
, buffer
, buffersize
, retval
);
1149 case PROC_PIDFDPSEMINFO
: {
1150 struct psemnode
* psem
;
1152 if ((error
= fp_getfpsem(p
, fd
, &fp
, &psem
)) !=0) {
1155 /* no need to be under the fdlock */
1156 closeonexec
= p
->p_fd
->fd_ofileflags
[fd
] & UF_EXCLOSE
;
1157 error
= pid_pseminfo(psem
, fp
, closeonexec
, buffer
, buffersize
, retval
);
1161 case PROC_PIDFDPSHMINFO
: {
1162 struct pshmnode
* pshm
;
1164 if ((error
= fp_getfpshm(p
, fd
, &fp
, &pshm
)) !=0) {
1167 /* no need to be under the fdlock */
1168 closeonexec
= p
->p_fd
->fd_ofileflags
[fd
] & UF_EXCLOSE
;
1169 error
= pid_pshminfo(pshm
, fp
, closeonexec
, buffer
, buffersize
, retval
);
1173 case PROC_PIDFDPIPEINFO
: {
1174 struct pipe
* cpipe
;
1176 if ((error
= fp_getfpipe(p
, fd
, &fp
, &cpipe
)) !=0) {
1179 /* no need to be under the fdlock */
1180 closeonexec
= p
->p_fd
->fd_ofileflags
[fd
] & UF_EXCLOSE
;
1181 error
= pid_pipeinfo(cpipe
, fp
, closeonexec
, buffer
, buffersize
, retval
);
1185 case PROC_PIDFDKQUEUEINFO
: {
1188 if ((error
= fp_getfkq(p
, fd
, &fp
, &kq
)) !=0) {
1191 /* no need to be under the fdlock */
1192 closeonexec
= p
->p_fd
->fd_ofileflags
[fd
] & UF_EXCLOSE
;
1193 error
= pid_kqueueinfo(kq
, fp
, closeonexec
, buffer
, buffersize
, retval
);
1197 case PROC_PIDFDATALKINFO
: {
1200 if ((error
= fp_getfatalk(p
, fd
, &fp
, &at
)) !=0) {
1204 /* no need to be under the fdlock */
1205 closeonexec
= p
->p_fd
->fd_ofileflags
[fd
] & UF_EXCLOSE
;
1206 error
= pid_atalkinfo(at
, fp
, closeonexec
, buffer
, buffersize
, retval
);
1217 fp_drop(p
, fd
, fp
, 0);
1226 proc_security_policy(proc_t p
)
1228 kauth_cred_t my_cred
;
1231 my_cred
= kauth_cred_proc_ref(p
);
1232 uid
= kauth_cred_getuid(my_cred
) ;
1233 kauth_cred_unref(&my_cred
);
1235 if ((uid
!= kauth_cred_getuid(kauth_cred_get()))
1236 && suser(kauth_cred_get(), (u_short
*)0)) {
1244 proc_kernmsgbuf(user_addr_t buffer
, uint32_t buffersize
, register_t
* retval
)
1246 if (suser(kauth_cred_get(), (u_short
*)0) == 0) {
1247 return(log_dmesg(buffer
, buffersize
, retval
));
1253 * copy stat64 structure into vinfo_stat structure.
1256 munge_vinfo_stat(struct stat64
*sbp
, struct vinfo_stat
*vsbp
)
1258 bzero(vsbp
, sizeof(struct vinfo_stat
));
1260 vsbp
->vst_dev
= sbp
->st_dev
;
1261 vsbp
->vst_mode
= sbp
->st_mode
;
1262 vsbp
->vst_nlink
= sbp
->st_nlink
;
1263 vsbp
->vst_ino
= sbp
->st_ino
;
1264 vsbp
->vst_uid
= sbp
->st_uid
;
1265 vsbp
->vst_gid
= sbp
->st_gid
;
1266 vsbp
->vst_atime
= sbp
->st_atimespec
.tv_sec
;
1267 vsbp
->vst_atimensec
= sbp
->st_atimespec
.tv_nsec
;
1268 vsbp
->vst_mtime
= sbp
->st_mtimespec
.tv_sec
;
1269 vsbp
->vst_mtimensec
= sbp
->st_mtimespec
.tv_nsec
;
1270 vsbp
->vst_ctime
= sbp
->st_ctimespec
.tv_sec
;
1271 vsbp
->vst_ctimensec
= sbp
->st_ctimespec
.tv_nsec
;
1272 vsbp
->vst_birthtime
= sbp
->st_birthtimespec
.tv_sec
;
1273 vsbp
->vst_birthtimensec
= sbp
->st_birthtimespec
.tv_nsec
;
1274 vsbp
->vst_size
= sbp
->st_size
;
1275 vsbp
->vst_blocks
= sbp
->st_blocks
;
1276 vsbp
->vst_blksize
= sbp
->st_blksize
;
1277 vsbp
->vst_flags
= sbp
->st_flags
;
1278 vsbp
->vst_gen
= sbp
->st_gen
;
1279 vsbp
->vst_rdev
= sbp
->st_rdev
;
1280 vsbp
->vst_qspare
[0] = sbp
->st_qspare
[0];
1281 vsbp
->vst_qspare
[1] = sbp
->st_qspare
[1];