2 * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
27 #include <sys/param.h>
28 #include <sys/systm.h>
29 #include <sys/kernel.h>
30 #include <sys/malloc.h>
31 #include <sys/proc_internal.h>
32 #include <sys/kauth.h>
33 #include <sys/file_internal.h>
34 #include <sys/vnode_internal.h>
35 #include <sys/unistd.h>
37 #include <sys/ioctl.h>
38 #include <sys/namei.h>
40 #include <sys/disklabel.h>
42 #include <sys/sysctl.h>
44 #include <sys/aio_kern.h>
46 #include <bsm/audit_kernel.h>
48 #include <mach/machine.h>
49 #include <mach/mach_types.h>
50 #include <mach/vm_param.h>
51 #include <kern/task.h>
52 #include <kern/lock.h>
53 #include <kern/kalloc.h>
54 #include <vm/vm_kern.h>
55 #include <vm/vm_map.h>
56 #include <mach/host_info.h>
57 #include <mach/task_info.h>
58 #include <mach/thread_info.h>
59 #include <mach/vm_region.h>
61 #include <sys/mount_internal.h>
62 #include <sys/proc_info.h>
63 #include <sys/bsdtask_info.h>
64 #include <sys/kdebug.h>
65 #include <sys/sysproto.h>
66 #include <sys/msgbuf.h>
69 #include <machine/machine_routines.h>
71 #include <vm/vm_protos.h>
79 int proc_info_internal(int callnum
, int pid
, int flavor
, uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, register_t
* retval
);
81 /* protos for proc_info calls */
82 int proc_listpids(uint32_t type
, uint32_t tyoneinfo
, user_addr_t buffer
, uint32_t buffersize
, register_t
* retval
);
83 int proc_pidinfo(int pid
, int flavor
, uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, register_t
* retval
);
84 int proc_pidfdinfo(int pid
, int flavor
,int fd
, user_addr_t buffer
, uint32_t buffersize
, register_t
* retval
);
85 int proc_kernmsgbuf(user_addr_t buffer
, uint32_t buffersize
, register_t
* retval
);
87 /* protos for procpidinfo calls */
88 int proc_pidfdlist(proc_t p
, user_addr_t buffer
, uint32_t buffersize
, register_t
*retval
);
89 int proc_pidbsdinfo(proc_t p
, struct proc_bsdinfo
*pbsd
);
90 int proc_pidtaskinfo(proc_t p
, struct proc_taskinfo
*ptinfo
);
91 int proc_pidallinfo(proc_t p
, int flavor
, uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, register_t
*retval
);
92 int proc_pidthreadinfo(proc_t p
, uint64_t arg
, struct proc_threadinfo
*pthinfo
);
93 int proc_pidlistthreads(proc_t p
, user_addr_t buffer
, uint32_t buffersize
, register_t
*retval
);
94 int proc_pidregioninfo(proc_t p
, uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, register_t
*retval
);
95 int proc_pidregionpathinfo(proc_t p
, uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, register_t
*retval
);
96 int proc_pidvnodepathinfo(proc_t p
, uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, register_t
*retval
);
99 /* protos for proc_pidfdinfo calls */
100 int pid_vnodeinfo(vnode_t vp
, uint32_t vid
, struct fileproc
* fp
, user_addr_t buffer
, uint32_t buffersize
, register_t
* retval
);
101 int pid_vnodeinfopath(vnode_t vp
, uint32_t vid
, struct fileproc
* fp
, user_addr_t buffer
, uint32_t buffersize
, register_t
* retval
);
102 int pid_socketinfo(socket_t so
, struct fileproc
*fp
, user_addr_t buffer
, uint32_t buffersize
, register_t
* retval
);
103 int pid_pseminfo(struct psemnode
* psem
, struct fileproc
* fp
, user_addr_t buffer
, uint32_t buffersize
, register_t
* retval
);
104 int pid_pshminfo(struct pshmnode
* pshm
, struct fileproc
* fp
, user_addr_t buffer
, uint32_t buffersize
, register_t
* retval
);
105 int pid_pipeinfo(struct pipe
* p
, struct fileproc
* fp
, user_addr_t buffer
, uint32_t buffersize
, register_t
* retval
);
106 int pid_kqueueinfo(struct kqueue
* kq
, struct fileproc
* fp
, user_addr_t buffer
, uint32_t buffersize
, register_t
* retval
);
107 int pid_atalkinfo(struct atalk
* at
, struct fileproc
* fp
, user_addr_t buffer
, uint32_t buffersize
, register_t
* retval
);
110 /* protos for misc */
112 int fill_vnodeinfo(vnode_t vp
, struct vnode_info
*vinfo
);
113 void fill_fileinfo(struct fileproc
* fp
, struct proc_fileinfo
* finfo
);
114 static int proc_security_policy(proc_t p
);
117 /***************************** proc_info ********************/
120 proc_info(__unused
struct proc
*p
, struct proc_info_args
* uap
, register_t
*retval
)
122 return(proc_info_internal(uap
->callnum
, uap
->pid
, uap
->flavor
, uap
->arg
, uap
->buffer
, uap
->buffersize
, retval
));
127 proc_info_internal(int callnum
, int pid
, int flavor
, uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, register_t
* retval
)
131 case 1: /* proc_listpids */
132 /* pid contains type and flavor contains typeinfo */
133 return(proc_listpids(pid
, flavor
, buffer
, buffersize
, retval
));
134 case 2: /* proc_pidinfo */
135 return(proc_pidinfo(pid
, flavor
, arg
, buffer
, buffersize
, retval
));
136 case 3: /* proc_pidfdinfo */
137 return(proc_pidfdinfo(pid
, flavor
, (int)arg
, buffer
, buffersize
, retval
));
138 case 4: /* proc_kernmsgbuf */
139 return(proc_kernmsgbuf( buffer
, buffersize
, retval
));
147 /******************* proc_listpids routine ****************/
149 proc_listpids(uint32_t type
, uint32_t typeinfo
, user_addr_t buffer
, uint32_t buffersize
, register_t
* retval
)
151 boolean_t funnel_state
;
152 int numprocs
, wantpids
;
159 /* if the buffer is null, return num of procs */
160 if (buffer
== (user_addr_t
)0) {
161 *retval
= ((nprocs
+20) * sizeof(int));
165 if (buffersize
< sizeof(int)) {
168 wantpids
= buffersize
/sizeof(int);
169 numprocs
= nprocs
+20;
170 if (numprocs
> wantpids
)
173 kbuf
= (char *)kalloc((vm_size_t
)(numprocs
* sizeof(int)));
174 bzero(kbuf
, sizeof(int));
176 funnel_state
= thread_funnel_set(kernel_flock
, TRUE
);
180 LIST_FOREACH(p
, &allproc
, p_list
) {
184 if (p
->p_pgrp
->pg_id
!= (pid_t
)typeinfo
)
191 if ((p
->p_flag
& P_CONTROLT
) == 0 ||
192 (p
->p_session
== NULL
) ||
193 p
->p_session
->s_ttyp
== NULL
||
194 p
->p_session
->s_ttyp
->t_dev
!= (dev_t
)typeinfo
)
198 if ((p
->p_ucred
== NULL
) ||
199 (kauth_cred_getuid(p
->p_ucred
) != (uid_t
)typeinfo
))
203 if ((p
->p_ucred
== NULL
) ||
204 (p
->p_ucred
->cr_ruid
!= (uid_t
)typeinfo
))
211 /* Do we have permission to look into this ? */
212 if (proc_security_policy(p
) != 0) {
225 LIST_FOREACH(p
, &zombproc
, p_list
) {
233 thread_funnel_set(kernel_flock
, funnel_state
);
236 error
= copyout((caddr_t
)ptr
, buffer
, n
* sizeof(int));
238 *retval
= (n
* sizeof(int));
239 kfree((void *)kbuf
, (vm_size_t
)(numprocs
* sizeof(int)));
245 /********************************** proc_pidinfo routines ********************************/
248 proc_pidfdlist(proc_t p
, user_addr_t buffer
, uint32_t buffersize
, register_t
*retval
)
252 struct proc_fdinfo
* pfd
;
253 struct fileproc
* fp
;
258 numfds
= p
->p_fd
->fd_nfiles
;
260 if (buffer
== (user_addr_t
) 0) {
262 *retval
= (numfds
* sizeof(struct proc_fdinfo
));
266 /* buffersize is big enough atleast for one struct */
267 needfds
= buffersize
/sizeof(struct proc_fdinfo
);
269 if (numfds
> needfds
)
272 kbuf
= (char *)kalloc((vm_size_t
)(numfds
* sizeof(struct proc_fdinfo
)));
273 bzero(kbuf
, numfds
* sizeof(struct proc_fdinfo
));
277 pfd
= (struct proc_fdinfo
*)kbuf
;
279 for (n
= 0; ((n
< numfds
) && (n
< p
->p_fd
->fd_nfiles
)); n
++) {
280 if (((fp
= p
->p_fd
->fd_ofiles
[n
]) != 0)
281 && ((p
->p_fd
->fd_ofileflags
[n
] & UF_RESERVED
) == 0)) {
283 pfd
->proc_fdtype
= fp
->f_fglob
->fg_type
;
290 error
= copyout(kbuf
, buffer
, count
* sizeof(struct proc_fdinfo
));
291 kfree((void *)kbuf
, (vm_size_t
)(numfds
* sizeof(struct proc_fdinfo
)));
293 *retval
= (count
* sizeof(struct proc_fdinfo
));
299 proc_pidbsdinfo(proc_t p
, struct proc_bsdinfo
* pbsd
)
301 register struct tty
*tp
;
302 struct session
*sessionp
= NULL
;
304 bzero(pbsd
, sizeof(struct proc_bsdinfo
));
305 pbsd
->pbi_status
= p
->p_stat
;
306 pbsd
->pbi_xstatus
= p
->p_xstat
;
307 pbsd
->pbi_pid
= p
->p_pid
;
308 pbsd
->pbi_ppid
= p
->p_pptr
->p_pid
;
309 pbsd
->pbi_uid
= p
->p_ucred
->cr_uid
;
310 pbsd
->pbi_gid
= p
->p_ucred
->cr_uid
; /* XXX */
311 pbsd
->pbi_ruid
= p
->p_ucred
->cr_ruid
;
312 pbsd
->pbi_rgid
= p
->p_ucred
->cr_rgid
;
313 pbsd
->pbi_svuid
= p
->p_ucred
->cr_svuid
;
314 pbsd
->pbi_svgid
= p
->p_ucred
->cr_svgid
;
316 pbsd
->pbi_nice
= p
->p_nice
;
318 pbsd
->pbi_start
= p
->p_stats
->p_start
;
319 bcopy(&p
->p_comm
, &pbsd
->pbi_comm
[0], MAXCOMLEN
);
320 bcopy(&p
->p_name
, &pbsd
->pbi_name
[0], 2* MAXCOMLEN
);
323 if ((p
->p_flag
& P_SYSTEM
) == P_SYSTEM
)
324 pbsd
->pbi_flags
|= PROC_FLAG_SYSTEM
;
325 if ((p
->p_flag
& P_TRACED
) == P_TRACED
)
326 pbsd
->pbi_flags
|= PROC_FLAG_TRACED
;
327 if ((p
->p_flag
& P_WEXIT
) == P_WEXIT
)
328 pbsd
->pbi_flags
|= PROC_FLAG_INEXIT
;
329 if ((p
->p_flag
& P_PPWAIT
) == P_PPWAIT
)
330 pbsd
->pbi_flags
|= PROC_FLAG_PPWAIT
;
331 if ((p
->p_flag
& P_LP64
) == P_LP64
)
332 pbsd
->pbi_flags
|= PROC_FLAG_LP64
;
333 if ((p
->p_flag
& P_CONTROLT
) == P_CONTROLT
)
334 pbsd
->pbi_flags
|= PROC_FLAG_CONTROLT
;
337 pbsd
->pbi_flags
|= PROC_FLAG_SLEADER
;
338 if (p
->p_pgrp
->pg_session
&& p
->p_pgrp
->pg_session
->s_ttyvp
)
339 pbsd
->pbi_flags
|= PROC_FLAG_CTTY
;
341 pbsd
->pbi_nfiles
= p
->p_fd
->fd_nfiles
;
343 sessionp
= p
->p_pgrp
->pg_session
;
344 pbsd
->pbi_pgid
= p
->p_pgrp
->pg_id
;
345 pbsd
->pbi_pjobc
= p
->p_pgrp
->pg_jobc
;
346 if ((p
->p_flag
& P_CONTROLT
) && (sessionp
) && (tp
= sessionp
->s_ttyp
)) {
347 pbsd
->e_tdev
= tp
->t_dev
;
348 pbsd
->e_tpgid
= tp
->t_pgrp
? tp
->t_pgrp
->pg_id
: 0;
356 proc_pidtaskinfo(proc_t p
, struct proc_taskinfo
* ptinfo
)
362 bzero(ptinfo
, sizeof(struct proc_taskinfo
));
363 fill_taskprocinfo(task
, (struct proc_taskinfo_internal
*)ptinfo
);
371 proc_pidthreadinfo(proc_t p
, uint64_t arg
, struct proc_threadinfo
*pthinfo
)
374 uint64_t threadaddr
= (uint64_t)arg
;
376 bzero(pthinfo
, sizeof(struct proc_threadinfo
));
378 error
= fill_taskthreadinfo(p
->task
, threadaddr
, (struct proc_threadinfo_internal
*)pthinfo
);
388 proc_pidlistthreads(proc_t p
, user_addr_t buffer
, uint32_t buffersize
, register_t
*retval
)
397 count
= buffersize
/(sizeof(uint64_t));
398 numthreads
= get_numthreads(p
->task
);
402 if (numthreads
> count
)
405 kbuf
= (void *)kalloc(numthreads
* sizeof(uint64_t));
406 bzero(kbuf
, numthreads
* sizeof(uint64_t));
408 ret
= fill_taskthreadlist(p
->task
, kbuf
, numthreads
);
410 error
= copyout(kbuf
, buffer
, ret
);
411 kfree(kbuf
, numthreads
* sizeof(uint64_t));
420 proc_pidregioninfo(proc_t p
, uint64_t arg
, user_addr_t buffer
, __unused
uint32_t buffersize
, register_t
*retval
)
422 struct proc_regioninfo preginfo
;
425 bzero(&preginfo
, sizeof(struct proc_regioninfo
));
426 ret
= fill_procregioninfo( p
->task
, arg
, (struct proc_regioninfo_internal
*)&preginfo
, (uint32_t *)0, (uint32_t *)0);
429 error
= copyout(&preginfo
, buffer
, sizeof(struct proc_regioninfo
));
431 *retval
= sizeof(struct proc_regioninfo
);
437 proc_pidregionpathinfo(proc_t p
, uint64_t arg
, user_addr_t buffer
, __unused
uint32_t buffersize
, register_t
*retval
)
439 struct proc_regionwithpathinfo preginfo
;
441 uint32_t vnodeaddr
= 0;
446 bzero(&preginfo
, sizeof(struct proc_regionwithpathinfo
));
448 ret
= fill_procregioninfo( p
->task
, arg
, (struct proc_regioninfo_internal
*)&preginfo
.prp_prinfo
, (uint32_t *)&vnodeaddr
, (uint32_t *)&vnodeid
);
452 vp
= (vnode_t
)vnodeaddr
;
453 if ((vnode_getwithvid(vp
, vnodeid
)) == 0) {
454 /* FILL THE VNODEINFO */
455 error
= fill_vnodeinfo(vp
, &preginfo
.prp_vip
.vip_vi
);
457 vn_getpath(vp
, &preginfo
.prp_vip
.vip_path
[0], &count
);
458 /* Always make sure it is null terminated */
459 preginfo
.prp_vip
.vip_path
[MAXPATHLEN
-1] = 0;
463 error
= copyout(&preginfo
, buffer
, sizeof(struct proc_regionwithpathinfo
));
465 *retval
= sizeof(struct proc_regionwithpathinfo
);
470 proc_pidvnodepathinfo(proc_t p
, __unused
uint64_t arg
, user_addr_t buffer
, __unused
uint32_t buffersize
, register_t
*retval
)
472 struct proc_vnodepathinfo pvninfo
;
474 vnode_t vncdirvp
= NULLVP
;
476 vnode_t vnrdirvp
= NULLVP
;
480 bzero(&pvninfo
, sizeof(struct proc_vnodepathinfo
));
483 if (p
->p_fd
->fd_cdir
) {
484 vncdirvp
= p
->p_fd
->fd_cdir
;
485 vncdirid
= p
->p_fd
->fd_cdir
->v_id
;
487 if (p
->p_fd
->fd_rdir
) {
488 vnrdirvp
= p
->p_fd
->fd_rdir
;
489 vnrdirid
= p
->p_fd
->fd_rdir
->v_id
;
493 if (vncdirvp
!= NULLVP
) {
494 if ((error
= vnode_getwithvid(vncdirvp
, vncdirid
)) == 0) {
495 /* FILL THE VNODEINFO */
496 error
= fill_vnodeinfo(vncdirvp
, &pvninfo
.pvi_cdir
.vip_vi
);
499 vn_getpath(vncdirvp
, &pvninfo
.pvi_cdir
.vip_path
[0], &count
);
500 pvninfo
.pvi_cdir
.vip_path
[MAXPATHLEN
-1] = 0;
508 if ((error
== 0) && (vnrdirvp
!= NULLVP
)) {
509 if ((error
= vnode_getwithvid(vnrdirvp
, vnrdirid
)) == 0) {
510 /* FILL THE VNODEINFO */
511 error
= fill_vnodeinfo(vnrdirvp
, &pvninfo
.pvi_rdir
.vip_vi
);
514 vn_getpath(vnrdirvp
, &pvninfo
.pvi_rdir
.vip_path
[0], &count
);
515 pvninfo
.pvi_rdir
.vip_path
[MAXPATHLEN
-1] = 0;
523 error
= copyout(&pvninfo
, buffer
, sizeof(struct proc_vnodepathinfo
));
525 *retval
= sizeof(struct proc_vnodepathinfo
);
531 /********************************** proc_pidinfo ********************************/
535 proc_pidinfo(int pid
, int flavor
, uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, register_t
* retval
)
537 struct proc
* p
= PROC_NULL
;
541 boolean_t funnel_state
;
545 case PROC_PIDLISTFDS
:
546 size
= PROC_PIDLISTFD_SIZE
;
547 if (buffer
== (user_addr_t
)0)
550 case PROC_PIDTBSDINFO
:
551 size
= PROC_PIDTBSDINFO_SIZE
;
553 case PROC_PIDTASKINFO
:
554 size
= PROC_PIDTASKINFO_SIZE
;
556 case PROC_PIDTASKALLINFO
:
557 size
= PROC_PIDTASKALLINFO_SIZE
;
559 case PROC_PIDTHREADINFO
:
560 size
= PROC_PIDTHREADINFO_SIZE
;
562 case PROC_PIDLISTTHREADS
:
563 size
= PROC_PIDLISTTHREADS_SIZE
;
565 case PROC_PIDREGIONINFO
:
566 size
= PROC_PIDREGIONINFO_SIZE
;
568 case PROC_PIDREGIONPATHINFO
:
569 size
= PROC_PIDREGIONPATHINFO_SIZE
;
571 case PROC_PIDVNODEPATHINFO
:
572 size
= PROC_PIDVNODEPATHINFO_SIZE
;
578 if (buffersize
< size
)
581 if (flavor
!= PROC_PIDTBSDINFO
) {
582 if ((p
= proc_findref(pid
)) == PROC_NULL
) {
588 /* Do we have permission to look into this ? */
589 if ((error
= proc_security_policy(p
)) != 0) {
595 case PROC_PIDLISTFDS
: {
596 error
= proc_pidfdlist(p
, buffer
, buffersize
, retval
);
600 case PROC_PIDTBSDINFO
: {
601 struct proc_bsdinfo pbsd
;
605 funnel_state
= thread_funnel_set(kernel_flock
, TRUE
);
607 if (p
== PROC_NULL
) {
612 thread_funnel_set(kernel_flock
, funnel_state
);
616 /* Do we have permission to look into this ? */
617 if ((error
= proc_security_policy(p
)) != 0) {
618 thread_funnel_set(kernel_flock
, funnel_state
);
621 error
= proc_pidbsdinfo(p
, &pbsd
);
622 thread_funnel_set(kernel_flock
, funnel_state
);
624 error
= copyout(&pbsd
, buffer
, sizeof(struct proc_bsdinfo
));
626 *retval
= sizeof(struct proc_bsdinfo
);
631 case PROC_PIDTASKINFO
: {
632 struct proc_taskinfo ptinfo
;
634 error
= proc_pidtaskinfo(p
, &ptinfo
);
636 error
= copyout(&ptinfo
, buffer
, sizeof(struct proc_taskinfo
));
638 *retval
= sizeof(struct proc_taskinfo
);
643 case PROC_PIDTASKALLINFO
: {
644 struct proc_taskallinfo pall
;
646 error
= proc_pidbsdinfo(p
, &pall
.pbsd
);
647 error
= proc_pidtaskinfo(p
, &pall
.ptinfo
);
649 error
= copyout(&pall
, buffer
, sizeof(struct proc_taskallinfo
));
651 *retval
= sizeof(struct proc_taskallinfo
);
656 case PROC_PIDTHREADINFO
:{
657 struct proc_threadinfo pthinfo
;
659 error
= proc_pidthreadinfo(p
, arg
, &pthinfo
);
661 error
= copyout(&pthinfo
, buffer
, sizeof(struct proc_threadinfo
));
663 *retval
= sizeof(struct proc_threadinfo
);
668 case PROC_PIDLISTTHREADS
:{
669 error
= proc_pidlistthreads(p
, buffer
, buffersize
, retval
);
673 case PROC_PIDREGIONINFO
:{
674 error
= proc_pidregioninfo(p
, arg
, buffer
, buffersize
, retval
);
679 case PROC_PIDREGIONPATHINFO
:{
680 error
= proc_pidregionpathinfo(p
, arg
, buffer
, buffersize
, retval
);
684 case PROC_PIDVNODEPATHINFO
:{
685 error
= proc_pidvnodepathinfo(p
, arg
, buffer
, buffersize
, retval
);
701 pid_vnodeinfo(vnode_t vp
, uint32_t vid
, struct fileproc
* fp
, user_addr_t buffer
, __unused
uint32_t buffersize
, register_t
* retval
)
703 struct vnode_fdinfo vfi
;
706 if ((error
= vnode_getwithvid(vp
, vid
)) != 0) {
709 bzero(&vfi
, sizeof(struct vnode_fdinfo
));
710 fill_fileinfo(fp
, &vfi
.pfi
);
711 error
= fill_vnodeinfo(vp
, &vfi
.pvi
);
714 error
= copyout((caddr_t
)&vfi
, buffer
, sizeof(struct vnode_fdinfo
));
716 *retval
= sizeof(struct vnode_fdinfo
);
722 pid_vnodeinfopath(vnode_t vp
, uint32_t vid
, struct fileproc
* fp
, user_addr_t buffer
, __unused
uint32_t buffersize
, register_t
* retval
)
724 struct vnode_fdinfowithpath vfip
;
727 if ((error
= vnode_getwithvid(vp
, vid
)) != 0) {
730 bzero(&vfip
, sizeof(struct vnode_fdinfowithpath
));
731 fill_fileinfo(fp
, &vfip
.pfi
);
732 error
= fill_vnodeinfo(vp
, &vfip
.pvip
.vip_vi
) ;
735 vn_getpath(vp
, &vfip
.pvip
.vip_path
[0], &count
);
736 vfip
.pvip
.vip_path
[MAXPATHLEN
-1] = 0;
738 error
= copyout((caddr_t
)&vfip
, buffer
, sizeof(struct vnode_fdinfowithpath
));
740 *retval
= sizeof(struct vnode_fdinfowithpath
);
747 fill_fileinfo(struct fileproc
* fp
, struct proc_fileinfo
* fproc
)
749 fproc
->fi_openflags
= fp
->f_fglob
->fg_flag
;
750 fproc
->fi_status
= fp
->f_flags
;
751 fproc
->fi_offset
= fp
->f_fglob
->fg_offset
;
752 fproc
->fi_type
= fp
->f_fglob
->fg_type
;
758 fill_vnodeinfo(vnode_t vp
, struct vnode_info
*vinfo
)
760 vfs_context_t context
;
764 sb
= &vinfo
->vi_stat
;
766 context
= vfs_context_create((vfs_context_t
)0);
767 error
= vn_stat(vp
, sb
, NULL
, context
);
768 (void)vfs_context_rele(context
);
773 if (vp
->v_mount
!= dead_mountp
) {
774 vinfo
->vi_fsid
= vp
->v_mount
->mnt_vfsstat
.f_fsid
;
776 vinfo
->vi_fsid
.val
[0] = 0;
777 vinfo
->vi_fsid
.val
[1] = 0;
779 vinfo
->vi_type
= vp
->v_type
;
785 pid_socketinfo(socket_t so
, struct fileproc
*fp
, user_addr_t buffer
, __unused
uint32_t buffersize
, register_t
* retval
)
787 struct socket_fdinfo s
;
790 bzero(&s
, sizeof(struct socket_fdinfo
));
791 fill_fileinfo(fp
, &s
.pfi
);
792 if ((error
= fill_socketinfo(so
, &s
.psi
)) == 0) {
793 if ((error
= copyout(&s
, buffer
, sizeof(struct socket_fdinfo
))) == 0)
794 *retval
= sizeof(struct socket_fdinfo
);
801 pid_pseminfo(struct psemnode
*psem
, struct fileproc
*fp
, user_addr_t buffer
, __unused
uint32_t buffersize
, register_t
* retval
)
803 struct psem_fdinfo pseminfo
;
806 bzero(&pseminfo
, sizeof(struct psem_fdinfo
));
807 fill_fileinfo(fp
, &pseminfo
.pfi
);
809 if ((error
= fill_pseminfo(psem
, &pseminfo
.pseminfo
)) == 0) {
810 if ((error
= copyout(&pseminfo
, buffer
, sizeof(struct psem_fdinfo
))) == 0)
811 *retval
= sizeof(struct psem_fdinfo
);
818 pid_pshminfo(struct pshmnode
*pshm
, struct fileproc
*fp
, user_addr_t buffer
, __unused
uint32_t buffersize
, register_t
* retval
)
820 struct pshm_fdinfo pshminfo
;
823 bzero(&pshminfo
, sizeof(struct pshm_fdinfo
));
824 fill_fileinfo(fp
, &pshminfo
.pfi
);
826 if ((error
= fill_pshminfo(pshm
, &pshminfo
.pshminfo
)) == 0) {
827 if ((error
= copyout(&pshminfo
, buffer
, sizeof(struct pshm_fdinfo
))) == 0)
828 *retval
= sizeof(struct pshm_fdinfo
);
835 pid_pipeinfo(struct pipe
* p
, struct fileproc
*fp
, user_addr_t buffer
, __unused
uint32_t buffersize
, register_t
* retval
)
837 struct pipe_fdinfo pipeinfo
;
840 bzero(&pipeinfo
, sizeof(struct pipe_fdinfo
));
841 fill_fileinfo(fp
, &pipeinfo
.pfi
);
842 if ((error
= fill_pipeinfo(p
, &pipeinfo
.pipeinfo
)) == 0) {
843 if ((error
= copyout(&pipeinfo
, buffer
, sizeof(struct pipe_fdinfo
))) == 0)
844 *retval
= sizeof(struct pipe_fdinfo
);
851 pid_kqueueinfo(struct kqueue
* kq
, struct fileproc
*fp
, user_addr_t buffer
, __unused
uint32_t buffersize
, register_t
* retval
)
853 struct kqueue_fdinfo kqinfo
;
856 bzero(&kqinfo
, sizeof(struct kqueue_fdinfo
));
858 fill_fileinfo(fp
, &kqinfo
.pfi
);
860 if ((error
= fill_kqueueinfo(kq
, &kqinfo
.kqueueinfo
)) == 0) {
861 if ((error
= copyout(&kqinfo
, buffer
, sizeof(struct kqueue_fdinfo
))) == 0)
862 *retval
= sizeof(struct kqueue_fdinfo
);
869 pid_atalkinfo(__unused
struct atalk
* at
, __unused
struct fileproc
*fp
, __unused user_addr_t buffer
, __unused
uint32_t buffersize
, __unused register_t
* retval
)
876 /************************** proc_pidfdinfo routine ***************************/
878 proc_pidfdinfo(int pid
, int flavor
, int fd
, user_addr_t buffer
, uint32_t buffersize
, register_t
* retval
)
882 struct fileproc
* fp
;
887 case PROC_PIDFDVNODEINFO
:
888 size
= PROC_PIDFDVNODEINFO_SIZE
;
890 case PROC_PIDFDVNODEPATHINFO
:
891 size
= PROC_PIDFDVNODEPATHINFO_SIZE
;
893 case PROC_PIDFDSOCKETINFO
:
894 size
= PROC_PIDFDSOCKETINFO_SIZE
;
896 case PROC_PIDFDPSEMINFO
:
897 size
= PROC_PIDFDPSEMINFO_SIZE
;
899 case PROC_PIDFDPSHMINFO
:
900 size
= PROC_PIDFDPSHMINFO_SIZE
;
902 case PROC_PIDFDPIPEINFO
:
903 size
= PROC_PIDFDPIPEINFO_SIZE
;
905 case PROC_PIDFDKQUEUEINFO
:
906 size
= PROC_PIDFDKQUEUEINFO_SIZE
;
908 case PROC_PIDFDATALKINFO
:
909 size
= PROC_PIDFDATALKINFO_SIZE
;
917 if (buffersize
< size
)
920 if ((p
= proc_findref(pid
)) == PROC_NULL
) {
924 /* Do we have permission to look into this ? */
925 if ((error
= proc_security_policy(p
)) != 0) {
930 case PROC_PIDFDVNODEINFO
: {
934 if ((error
= fp_getfvpandvid(p
, fd
, &fp
, &vp
, &vid
)) !=0) {
937 error
= pid_vnodeinfo(vp
, vid
, fp
, buffer
, buffersize
, retval
);
941 case PROC_PIDFDVNODEPATHINFO
: {
945 if ((error
= fp_getfvpandvid(p
, fd
, &fp
, &vp
, &vid
)) !=0) {
949 error
= pid_vnodeinfopath(vp
, vid
, fp
, buffer
, buffersize
, retval
);
953 case PROC_PIDFDSOCKETINFO
: {
956 if ((error
= fp_getfsock(p
, fd
, &fp
, &so
)) !=0) {
959 error
= pid_socketinfo(so
, fp
, buffer
, buffersize
, retval
);
963 case PROC_PIDFDPSEMINFO
: {
964 struct psemnode
* psem
;
966 if ((error
= fp_getfpsem(p
, fd
, &fp
, &psem
)) !=0) {
969 error
= pid_pseminfo(psem
, fp
, buffer
, buffersize
, retval
);
973 case PROC_PIDFDPSHMINFO
: {
974 struct pshmnode
* pshm
;
976 if ((error
= fp_getfpshm(p
, fd
, &fp
, &pshm
)) !=0) {
979 error
= pid_pshminfo(pshm
, fp
, buffer
, buffersize
, retval
);
983 case PROC_PIDFDPIPEINFO
: {
986 if ((error
= fp_getfpipe(p
, fd
, &fp
, &cpipe
)) !=0) {
989 error
= pid_pipeinfo(cpipe
, fp
, buffer
, buffersize
, retval
);
993 case PROC_PIDFDKQUEUEINFO
: {
996 if ((error
= fp_getfkq(p
, fd
, &fp
, &kq
)) !=0) {
999 error
= pid_kqueueinfo(kq
, fp
, buffer
, buffersize
, retval
);
1003 case PROC_PIDFDATALKINFO
: {
1006 if ((error
= fp_getfatalk(p
, fd
, &fp
, &at
)) !=0) {
1010 error
= pid_atalkinfo(at
, fp
, buffer
, buffersize
, retval
);
1021 fp_drop(p
, fd
, fp
, 0);
1030 proc_security_policy(proc_t p
)
1032 if ((kauth_cred_getuid(p
->p_ucred
) != kauth_cred_getuid(kauth_cred_get()))
1033 && suser(kauth_cred_get(), (u_short
*)0)) {
1041 /* Temporary hack to get dmesg to work. In Leopard this will disappear */
1043 proc_kernmsgbuf(user_addr_t buffer
, uint32_t buffersize
, register_t
* retval
)
1047 if (buffersize
< sizeof(struct msgbuf
))
1050 if (suser(kauth_cred_get(), (u_short
*)0) == 0) {
1051 error
= copyout(msgbufp
, buffer
, sizeof(struct msgbuf
));
1053 *retval
= sizeof(struct msgbuf
);