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 <security/audit/audit.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 uint64_t get_dispatchqueue_offset_from_proc(void *);
87 int proc_info_internal(int callnum
, int pid
, int flavor
, uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
);
89 /* protos for proc_info calls */
90 int proc_listpids(uint32_t type
, uint32_t tyoneinfo
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
);
91 int proc_pidinfo(int pid
, int flavor
, uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
);
92 int proc_pidfdinfo(int pid
, int flavor
,int fd
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
);
93 int proc_kernmsgbuf(user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
);
94 int proc_setcontrol(int pid
, int flavor
, uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
);
96 /* protos for procpidinfo calls */
97 int proc_pidfdlist(proc_t p
, user_addr_t buffer
, uint32_t buffersize
, int32_t *retval
);
98 int proc_pidbsdinfo(proc_t p
, struct proc_bsdinfo
*pbsd
, int zombie
);
99 int proc_pidtaskinfo(proc_t p
, struct proc_taskinfo
*ptinfo
);
100 int proc_pidallinfo(proc_t p
, int flavor
, uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, int32_t *retval
);
101 int proc_pidthreadinfo(proc_t p
, uint64_t arg
, struct proc_threadinfo
*pthinfo
);
102 int proc_pidthreadpathinfo(proc_t p
, uint64_t arg
, struct proc_threadwithpathinfo
*pinfo
);
103 int proc_pidlistthreads(proc_t p
, user_addr_t buffer
, uint32_t buffersize
, int32_t *retval
);
104 int proc_pidregioninfo(proc_t p
, uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, int32_t *retval
);
105 int proc_pidregionpathinfo(proc_t p
, uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, int32_t *retval
);
106 int proc_pidvnodepathinfo(proc_t p
, uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, int32_t *retval
);
107 int proc_pidpathinfo(proc_t p
, uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, int32_t *retval
);
108 int proc_pidworkqueueinfo(proc_t p
, struct proc_workqueueinfo
*pwqinfo
);
111 /* protos for proc_pidfdinfo calls */
112 int pid_vnodeinfo(vnode_t vp
, uint32_t vid
, struct fileproc
* fp
, int closeonexec
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
);
113 int pid_vnodeinfopath(vnode_t vp
, uint32_t vid
, struct fileproc
* fp
, int closeonexec
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
);
114 int pid_socketinfo(socket_t so
, struct fileproc
*fp
, int closeonexec
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
);
115 int pid_pseminfo(struct psemnode
* psem
, struct fileproc
* fp
, int closeonexec
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
);
116 int pid_pshminfo(struct pshmnode
* pshm
, struct fileproc
* fp
, int closeonexec
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
);
117 int pid_pipeinfo(struct pipe
* p
, struct fileproc
* fp
, int closeonexec
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
);
118 int pid_kqueueinfo(struct kqueue
* kq
, struct fileproc
* fp
, int closeonexec
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
);
119 int pid_atalkinfo(struct atalk
* at
, struct fileproc
* fp
, int closeonexec
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
);
122 /* protos for misc */
124 int fill_vnodeinfo(vnode_t vp
, struct vnode_info
*vinfo
);
125 void fill_fileinfo(struct fileproc
* fp
, int closeonexec
, struct proc_fileinfo
* finfo
);
126 static int proc_security_policy(proc_t p
);
127 static void munge_vinfo_stat(struct stat64
*sbp
, struct vinfo_stat
*vsbp
);
129 uint64_t get_dispatchqueue_offset_from_proc(void *p
)
132 proc_t pself
= (proc_t
)p
;
133 return (pself
->p_dispatchqueue_offset
);
139 /***************************** proc_info ********************/
142 proc_info(__unused
struct proc
*p
, struct proc_info_args
* uap
, int32_t *retval
)
144 return(proc_info_internal(uap
->callnum
, uap
->pid
, uap
->flavor
, uap
->arg
, uap
->buffer
, uap
->buffersize
, retval
));
149 proc_info_internal(int callnum
, int pid
, int flavor
, uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
)
153 case 1: /* proc_listpids */
154 /* pid contains type and flavor contains typeinfo */
155 return(proc_listpids(pid
, flavor
, buffer
, buffersize
, retval
));
156 case 2: /* proc_pidinfo */
157 return(proc_pidinfo(pid
, flavor
, arg
, buffer
, buffersize
, retval
));
158 case 3: /* proc_pidfdinfo */
159 return(proc_pidfdinfo(pid
, flavor
, (int)arg
, buffer
, buffersize
, retval
));
160 case 4: /* proc_kernmsgbuf */
161 return(proc_kernmsgbuf(buffer
, buffersize
, retval
));
162 case 5: /* set on self properties proc_setcontrol */
163 return(proc_setcontrol(pid
, flavor
, arg
, buffer
, buffersize
, retval
));
172 /******************* proc_listpids routine ****************/
174 proc_listpids(uint32_t type
, uint32_t typeinfo
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
)
176 int numprocs
, wantpids
;
184 /* if the buffer is null, return num of procs */
185 if (buffer
== (user_addr_t
)0) {
186 *retval
= ((nprocs
+20) * sizeof(int));
190 if (buffersize
< sizeof(int)) {
193 wantpids
= buffersize
/sizeof(int);
194 numprocs
= nprocs
+20;
195 if (numprocs
> wantpids
)
198 kbuf
= (char *)kalloc((vm_size_t
)(numprocs
* sizeof(int)));
201 bzero(kbuf
, sizeof(int));
208 LIST_FOREACH(p
, &allproc
, p_list
) {
212 if (p
->p_pgrpid
!= (pid_t
)typeinfo
)
219 /* racy but list lock is held */
220 if ((p
->p_flag
& P_CONTROLT
) == 0 ||
221 (p
->p_pgrp
== NULL
) || (p
->p_pgrp
->pg_session
== NULL
) ||
222 (tp
= SESSION_TP(p
->p_pgrp
->pg_session
)) == TTY_NULL
||
223 tp
->t_dev
!= (dev_t
)typeinfo
)
227 if (p
->p_ucred
== NULL
)
230 kauth_cred_t my_cred
;
233 my_cred
= kauth_cred_proc_ref(p
);
234 uid
= kauth_cred_getuid(my_cred
);
235 kauth_cred_unref(&my_cred
);
236 if (uid
!= (uid_t
)typeinfo
)
241 if (p
->p_ucred
== NULL
)
244 kauth_cred_t my_cred
;
247 my_cred
= kauth_cred_proc_ref(p
);
248 uid
= my_cred
->cr_ruid
;
249 kauth_cred_unref(&my_cred
);
250 if (uid
!= (uid_t
)typeinfo
)
259 /* Do we have permission to look into this ? */
260 if (proc_security_policy(p
) != 0) {
273 LIST_FOREACH(p
, &zombproc
, p_list
) {
285 error
= copyout((caddr_t
)ptr
, buffer
, n
* sizeof(int));
287 *retval
= (n
* sizeof(int));
288 kfree((void *)kbuf
, (vm_size_t
)(numprocs
* sizeof(int)));
294 /********************************** proc_pidinfo routines ********************************/
297 proc_pidfdlist(proc_t p
, user_addr_t buffer
, uint32_t buffersize
, int32_t *retval
)
301 struct proc_fdinfo
* pfd
;
302 struct fileproc
* fp
;
307 numfds
= p
->p_fd
->fd_nfiles
;
309 if (buffer
== (user_addr_t
) 0) {
311 *retval
= (numfds
* sizeof(struct proc_fdinfo
));
315 /* buffersize is big enough atleast for one struct */
316 needfds
= buffersize
/sizeof(struct proc_fdinfo
);
318 if (numfds
> needfds
)
321 kbuf
= (char *)kalloc((vm_size_t
)(numfds
* sizeof(struct proc_fdinfo
)));
324 bzero(kbuf
, numfds
* sizeof(struct proc_fdinfo
));
328 pfd
= (struct proc_fdinfo
*)kbuf
;
330 for (n
= 0; ((n
< numfds
) && (n
< p
->p_fd
->fd_nfiles
)); n
++) {
331 if (((fp
= p
->p_fd
->fd_ofiles
[n
]) != 0)
332 && ((p
->p_fd
->fd_ofileflags
[n
] & UF_RESERVED
) == 0)) {
334 pfd
->proc_fdtype
= fp
->f_fglob
->fg_type
;
341 error
= copyout(kbuf
, buffer
, count
* sizeof(struct proc_fdinfo
));
342 kfree((void *)kbuf
, (vm_size_t
)(numfds
* sizeof(struct proc_fdinfo
)));
344 *retval
= (count
* sizeof(struct proc_fdinfo
));
350 proc_pidbsdinfo(proc_t p
, struct proc_bsdinfo
* pbsd
, int zombie
)
352 register struct tty
*tp
;
353 struct session
*sessionp
= NULL
;
355 kauth_cred_t my_cred
;
358 sessionp
= proc_session(p
);
360 my_cred
= kauth_cred_proc_ref(p
);
361 bzero(pbsd
, sizeof(struct proc_bsdinfo
));
362 pbsd
->pbi_status
= p
->p_stat
;
363 pbsd
->pbi_xstatus
= p
->p_xstat
;
364 pbsd
->pbi_pid
= p
->p_pid
;
365 pbsd
->pbi_ppid
= p
->p_ppid
;
366 pbsd
->pbi_uid
= my_cred
->cr_uid
;
367 pbsd
->pbi_gid
= my_cred
->cr_gid
;
368 pbsd
->pbi_ruid
= my_cred
->cr_ruid
;
369 pbsd
->pbi_rgid
= my_cred
->cr_rgid
;
370 pbsd
->pbi_svuid
= my_cred
->cr_svuid
;
371 pbsd
->pbi_svgid
= my_cred
->cr_svgid
;
372 kauth_cred_unref(&my_cred
);
374 pbsd
->pbi_nice
= p
->p_nice
;
375 pbsd
->pbi_start_tvsec
= p
->p_start
.tv_sec
;
376 pbsd
->pbi_start_tvusec
= p
->p_start
.tv_usec
;
377 bcopy(&p
->p_comm
, &pbsd
->pbi_comm
[0], MAXCOMLEN
-1);
378 bcopy(&p
->p_name
, &pbsd
->pbi_name
[0], 2*MAXCOMLEN
-1);
381 if ((p
->p_flag
& P_SYSTEM
) == P_SYSTEM
)
382 pbsd
->pbi_flags
|= PROC_FLAG_SYSTEM
;
383 if ((p
->p_lflag
& P_LTRACED
) == P_LTRACED
)
384 pbsd
->pbi_flags
|= PROC_FLAG_TRACED
;
385 if ((p
->p_lflag
& P_LEXIT
) == P_LEXIT
)
386 pbsd
->pbi_flags
|= PROC_FLAG_INEXIT
;
387 if ((p
->p_lflag
& P_LPPWAIT
) == P_LPPWAIT
)
388 pbsd
->pbi_flags
|= PROC_FLAG_PPWAIT
;
389 if ((p
->p_flag
& P_LP64
) == P_LP64
)
390 pbsd
->pbi_flags
|= PROC_FLAG_LP64
;
391 if ((p
->p_flag
& P_CONTROLT
) == P_CONTROLT
)
392 pbsd
->pbi_flags
|= PROC_FLAG_CONTROLT
;
393 if ((p
->p_flag
& P_THCWD
) == P_THCWD
)
394 pbsd
->pbi_flags
|= PROC_FLAG_THCWD
;
396 if (sessionp
!= SESSION_NULL
) {
397 if (SESS_LEADER(p
, sessionp
))
398 pbsd
->pbi_flags
|= PROC_FLAG_SLEADER
;
399 if (sessionp
->s_ttyvp
)
400 pbsd
->pbi_flags
|= PROC_FLAG_CTTY
;
404 switch(PROC_CONTROL_STATE(p
)) {
406 pbsd
->pbi_flags
|= PROC_FLAG_PC_THROTTLE
;
409 pbsd
->pbi_flags
|= PROC_FLAG_PC_SUSP
;
412 pbsd
->pbi_flags
|= PROC_FLAG_PC_KILL
;
416 switch(PROC_ACTION_STATE(p
)) {
418 pbsd
->pbi_flags
|= PROC_FLAG_PA_THROTTLE
;
421 pbsd
->pbi_flags
|= PROC_FLAG_PA_SUSP
;
426 pbsd
->pbi_nfiles
= p
->p_fd
->fd_nfiles
;
427 if (pg
!= PGRP_NULL
) {
428 pbsd
->pbi_pgid
= p
->p_pgrpid
;
429 pbsd
->pbi_pjobc
= pg
->pg_jobc
;
430 if ((p
->p_flag
& P_CONTROLT
) && (sessionp
!= SESSION_NULL
) && (tp
= SESSION_TP(sessionp
))) {
431 pbsd
->e_tdev
= tp
->t_dev
;
432 pbsd
->e_tpgid
= sessionp
->s_ttypgrpid
;
435 if (sessionp
!= SESSION_NULL
)
436 session_rele(sessionp
);
445 proc_pidtaskinfo(proc_t p
, struct proc_taskinfo
* ptinfo
)
451 bzero(ptinfo
, sizeof(struct proc_taskinfo
));
452 fill_taskprocinfo(task
, (struct proc_taskinfo_internal
*)ptinfo
);
460 proc_pidthreadinfo(proc_t p
, uint64_t arg
, struct proc_threadinfo
*pthinfo
)
463 uint64_t threadaddr
= (uint64_t)arg
;
465 bzero(pthinfo
, sizeof(struct proc_threadinfo
));
467 error
= fill_taskthreadinfo(p
->task
, threadaddr
, (struct proc_threadinfo_internal
*)pthinfo
, NULL
, NULL
);
476 bsd_getthreadname(void *uth
, char *buffer
)
478 struct uthread
*ut
= (struct uthread
*)uth
;
480 bcopy(ut
->pth_name
,buffer
,MAXTHREADNAMESIZE
);
484 bsd_threadcdir(void * uth
, void *vptr
, int *vidp
)
486 struct uthread
* ut
= (struct uthread
*)uth
;
488 vnode_t
*vpp
= (vnode_t
*)vptr
;
502 proc_pidthreadpathinfo(proc_t p
, uint64_t arg
, struct proc_threadwithpathinfo
*pinfo
)
507 uint64_t threadaddr
= (uint64_t)arg
;
510 bzero(pinfo
, sizeof(struct proc_threadwithpathinfo
));
512 error
= fill_taskthreadinfo(p
->task
, threadaddr
, (struct proc_threadinfo_internal
*)&pinfo
->pt
, (void *)&vp
, &vid
);
516 if ((vp
!= NULLVP
) && ((vnode_getwithvid(vp
, vid
)) == 0)) {
517 error
= fill_vnodeinfo(vp
, &pinfo
->pvip
.vip_vi
) ;
520 vn_getpath(vp
, &pinfo
->pvip
.vip_path
[0], &count
);
521 pinfo
->pvip
.vip_path
[MAXPATHLEN
-1] = 0;
531 proc_pidlistthreads(proc_t p
, user_addr_t buffer
, uint32_t buffersize
, int32_t *retval
)
540 count
= buffersize
/(sizeof(uint64_t));
541 numthreads
= get_numthreads(p
->task
);
545 if (numthreads
> count
)
548 kbuf
= (void *)kalloc(numthreads
* sizeof(uint64_t));
551 bzero(kbuf
, numthreads
* sizeof(uint64_t));
553 ret
= fill_taskthreadlist(p
->task
, kbuf
, numthreads
);
555 error
= copyout(kbuf
, buffer
, ret
);
556 kfree(kbuf
, numthreads
* sizeof(uint64_t));
565 proc_pidregioninfo(proc_t p
, uint64_t arg
, user_addr_t buffer
, __unused
uint32_t buffersize
, int32_t *retval
)
567 struct proc_regioninfo preginfo
;
570 bzero(&preginfo
, sizeof(struct proc_regioninfo
));
571 ret
= fill_procregioninfo( p
->task
, arg
, (struct proc_regioninfo_internal
*)&preginfo
, (uintptr_t *)0, (uint32_t *)0);
574 error
= copyout(&preginfo
, buffer
, sizeof(struct proc_regioninfo
));
576 *retval
= sizeof(struct proc_regioninfo
);
582 proc_pidregionpathinfo(proc_t p
, uint64_t arg
, user_addr_t buffer
, __unused
uint32_t buffersize
, int32_t *retval
)
584 struct proc_regionwithpathinfo preginfo
;
586 uintptr_t vnodeaddr
= 0;
591 bzero(&preginfo
, sizeof(struct proc_regionwithpathinfo
));
593 ret
= fill_procregioninfo( p
->task
, arg
, (struct proc_regioninfo_internal
*)&preginfo
.prp_prinfo
, (uintptr_t *)&vnodeaddr
, (uint32_t *)&vnodeid
);
597 vp
= (vnode_t
)vnodeaddr
;
598 if ((vnode_getwithvid(vp
, vnodeid
)) == 0) {
599 /* FILL THE VNODEINFO */
600 error
= fill_vnodeinfo(vp
, &preginfo
.prp_vip
.vip_vi
);
602 vn_getpath(vp
, &preginfo
.prp_vip
.vip_path
[0], &count
);
603 /* Always make sure it is null terminated */
604 preginfo
.prp_vip
.vip_path
[MAXPATHLEN
-1] = 0;
608 error
= copyout(&preginfo
, buffer
, sizeof(struct proc_regionwithpathinfo
));
610 *retval
= sizeof(struct proc_regionwithpathinfo
);
615 * Path is relative to current process directory; may different from current
619 proc_pidvnodepathinfo(proc_t p
, __unused
uint64_t arg
, user_addr_t buffer
, __unused
uint32_t buffersize
, int32_t *retval
)
621 struct proc_vnodepathinfo pvninfo
;
623 vnode_t vncdirvp
= NULLVP
;
625 vnode_t vnrdirvp
= NULLVP
;
629 bzero(&pvninfo
, sizeof(struct proc_vnodepathinfo
));
632 if (p
->p_fd
->fd_cdir
) {
633 vncdirvp
= p
->p_fd
->fd_cdir
;
634 vncdirid
= p
->p_fd
->fd_cdir
->v_id
;
636 if (p
->p_fd
->fd_rdir
) {
637 vnrdirvp
= p
->p_fd
->fd_rdir
;
638 vnrdirid
= p
->p_fd
->fd_rdir
->v_id
;
642 if (vncdirvp
!= NULLVP
) {
643 if ((error
= vnode_getwithvid(vncdirvp
, vncdirid
)) == 0) {
644 /* FILL THE VNODEINFO */
645 error
= fill_vnodeinfo(vncdirvp
, &pvninfo
.pvi_cdir
.vip_vi
);
648 vn_getpath(vncdirvp
, &pvninfo
.pvi_cdir
.vip_path
[0], &count
);
649 pvninfo
.pvi_cdir
.vip_path
[MAXPATHLEN
-1] = 0;
657 if ((error
== 0) && (vnrdirvp
!= NULLVP
)) {
658 if ((error
= vnode_getwithvid(vnrdirvp
, vnrdirid
)) == 0) {
659 /* FILL THE VNODEINFO */
660 error
= fill_vnodeinfo(vnrdirvp
, &pvninfo
.pvi_rdir
.vip_vi
);
663 vn_getpath(vnrdirvp
, &pvninfo
.pvi_rdir
.vip_path
[0], &count
);
664 pvninfo
.pvi_rdir
.vip_path
[MAXPATHLEN
-1] = 0;
672 error
= copyout(&pvninfo
, buffer
, sizeof(struct proc_vnodepathinfo
));
674 *retval
= sizeof(struct proc_vnodepathinfo
);
681 proc_pidpathinfo(proc_t p
, __unused
uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, __unused
int32_t *retval
)
685 vnode_t nvp
= NULLVP
;
686 int len
= buffersize
;
694 buf
= (char *)kalloc(buffersize
);
699 vid
= vnode_vid(tvp
);
700 error
= vnode_getwithvid(tvp
, vid
);
702 error
= vn_getpath_fsenter(tvp
, buf
, &len
);
705 error
= vnode_lookup(buf
, 0, &nvp
, vfs_context_current());
706 if ((error
== 0) && ( nvp
!= NULLVP
))
709 error
= copyout(buf
, buffer
, len
);
713 kfree(buf
, buffersize
);
719 proc_pidworkqueueinfo(proc_t p
, struct proc_workqueueinfo
*pwqinfo
)
723 bzero(pwqinfo
, sizeof(struct proc_workqueueinfo
));
725 error
= fill_procworkqueue(p
, pwqinfo
);
732 /********************************** proc_pidinfo ********************************/
736 proc_pidinfo(int pid
, int flavor
, uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
)
738 struct proc
* p
= PROC_NULL
;
747 case PROC_PIDLISTFDS
:
748 size
= PROC_PIDLISTFD_SIZE
;
749 if (buffer
== (user_addr_t
)0)
752 case PROC_PIDTBSDINFO
:
753 size
= PROC_PIDTBSDINFO_SIZE
;
755 case PROC_PIDTASKINFO
:
756 size
= PROC_PIDTASKINFO_SIZE
;
758 case PROC_PIDTASKALLINFO
:
759 size
= PROC_PIDTASKALLINFO_SIZE
;
761 case PROC_PIDTHREADINFO
:
762 size
= PROC_PIDTHREADINFO_SIZE
;
764 case PROC_PIDLISTTHREADS
:
765 size
= PROC_PIDLISTTHREADS_SIZE
;
767 case PROC_PIDREGIONINFO
:
768 size
= PROC_PIDREGIONINFO_SIZE
;
770 case PROC_PIDREGIONPATHINFO
:
771 size
= PROC_PIDREGIONPATHINFO_SIZE
;
773 case PROC_PIDVNODEPATHINFO
:
774 size
= PROC_PIDVNODEPATHINFO_SIZE
;
776 case PROC_PIDTHREADPATHINFO
:
777 size
= PROC_PIDTHREADPATHINFO_SIZE
;
779 case PROC_PIDPATHINFO
:
782 case PROC_PIDWORKQUEUEINFO
:
783 /* kernel does not have workq info */
787 size
= PROC_PIDWORKQUEUEINFO_SIZE
;
793 if (buffersize
< size
)
796 if ((flavor
== PROC_PIDPATHINFO
) && (buffersize
> PROC_PIDPATHINFO_MAXSIZE
)) {
800 if ((flavor
!= PROC_PIDTBSDINFO
) && (flavor
!= PROC_PIDPATHINFO
)) {
801 if ((p
= proc_find(pid
)) == PROC_NULL
) {
807 /* Do we have permission to look into this ? */
808 if ((error
= proc_security_policy(p
)) != 0) {
814 case PROC_PIDLISTFDS
: {
815 error
= proc_pidfdlist(p
, buffer
, buffersize
, retval
);
819 case PROC_PIDTBSDINFO
: {
820 struct proc_bsdinfo pbsd
;
826 if (p
== PROC_NULL
) {
836 /* Do we have permission to look into this ? */
837 if ((error
= proc_security_policy(p
)) != 0) {
842 error
= proc_pidbsdinfo(p
, &pbsd
, zombie
);
846 error
= copyout(&pbsd
, buffer
, sizeof(struct proc_bsdinfo
));
848 *retval
= sizeof(struct proc_bsdinfo
);
853 case PROC_PIDTASKINFO
: {
854 struct proc_taskinfo ptinfo
;
856 error
= proc_pidtaskinfo(p
, &ptinfo
);
858 error
= copyout(&ptinfo
, buffer
, sizeof(struct proc_taskinfo
));
860 *retval
= sizeof(struct proc_taskinfo
);
865 case PROC_PIDTASKALLINFO
: {
866 struct proc_taskallinfo pall
;
868 error
= proc_pidbsdinfo(p
, &pall
.pbsd
, 0);
869 error
= proc_pidtaskinfo(p
, &pall
.ptinfo
);
871 error
= copyout(&pall
, buffer
, sizeof(struct proc_taskallinfo
));
873 *retval
= sizeof(struct proc_taskallinfo
);
878 case PROC_PIDTHREADINFO
:{
879 struct proc_threadinfo pthinfo
;
881 error
= proc_pidthreadinfo(p
, arg
, &pthinfo
);
883 error
= copyout(&pthinfo
, buffer
, sizeof(struct proc_threadinfo
));
885 *retval
= sizeof(struct proc_threadinfo
);
890 case PROC_PIDLISTTHREADS
:{
891 error
= proc_pidlistthreads(p
, buffer
, buffersize
, retval
);
895 case PROC_PIDREGIONINFO
:{
896 error
= proc_pidregioninfo(p
, arg
, buffer
, buffersize
, retval
);
901 case PROC_PIDREGIONPATHINFO
:{
902 error
= proc_pidregionpathinfo(p
, arg
, buffer
, buffersize
, retval
);
906 case PROC_PIDVNODEPATHINFO
:{
907 error
= proc_pidvnodepathinfo(p
, arg
, buffer
, buffersize
, retval
);
912 case PROC_PIDTHREADPATHINFO
:{
913 struct proc_threadwithpathinfo pinfo
;
915 error
= proc_pidthreadpathinfo(p
, arg
, &pinfo
);
917 error
= copyout((caddr_t
)&pinfo
, buffer
, sizeof(struct proc_threadwithpathinfo
));
919 *retval
= sizeof(struct proc_threadwithpathinfo
);
924 case PROC_PIDPATHINFO
: {
926 if (p
== PROC_NULL
) {
931 error
= proc_pidpathinfo(p
, arg
, buffer
, buffersize
, retval
);
936 case PROC_PIDWORKQUEUEINFO
:{
937 struct proc_workqueueinfo pwqinfo
;
939 error
= proc_pidworkqueueinfo(p
, &pwqinfo
);
941 error
= copyout(&pwqinfo
, buffer
, sizeof(struct proc_workqueueinfo
));
943 *retval
= sizeof(struct proc_workqueueinfo
);
960 pid_vnodeinfo(vnode_t vp
, uint32_t vid
, struct fileproc
* fp
, int closeonexec
, user_addr_t buffer
, __unused
uint32_t buffersize
, int32_t * retval
)
962 struct vnode_fdinfo vfi
;
965 if ((error
= vnode_getwithvid(vp
, vid
)) != 0) {
968 bzero(&vfi
, sizeof(struct vnode_fdinfo
));
969 fill_fileinfo(fp
, closeonexec
, &vfi
.pfi
);
970 error
= fill_vnodeinfo(vp
, &vfi
.pvi
);
973 error
= copyout((caddr_t
)&vfi
, buffer
, sizeof(struct vnode_fdinfo
));
975 *retval
= sizeof(struct vnode_fdinfo
);
981 pid_vnodeinfopath(vnode_t vp
, uint32_t vid
, struct fileproc
* fp
, int closeonexec
, user_addr_t buffer
, __unused
uint32_t buffersize
, int32_t * retval
)
983 struct vnode_fdinfowithpath vfip
;
986 if ((error
= vnode_getwithvid(vp
, vid
)) != 0) {
989 bzero(&vfip
, sizeof(struct vnode_fdinfowithpath
));
990 fill_fileinfo(fp
, closeonexec
, &vfip
.pfi
);
991 error
= fill_vnodeinfo(vp
, &vfip
.pvip
.vip_vi
) ;
994 vn_getpath(vp
, &vfip
.pvip
.vip_path
[0], &count
);
995 vfip
.pvip
.vip_path
[MAXPATHLEN
-1] = 0;
997 error
= copyout((caddr_t
)&vfip
, buffer
, sizeof(struct vnode_fdinfowithpath
));
999 *retval
= sizeof(struct vnode_fdinfowithpath
);
1006 fill_fileinfo(struct fileproc
* fp
, int closeonexec
, struct proc_fileinfo
* fproc
)
1008 fproc
->fi_openflags
= fp
->f_fglob
->fg_flag
;
1009 fproc
->fi_status
= 0;
1010 fproc
->fi_offset
= fp
->f_fglob
->fg_offset
;
1011 fproc
->fi_type
= fp
->f_fglob
->fg_type
;
1012 if (fp
->f_fglob
->fg_count
)
1013 fproc
->fi_status
|= PROC_FP_SHARED
;
1014 if (closeonexec
!= 0)
1015 fproc
->fi_status
|= PROC_FP_CLEXEC
;
1021 fill_vnodeinfo(vnode_t vp
, struct vnode_info
*vinfo
)
1023 vfs_context_t context
;
1027 context
= vfs_context_create((vfs_context_t
)0);
1028 error
= vn_stat(vp
, &sb
, NULL
, 1, context
);
1029 (void)vfs_context_rele(context
);
1031 munge_vinfo_stat(&sb
, &vinfo
->vi_stat
);
1036 if (vp
->v_mount
!= dead_mountp
) {
1037 vinfo
->vi_fsid
= vp
->v_mount
->mnt_vfsstat
.f_fsid
;
1039 vinfo
->vi_fsid
.val
[0] = 0;
1040 vinfo
->vi_fsid
.val
[1] = 0;
1042 vinfo
->vi_type
= vp
->v_type
;
1048 pid_socketinfo(socket_t so
, struct fileproc
*fp
, int closeonexec
, user_addr_t buffer
, __unused
uint32_t buffersize
, int32_t * retval
)
1051 struct socket_fdinfo s
;
1054 bzero(&s
, sizeof(struct socket_fdinfo
));
1055 fill_fileinfo(fp
, closeonexec
, &s
.pfi
);
1056 if ((error
= fill_socketinfo(so
, &s
.psi
)) == 0) {
1057 if ((error
= copyout(&s
, buffer
, sizeof(struct socket_fdinfo
))) == 0)
1058 *retval
= sizeof(struct socket_fdinfo
);
1068 pid_pseminfo(struct psemnode
*psem
, struct fileproc
*fp
, int closeonexec
, user_addr_t buffer
, __unused
uint32_t buffersize
, int32_t * retval
)
1070 struct psem_fdinfo pseminfo
;
1073 bzero(&pseminfo
, sizeof(struct psem_fdinfo
));
1074 fill_fileinfo(fp
, closeonexec
, &pseminfo
.pfi
);
1076 if ((error
= fill_pseminfo(psem
, &pseminfo
.pseminfo
)) == 0) {
1077 if ((error
= copyout(&pseminfo
, buffer
, sizeof(struct psem_fdinfo
))) == 0)
1078 *retval
= sizeof(struct psem_fdinfo
);
1085 pid_pshminfo(struct pshmnode
*pshm
, struct fileproc
*fp
, int closeonexec
, user_addr_t buffer
, __unused
uint32_t buffersize
, int32_t * retval
)
1087 struct pshm_fdinfo pshminfo
;
1090 bzero(&pshminfo
, sizeof(struct pshm_fdinfo
));
1091 fill_fileinfo(fp
, closeonexec
, &pshminfo
.pfi
);
1093 if ((error
= fill_pshminfo(pshm
, &pshminfo
.pshminfo
)) == 0) {
1094 if ((error
= copyout(&pshminfo
, buffer
, sizeof(struct pshm_fdinfo
))) == 0)
1095 *retval
= sizeof(struct pshm_fdinfo
);
1102 pid_pipeinfo(struct pipe
* p
, struct fileproc
*fp
, int closeonexec
, user_addr_t buffer
, __unused
uint32_t buffersize
, int32_t * retval
)
1104 struct pipe_fdinfo pipeinfo
;
1107 bzero(&pipeinfo
, sizeof(struct pipe_fdinfo
));
1108 fill_fileinfo(fp
, closeonexec
, &pipeinfo
.pfi
);
1109 if ((error
= fill_pipeinfo(p
, &pipeinfo
.pipeinfo
)) == 0) {
1110 if ((error
= copyout(&pipeinfo
, buffer
, sizeof(struct pipe_fdinfo
))) == 0)
1111 *retval
= sizeof(struct pipe_fdinfo
);
1118 pid_kqueueinfo(struct kqueue
* kq
, struct fileproc
*fp
, int closeonexec
, user_addr_t buffer
, __unused
uint32_t buffersize
, int32_t * retval
)
1120 struct kqueue_fdinfo kqinfo
;
1123 bzero(&kqinfo
, sizeof(struct kqueue_fdinfo
));
1125 fill_fileinfo(fp
, closeonexec
, &kqinfo
.pfi
);
1127 if ((error
= fill_kqueueinfo(kq
, &kqinfo
.kqueueinfo
)) == 0) {
1128 if ((error
= copyout(&kqinfo
, buffer
, sizeof(struct kqueue_fdinfo
))) == 0)
1129 *retval
= sizeof(struct kqueue_fdinfo
);
1136 pid_atalkinfo(__unused
struct atalk
* at
, __unused
struct fileproc
*fp
, __unused
int closeonexec
, __unused user_addr_t buffer
, __unused
uint32_t buffersize
, __unused
int32_t * retval
)
1143 /************************** proc_pidfdinfo routine ***************************/
1145 proc_pidfdinfo(int pid
, int flavor
, int fd
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
)
1148 int error
= ENOTSUP
;
1149 struct fileproc
* fp
;
1151 int closeonexec
= 0;
1154 case PROC_PIDFDVNODEINFO
:
1155 size
= PROC_PIDFDVNODEINFO_SIZE
;
1157 case PROC_PIDFDVNODEPATHINFO
:
1158 size
= PROC_PIDFDVNODEPATHINFO_SIZE
;
1160 case PROC_PIDFDSOCKETINFO
:
1161 size
= PROC_PIDFDSOCKETINFO_SIZE
;
1163 case PROC_PIDFDPSEMINFO
:
1164 size
= PROC_PIDFDPSEMINFO_SIZE
;
1166 case PROC_PIDFDPSHMINFO
:
1167 size
= PROC_PIDFDPSHMINFO_SIZE
;
1169 case PROC_PIDFDPIPEINFO
:
1170 size
= PROC_PIDFDPIPEINFO_SIZE
;
1172 case PROC_PIDFDKQUEUEINFO
:
1173 size
= PROC_PIDFDKQUEUEINFO_SIZE
;
1175 case PROC_PIDFDATALKINFO
:
1176 size
= PROC_PIDFDATALKINFO_SIZE
;
1184 if (buffersize
< size
)
1187 if ((p
= proc_find(pid
)) == PROC_NULL
) {
1191 /* Do we have permission to look into this ? */
1192 if ((error
= proc_security_policy(p
)) != 0) {
1197 case PROC_PIDFDVNODEINFO
: {
1201 if ((error
= fp_getfvpandvid(p
, fd
, &fp
, &vp
, &vid
)) !=0) {
1204 /* no need to be under the fdlock */
1205 closeonexec
= p
->p_fd
->fd_ofileflags
[fd
] & UF_EXCLOSE
;
1206 error
= pid_vnodeinfo(vp
, vid
, fp
, closeonexec
, buffer
, buffersize
, retval
);
1210 case PROC_PIDFDVNODEPATHINFO
: {
1214 if ((error
= fp_getfvpandvid(p
, fd
, &fp
, &vp
, &vid
)) !=0) {
1218 /* no need to be under the fdlock */
1219 closeonexec
= p
->p_fd
->fd_ofileflags
[fd
] & UF_EXCLOSE
;
1220 error
= pid_vnodeinfopath(vp
, vid
, fp
, closeonexec
, buffer
, buffersize
, retval
);
1224 case PROC_PIDFDSOCKETINFO
: {
1227 if ((error
= fp_getfsock(p
, fd
, &fp
, &so
)) !=0) {
1230 /* no need to be under the fdlock */
1231 closeonexec
= p
->p_fd
->fd_ofileflags
[fd
] & UF_EXCLOSE
;
1232 error
= pid_socketinfo(so
, fp
, closeonexec
, buffer
, buffersize
, retval
);
1236 case PROC_PIDFDPSEMINFO
: {
1237 struct psemnode
* psem
;
1239 if ((error
= fp_getfpsem(p
, fd
, &fp
, &psem
)) !=0) {
1242 /* no need to be under the fdlock */
1243 closeonexec
= p
->p_fd
->fd_ofileflags
[fd
] & UF_EXCLOSE
;
1244 error
= pid_pseminfo(psem
, fp
, closeonexec
, buffer
, buffersize
, retval
);
1248 case PROC_PIDFDPSHMINFO
: {
1249 struct pshmnode
* pshm
;
1251 if ((error
= fp_getfpshm(p
, fd
, &fp
, &pshm
)) !=0) {
1254 /* no need to be under the fdlock */
1255 closeonexec
= p
->p_fd
->fd_ofileflags
[fd
] & UF_EXCLOSE
;
1256 error
= pid_pshminfo(pshm
, fp
, closeonexec
, buffer
, buffersize
, retval
);
1260 case PROC_PIDFDPIPEINFO
: {
1261 struct pipe
* cpipe
;
1263 if ((error
= fp_getfpipe(p
, fd
, &fp
, &cpipe
)) !=0) {
1266 /* no need to be under the fdlock */
1267 closeonexec
= p
->p_fd
->fd_ofileflags
[fd
] & UF_EXCLOSE
;
1268 error
= pid_pipeinfo(cpipe
, fp
, closeonexec
, buffer
, buffersize
, retval
);
1272 case PROC_PIDFDKQUEUEINFO
: {
1275 if ((error
= fp_getfkq(p
, fd
, &fp
, &kq
)) !=0) {
1278 /* no need to be under the fdlock */
1279 closeonexec
= p
->p_fd
->fd_ofileflags
[fd
] & UF_EXCLOSE
;
1280 error
= pid_kqueueinfo(kq
, fp
, closeonexec
, buffer
, buffersize
, retval
);
1285 case PROC_PIDFDATALKINFO
: {
1288 if ((error
= fp_getfatalk(p
, fd
, &fp
, &at
)) !=0) {
1292 /* no need to be under the fdlock */
1293 closeonexec
= p
->p_fd
->fd_ofileflags
[fd
] & UF_EXCLOSE
;
1294 error
= pid_atalkinfo(at
, fp
, closeonexec
, buffer
, buffersize
, retval
);
1305 fp_drop(p
, fd
, fp
, 0);
1314 proc_security_policy(proc_t p
)
1316 kauth_cred_t my_cred
;
1319 my_cred
= kauth_cred_proc_ref(p
);
1320 uid
= kauth_cred_getuid(my_cred
) ;
1321 kauth_cred_unref(&my_cred
);
1323 if ((uid
!= kauth_cred_getuid(kauth_cred_get()))
1324 && suser(kauth_cred_get(), (u_short
*)0)) {
1332 proc_kernmsgbuf(user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
)
1334 if (suser(kauth_cred_get(), (u_short
*)0) == 0) {
1335 return(log_dmesg(buffer
, buffersize
, retval
));
1340 /* ********* process control sets on self only */
1342 proc_setcontrol(int pid
, int flavor
, uint64_t arg
, __unused user_addr_t buffer
, __unused
uint32_t buffersize
, __unused
int32_t * retval
)
1344 struct proc
* pself
= PROC_NULL
;
1346 uint32_t pcontrol
= (uint32_t)arg
;
1349 pself
= current_proc();
1350 if (pid
!= pself
->p_pid
)
1353 if (pcontrol
> P_PCMAX
)
1357 case PROC_SELFSET_PCONTROL
: {
1359 /* reset existing control setting while retaining action state */
1360 pself
->p_pcaction
&= PROC_ACTION_MASK
;
1361 /* set new control state */
1362 pself
->p_pcaction
|= pcontrol
;
1376 * copy stat64 structure into vinfo_stat structure.
1379 munge_vinfo_stat(struct stat64
*sbp
, struct vinfo_stat
*vsbp
)
1381 bzero(vsbp
, sizeof(struct vinfo_stat
));
1383 vsbp
->vst_dev
= sbp
->st_dev
;
1384 vsbp
->vst_mode
= sbp
->st_mode
;
1385 vsbp
->vst_nlink
= sbp
->st_nlink
;
1386 vsbp
->vst_ino
= sbp
->st_ino
;
1387 vsbp
->vst_uid
= sbp
->st_uid
;
1388 vsbp
->vst_gid
= sbp
->st_gid
;
1389 vsbp
->vst_atime
= sbp
->st_atimespec
.tv_sec
;
1390 vsbp
->vst_atimensec
= sbp
->st_atimespec
.tv_nsec
;
1391 vsbp
->vst_mtime
= sbp
->st_mtimespec
.tv_sec
;
1392 vsbp
->vst_mtimensec
= sbp
->st_mtimespec
.tv_nsec
;
1393 vsbp
->vst_ctime
= sbp
->st_ctimespec
.tv_sec
;
1394 vsbp
->vst_ctimensec
= sbp
->st_ctimespec
.tv_nsec
;
1395 vsbp
->vst_birthtime
= sbp
->st_birthtimespec
.tv_sec
;
1396 vsbp
->vst_birthtimensec
= sbp
->st_birthtimespec
.tv_nsec
;
1397 vsbp
->vst_size
= sbp
->st_size
;
1398 vsbp
->vst_blocks
= sbp
->st_blocks
;
1399 vsbp
->vst_blksize
= sbp
->st_blksize
;
1400 vsbp
->vst_flags
= sbp
->st_flags
;
1401 vsbp
->vst_gen
= sbp
->st_gen
;
1402 vsbp
->vst_rdev
= sbp
->st_rdev
;
1403 vsbp
->vst_qspare
[0] = sbp
->st_qspare
[0];
1404 vsbp
->vst_qspare
[1] = sbp
->st_qspare
[1];