2 * Copyright (c) 2005-2013 Apple 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>
51 #include <sys/kern_memorystatus.h>
53 #include <security/audit/audit.h>
55 #include <mach/machine.h>
56 #include <mach/mach_types.h>
57 #include <mach/vm_param.h>
58 #include <kern/task.h>
59 #include <kern/kalloc.h>
60 #include <kern/assert.h>
61 #include <vm/vm_kern.h>
62 #include <vm/vm_map.h>
63 #include <mach/host_info.h>
64 #include <mach/task_info.h>
65 #include <mach/thread_info.h>
66 #include <mach/vm_region.h>
68 #include <sys/mount_internal.h>
69 #include <sys/proc_info.h>
70 #include <sys/bsdtask_info.h>
71 #include <sys/kdebug.h>
72 #include <sys/sysproto.h>
73 #include <sys/msgbuf.h>
76 #include <sys/guarded.h>
78 #include <machine/machine_routines.h>
80 #include <kern/ipc_misc.h>
82 #include <vm/vm_protos.h>
84 /* Needed by proc_pidnoteexit() */
85 #include <sys/event.h>
86 #include <sys/codesign.h>
88 /* Needed by proc_listcoalitions() */
89 #ifdef CONFIG_COALITIONS
90 #include <sys/coalition.h>
99 uint64_t get_dispatchqueue_offset_from_proc(void *);
100 uint64_t get_dispatchqueue_serialno_offset_from_proc(void *);
101 int proc_info_internal(int callnum
, int pid
, int flavor
, uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
);
104 * TODO: Replace the noinline attribute below. Currently, it serves
105 * to avoid stack bloat caused by inlining multiple functions that
106 * have large stack footprints; when the functions are independent
107 * of each other (will not both be called in any given call to the
108 * caller), this only serves to bloat the stack, as we allocate
109 * space for both functions, despite the fact that we only need a
110 * fraction of that space.
112 * Long term, these functions should not be allocating everything on
113 * the stack, and should move large allocations (the huge structs
114 * that proc info deals in) to the heap, or eliminate them if
117 * The functions that most desperately need to improve stack usage
118 * (starting with the worst offenders):
119 * proc_pidvnodepathinfo
121 * proc_pidregionpathinfo
127 * proc_pidoriginatorinfo
130 /* protos for proc_info calls */
131 int __attribute__ ((noinline
)) proc_listpids(uint32_t type
, uint32_t tyoneinfo
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
);
132 int __attribute__ ((noinline
)) proc_pidinfo(int pid
, int flavor
, uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
);
133 int __attribute__ ((noinline
)) proc_pidfdinfo(int pid
, int flavor
,int fd
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
);
134 int __attribute__ ((noinline
)) proc_kernmsgbuf(user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
);
135 int __attribute__ ((noinline
)) proc_setcontrol(int pid
, int flavor
, uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
);
136 int __attribute__ ((noinline
)) proc_pidfileportinfo(int pid
, int flavor
, mach_port_name_t name
, user_addr_t buffer
, uint32_t buffersize
, int32_t *retval
);
137 int __attribute__ ((noinline
)) proc_dirtycontrol(int pid
, int flavor
, uint64_t arg
, int32_t * retval
);
138 int __attribute__ ((noinline
)) proc_terminate(int pid
, int32_t * retval
);
139 int __attribute__ ((noinline
)) proc_pid_rusage(int pid
, int flavor
, user_addr_t buffer
, int32_t * retval
);
140 int __attribute__ ((noinline
)) proc_pidoriginatorinfo(int pid
, int flavor
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
);
141 int __attribute__ ((noinline
)) proc_listcoalitions(int flavor
, int coaltype
, user_addr_t buffer
, uint32_t buffersize
, int32_t *retval
);
143 /* protos for procpidinfo calls */
144 int __attribute__ ((noinline
)) proc_pidfdlist(proc_t p
, user_addr_t buffer
, uint32_t buffersize
, int32_t *retval
);
145 int __attribute__ ((noinline
)) proc_pidbsdinfo(proc_t p
, struct proc_bsdinfo
*pbsd
, int zombie
);
146 int __attribute__ ((noinline
)) proc_pidshortbsdinfo(proc_t p
, struct proc_bsdshortinfo
*pbsd_shortp
, int zombie
);
147 int __attribute__ ((noinline
)) proc_pidtaskinfo(proc_t p
, struct proc_taskinfo
*ptinfo
);
148 int __attribute__ ((noinline
)) proc_pidthreadinfo(proc_t p
, uint64_t arg
, int thuniqueid
, struct proc_threadinfo
*pthinfo
);
149 int __attribute__ ((noinline
)) proc_pidthreadpathinfo(proc_t p
, uint64_t arg
, struct proc_threadwithpathinfo
*pinfo
);
150 int __attribute__ ((noinline
)) proc_pidlistthreads(proc_t p
, user_addr_t buffer
, uint32_t buffersize
, int32_t *retval
);
151 int __attribute__ ((noinline
)) proc_pidregioninfo(proc_t p
, uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, int32_t *retval
);
152 int __attribute__ ((noinline
)) proc_pidregionpathinfo(proc_t p
, uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, int32_t *retval
);
153 int __attribute__ ((noinline
)) proc_pidregionpathinfo2(proc_t p
, uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, int32_t *retval
);
154 int __attribute__ ((noinline
)) proc_pidregionpathinfo3(proc_t p
, uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, int32_t *retval
);
155 int __attribute__ ((noinline
)) proc_pidvnodepathinfo(proc_t p
, uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, int32_t *retval
);
156 int __attribute__ ((noinline
)) proc_pidpathinfo(proc_t p
, uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, int32_t *retval
);
157 int __attribute__ ((noinline
)) proc_pidworkqueueinfo(proc_t p
, struct proc_workqueueinfo
*pwqinfo
);
158 int __attribute__ ((noinline
)) proc_pidfileportlist(proc_t p
, user_addr_t buffer
, uint32_t buffersize
, int32_t *retval
);
159 void __attribute__ ((noinline
)) proc_piduniqidentifierinfo(proc_t p
, struct proc_uniqidentifierinfo
*p_uniqidinfo
);
160 void __attribute__ ((noinline
)) proc_archinfo(proc_t p
, struct proc_archinfo
*pai
);
161 void __attribute__ ((noinline
)) proc_pidcoalitioninfo(proc_t p
, struct proc_pidcoalitioninfo
*pci
);
162 int __attribute__ ((noinline
)) proc_pidnoteexit(proc_t p
, uint64_t arg
, uint32_t *data
);
163 int __attribute__ ((noinline
)) proc_pidoriginatorpid_uuid(uuid_t uuid
, uint32_t buffersize
, pid_t
*pid
);
166 /* protos for proc_pidfdinfo calls */
167 int __attribute__ ((noinline
)) pid_vnodeinfo(vnode_t vp
, uint32_t vid
, struct fileproc
* fp
,proc_t proc
, int fd
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
);
168 int __attribute__ ((noinline
)) pid_vnodeinfopath(vnode_t vp
, uint32_t vid
, struct fileproc
* fp
,proc_t proc
, int fd
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
);
169 int __attribute__ ((noinline
)) pid_socketinfo(socket_t so
, struct fileproc
*fp
,proc_t proc
, int fd
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
);
170 int __attribute__ ((noinline
)) pid_pseminfo(struct psemnode
* psem
, struct fileproc
* fp
, proc_t proc
, int fd
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
);
171 int __attribute__ ((noinline
)) pid_pshminfo(struct pshmnode
* pshm
, struct fileproc
* fp
, proc_t proc
, int fd
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
);
172 int __attribute__ ((noinline
)) pid_pipeinfo(struct pipe
* p
, struct fileproc
* fp
, proc_t proc
, int fd
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
);
173 int __attribute__ ((noinline
)) pid_kqueueinfo(struct kqueue
* kq
, struct fileproc
* fp
, proc_t proc
, int fd
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
);
174 int __attribute__ ((noinline
)) pid_atalkinfo(struct atalk
* at
, struct fileproc
* fp
, proc_t proc
, int fd
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
);
177 /* protos for misc */
179 int fill_vnodeinfo(vnode_t vp
, struct vnode_info
*vinfo
);
180 void fill_fileinfo(struct fileproc
* fp
, proc_t proc
, int fd
, struct proc_fileinfo
* finfo
);
181 int proc_security_policy(proc_t targetp
, int callnum
, int flavor
, boolean_t check_same_user
);
182 static void munge_vinfo_stat(struct stat64
*sbp
, struct vinfo_stat
*vsbp
);
183 static int proc_piduuidinfo(pid_t pid
, uuid_t uuid_buf
, uint32_t buffersize
);
185 extern int cansignal(struct proc
*, kauth_cred_t
, struct proc
*, int, int);
186 extern int proc_get_rusage(proc_t proc
, int flavor
, user_addr_t buffer
, int is_zombie
);
188 #define CHECK_SAME_USER TRUE
189 #define NO_CHECK_SAME_USER FALSE
191 uint64_t get_dispatchqueue_offset_from_proc(void *p
)
194 proc_t pself
= (proc_t
)p
;
195 return (pself
->p_dispatchqueue_offset
);
201 uint64_t get_dispatchqueue_serialno_offset_from_proc(void *p
)
204 proc_t pself
= (proc_t
)p
;
205 return (pself
->p_dispatchqueue_serialno_offset
);
211 /***************************** proc_info ********************/
214 proc_info(__unused
struct proc
*p
, struct proc_info_args
* uap
, int32_t *retval
)
216 return(proc_info_internal(uap
->callnum
, uap
->pid
, uap
->flavor
, uap
->arg
, uap
->buffer
, uap
->buffersize
, retval
));
221 proc_info_internal(int callnum
, int pid
, int flavor
, uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
)
225 case PROC_INFO_CALL_LISTPIDS
:
226 /* pid contains type and flavor contains typeinfo */
227 return(proc_listpids(pid
, flavor
, buffer
, buffersize
, retval
));
228 case PROC_INFO_CALL_PIDINFO
:
229 return(proc_pidinfo(pid
, flavor
, arg
, buffer
, buffersize
, retval
));
230 case PROC_INFO_CALL_PIDFDINFO
:
231 return(proc_pidfdinfo(pid
, flavor
, (int)arg
, buffer
, buffersize
, retval
));
232 case PROC_INFO_CALL_KERNMSGBUF
:
233 return(proc_kernmsgbuf(buffer
, buffersize
, retval
));
234 case PROC_INFO_CALL_SETCONTROL
:
235 return(proc_setcontrol(pid
, flavor
, arg
, buffer
, buffersize
, retval
));
236 case PROC_INFO_CALL_PIDFILEPORTINFO
:
237 return(proc_pidfileportinfo(pid
, flavor
, (mach_port_name_t
)arg
, buffer
, buffersize
, retval
));
238 case PROC_INFO_CALL_TERMINATE
:
239 return(proc_terminate(pid
, retval
));
240 case PROC_INFO_CALL_DIRTYCONTROL
:
241 return(proc_dirtycontrol(pid
, flavor
, arg
, retval
));
242 case PROC_INFO_CALL_PIDRUSAGE
:
243 return (proc_pid_rusage(pid
, flavor
, buffer
, retval
));
244 case PROC_INFO_CALL_PIDORIGINATORINFO
:
245 return (proc_pidoriginatorinfo(pid
, flavor
, buffer
, buffersize
, retval
));
246 case PROC_INFO_CALL_LISTCOALITIONS
:
247 return proc_listcoalitions(pid
/* flavor */, flavor
/* coaltype */, buffer
,
256 /******************* proc_listpids routine ****************/
258 proc_listpids(uint32_t type
, uint32_t typeinfo
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
)
260 int numprocs
, wantpids
;
267 struct proclist
*current_list
;
269 /* Do we have permission to look into this? */
270 if ((error
= proc_security_policy(PROC_NULL
, PROC_INFO_CALL_LISTPIDS
, type
, NO_CHECK_SAME_USER
)))
273 /* if the buffer is null, return num of procs */
274 if (buffer
== (user_addr_t
)0) {
275 *retval
= ((nprocs
+20) * sizeof(int));
279 if (buffersize
< sizeof(int)) {
282 wantpids
= buffersize
/sizeof(int);
283 numprocs
= nprocs
+20;
284 if (numprocs
> wantpids
)
287 kbuf
= (char *)kalloc((vm_size_t
)(numprocs
* sizeof(int)));
290 bzero(kbuf
, sizeof(int));
297 current_list
= &allproc
;
299 LIST_FOREACH(p
, current_list
, p_list
) {
303 if (p
->p_pgrpid
!= (pid_t
)typeinfo
)
307 if ((p
->p_ppid
!= (pid_t
)typeinfo
) && (((p
->p_lflag
& P_LTRACED
) == 0) || (p
->p_oppid
!= (pid_t
)typeinfo
)))
315 /* racy but list lock is held */
316 if ((p
->p_flag
& P_CONTROLT
) == 0 ||
317 (p
->p_pgrp
== NULL
) || (p
->p_pgrp
->pg_session
== NULL
) ||
318 (tp
= SESSION_TP(p
->p_pgrp
->pg_session
)) == TTY_NULL
||
319 tp
->t_dev
!= (dev_t
)typeinfo
)
323 if (p
->p_ucred
== NULL
)
326 kauth_cred_t my_cred
;
329 my_cred
= kauth_cred_proc_ref(p
);
330 uid
= kauth_cred_getuid(my_cred
);
331 kauth_cred_unref(&my_cred
);
332 if (uid
!= (uid_t
)typeinfo
)
337 if (p
->p_ucred
== NULL
)
340 kauth_cred_t my_cred
;
343 my_cred
= kauth_cred_proc_ref(p
);
344 uid
= kauth_cred_getruid(my_cred
);
345 kauth_cred_unref(&my_cred
);
346 if (uid
!= (uid_t
)typeinfo
)
363 if ((n
< numprocs
) && (current_list
== &allproc
)) {
364 current_list
= &zombproc
;
371 error
= copyout((caddr_t
)ptr
, buffer
, n
* sizeof(int));
373 *retval
= (n
* sizeof(int));
374 kfree((void *)kbuf
, (vm_size_t
)(numprocs
* sizeof(int)));
380 /********************************** proc_pidfdlist routines ********************************/
383 proc_pidfdlist(proc_t p
, user_addr_t buffer
, uint32_t buffersize
, int32_t *retval
)
387 struct proc_fdinfo
* pfd
;
388 struct fileproc
* fp
;
393 numfds
= p
->p_fd
->fd_nfiles
;
395 if (buffer
== (user_addr_t
) 0) {
397 *retval
= (numfds
* sizeof(struct proc_fdinfo
));
401 /* buffersize is big enough atleast for one struct */
402 needfds
= buffersize
/sizeof(struct proc_fdinfo
);
404 if (numfds
> needfds
)
407 kbuf
= (char *)kalloc((vm_size_t
)(numfds
* sizeof(struct proc_fdinfo
)));
410 bzero(kbuf
, numfds
* sizeof(struct proc_fdinfo
));
414 pfd
= (struct proc_fdinfo
*)kbuf
;
416 for (n
= 0; ((n
< numfds
) && (n
< p
->p_fd
->fd_nfiles
)); n
++) {
417 if (((fp
= p
->p_fd
->fd_ofiles
[n
]) != 0)
418 && ((p
->p_fd
->fd_ofileflags
[n
] & UF_RESERVED
) == 0)) {
419 file_type_t fdtype
= FILEGLOB_DTYPE(fp
->f_fglob
);
421 pfd
->proc_fdtype
= (fdtype
!= DTYPE_ATALK
) ?
422 fdtype
: PROX_FDTYPE_ATALK
;
429 error
= copyout(kbuf
, buffer
, count
* sizeof(struct proc_fdinfo
));
430 kfree((void *)kbuf
, (vm_size_t
)(numfds
* sizeof(struct proc_fdinfo
)));
432 *retval
= (count
* sizeof(struct proc_fdinfo
));
437 * Helper functions for proc_pidfileportlist.
440 proc_fileport_count(__unused mach_port_name_t name
,
441 __unused
struct fileglob
*fg
, void *arg
)
443 uint32_t *counter
= arg
;
449 struct fileport_fdtype_args
{
450 struct proc_fileportinfo
*ffa_pfi
;
451 struct proc_fileportinfo
*ffa_pfi_end
;
455 proc_fileport_fdtype(mach_port_name_t name
, struct fileglob
*fg
, void *arg
)
457 struct fileport_fdtype_args
*ffa
= arg
;
459 if (ffa
->ffa_pfi
!= ffa
->ffa_pfi_end
) {
460 file_type_t fdtype
= FILEGLOB_DTYPE(fg
);
462 ffa
->ffa_pfi
->proc_fdtype
= (fdtype
!= DTYPE_ATALK
) ?
463 fdtype
: PROX_FDTYPE_ATALK
;
464 ffa
->ffa_pfi
->proc_fileport
= name
;
466 return (0); /* keep walking */
468 return (-1); /* stop the walk! */
472 proc_pidfileportlist(proc_t p
,
473 user_addr_t buffer
, uint32_t buffersize
, int32_t *retval
)
477 struct proc_fileportinfo
*pfi
;
478 uint32_t needfileports
, numfileports
;
479 struct fileport_fdtype_args ffa
;
482 needfileports
= buffersize
/ sizeof (*pfi
);
483 if ((user_addr_t
)0 == buffer
|| needfileports
> (uint32_t)maxfiles
) {
485 * Either (i) the user is asking for a fileport count,
486 * or (ii) the number of fileports they're asking for is
487 * larger than the maximum number of open files (!); count
488 * them to bound subsequent heap allocations.
491 switch (fileport_walk(p
->task
,
492 proc_fileport_count
, &numfileports
)) {
495 case KERN_RESOURCE_SHORTAGE
:
497 case KERN_INVALID_TASK
:
503 if (numfileports
== 0) {
504 *retval
= 0; /* none at all, bail */
507 if ((user_addr_t
)0 == buffer
) {
508 numfileports
+= 20; /* accelerate convergence */
509 *retval
= numfileports
* sizeof (*pfi
);
512 if (needfileports
> numfileports
)
513 needfileports
= numfileports
;
516 assert(buffersize
>= PROC_PIDLISTFILEPORTS_SIZE
);
518 kbufsize
= (vm_size_t
)needfileports
* sizeof (*pfi
);
519 pfi
= kbuf
= kalloc(kbufsize
);
522 bzero(kbuf
, kbufsize
);
525 ffa
.ffa_pfi_end
= pfi
+ needfileports
;
527 switch (fileport_walk(p
->task
, proc_fileport_fdtype
, &ffa
)) {
531 if ((numfileports
= pfi
- (typeof(pfi
))kbuf
) == 0)
533 if (numfileports
> needfileports
)
534 panic("more fileports returned than requested");
535 error
= copyout(kbuf
, buffer
, numfileports
* sizeof (*pfi
));
537 case KERN_RESOURCE_SHORTAGE
:
540 case KERN_INVALID_TASK
:
547 kfree(kbuf
, kbufsize
);
549 *retval
= numfileports
* sizeof (*pfi
);
554 proc_pidbsdinfo(proc_t p
, struct proc_bsdinfo
* pbsd
, int zombie
)
556 register struct tty
*tp
;
557 struct session
*sessionp
= NULL
;
559 kauth_cred_t my_cred
;
562 sessionp
= proc_session(p
);
564 my_cred
= kauth_cred_proc_ref(p
);
565 bzero(pbsd
, sizeof(struct proc_bsdinfo
));
566 pbsd
->pbi_status
= p
->p_stat
;
567 pbsd
->pbi_xstatus
= p
->p_xstat
;
568 pbsd
->pbi_pid
= p
->p_pid
;
569 pbsd
->pbi_ppid
= p
->p_ppid
;
570 pbsd
->pbi_uid
= kauth_cred_getuid(my_cred
);
571 pbsd
->pbi_gid
= kauth_cred_getgid(my_cred
);
572 pbsd
->pbi_ruid
= kauth_cred_getruid(my_cred
);
573 pbsd
->pbi_rgid
= kauth_cred_getrgid(my_cred
);
574 pbsd
->pbi_svuid
= kauth_cred_getsvuid(my_cred
);
575 pbsd
->pbi_svgid
= kauth_cred_getsvgid(my_cred
);
576 kauth_cred_unref(&my_cred
);
578 pbsd
->pbi_nice
= p
->p_nice
;
579 pbsd
->pbi_start_tvsec
= p
->p_start
.tv_sec
;
580 pbsd
->pbi_start_tvusec
= p
->p_start
.tv_usec
;
581 bcopy(&p
->p_comm
, &pbsd
->pbi_comm
[0], MAXCOMLEN
);
582 pbsd
->pbi_comm
[MAXCOMLEN
- 1] = '\0';
583 bcopy(&p
->p_name
, &pbsd
->pbi_name
[0], 2*MAXCOMLEN
);
584 pbsd
->pbi_name
[(2*MAXCOMLEN
) - 1] = '\0';
587 if ((p
->p_flag
& P_SYSTEM
) == P_SYSTEM
)
588 pbsd
->pbi_flags
|= PROC_FLAG_SYSTEM
;
589 if ((p
->p_lflag
& P_LTRACED
) == P_LTRACED
)
590 pbsd
->pbi_flags
|= PROC_FLAG_TRACED
;
591 if ((p
->p_lflag
& P_LEXIT
) == P_LEXIT
)
592 pbsd
->pbi_flags
|= PROC_FLAG_INEXIT
;
593 if ((p
->p_lflag
& P_LPPWAIT
) == P_LPPWAIT
)
594 pbsd
->pbi_flags
|= PROC_FLAG_PPWAIT
;
595 if ((p
->p_flag
& P_LP64
) == P_LP64
)
596 pbsd
->pbi_flags
|= PROC_FLAG_LP64
;
597 if ((p
->p_flag
& P_CONTROLT
) == P_CONTROLT
)
598 pbsd
->pbi_flags
|= PROC_FLAG_CONTROLT
;
599 if ((p
->p_flag
& P_THCWD
) == P_THCWD
)
600 pbsd
->pbi_flags
|= PROC_FLAG_THCWD
;
601 if ((p
->p_flag
& P_SUGID
) == P_SUGID
)
602 pbsd
->pbi_flags
|= PROC_FLAG_PSUGID
;
603 if ((p
->p_flag
& P_EXEC
) == P_EXEC
)
604 pbsd
->pbi_flags
|= PROC_FLAG_EXEC
;
606 if (sessionp
!= SESSION_NULL
) {
607 if (SESS_LEADER(p
, sessionp
))
608 pbsd
->pbi_flags
|= PROC_FLAG_SLEADER
;
609 if (sessionp
->s_ttyvp
)
610 pbsd
->pbi_flags
|= PROC_FLAG_CTTY
;
613 if ((p
->p_flag
& P_DELAYIDLESLEEP
) == P_DELAYIDLESLEEP
)
614 pbsd
->pbi_flags
|= PROC_FLAG_DELAYIDLESLEEP
;
616 switch(PROC_CONTROL_STATE(p
)) {
618 pbsd
->pbi_flags
|= PROC_FLAG_PC_THROTTLE
;
621 pbsd
->pbi_flags
|= PROC_FLAG_PC_SUSP
;
624 pbsd
->pbi_flags
|= PROC_FLAG_PC_KILL
;
628 switch(PROC_ACTION_STATE(p
)) {
630 pbsd
->pbi_flags
|= PROC_FLAG_PA_THROTTLE
;
633 pbsd
->pbi_flags
|= PROC_FLAG_PA_SUSP
;
637 /* if process is a zombie skip bg state */
638 if ((zombie
== 0) && (p
->p_stat
!= SZOMB
) && (p
->task
!= TASK_NULL
))
639 proc_get_darwinbgstate(p
->task
, &pbsd
->pbi_flags
);
642 pbsd
->pbi_nfiles
= p
->p_fd
->fd_nfiles
;
644 pbsd
->e_tdev
= NODEV
;
645 if (pg
!= PGRP_NULL
) {
646 pbsd
->pbi_pgid
= p
->p_pgrpid
;
647 pbsd
->pbi_pjobc
= pg
->pg_jobc
;
648 if ((p
->p_flag
& P_CONTROLT
) && (sessionp
!= SESSION_NULL
) && (tp
= SESSION_TP(sessionp
))) {
649 pbsd
->e_tdev
= tp
->t_dev
;
650 pbsd
->e_tpgid
= sessionp
->s_ttypgrpid
;
653 if (sessionp
!= SESSION_NULL
)
654 session_rele(sessionp
);
663 proc_pidshortbsdinfo(proc_t p
, struct proc_bsdshortinfo
* pbsd_shortp
, int zombie
)
665 bzero(pbsd_shortp
, sizeof(struct proc_bsdshortinfo
));
666 pbsd_shortp
->pbsi_pid
= p
->p_pid
;
667 pbsd_shortp
->pbsi_ppid
= p
->p_ppid
;
668 pbsd_shortp
->pbsi_pgid
= p
->p_pgrpid
;
669 pbsd_shortp
->pbsi_status
= p
->p_stat
;
670 bcopy(&p
->p_comm
, &pbsd_shortp
->pbsi_comm
[0], MAXCOMLEN
);
671 pbsd_shortp
->pbsi_comm
[MAXCOMLEN
- 1] = '\0';
673 pbsd_shortp
->pbsi_flags
= 0;
674 if ((p
->p_flag
& P_SYSTEM
) == P_SYSTEM
)
675 pbsd_shortp
->pbsi_flags
|= PROC_FLAG_SYSTEM
;
676 if ((p
->p_lflag
& P_LTRACED
) == P_LTRACED
)
677 pbsd_shortp
->pbsi_flags
|= PROC_FLAG_TRACED
;
678 if ((p
->p_lflag
& P_LEXIT
) == P_LEXIT
)
679 pbsd_shortp
->pbsi_flags
|= PROC_FLAG_INEXIT
;
680 if ((p
->p_lflag
& P_LPPWAIT
) == P_LPPWAIT
)
681 pbsd_shortp
->pbsi_flags
|= PROC_FLAG_PPWAIT
;
682 if ((p
->p_flag
& P_LP64
) == P_LP64
)
683 pbsd_shortp
->pbsi_flags
|= PROC_FLAG_LP64
;
684 if ((p
->p_flag
& P_CONTROLT
) == P_CONTROLT
)
685 pbsd_shortp
->pbsi_flags
|= PROC_FLAG_CONTROLT
;
686 if ((p
->p_flag
& P_THCWD
) == P_THCWD
)
687 pbsd_shortp
->pbsi_flags
|= PROC_FLAG_THCWD
;
688 if ((p
->p_flag
& P_SUGID
) == P_SUGID
)
689 pbsd_shortp
->pbsi_flags
|= PROC_FLAG_PSUGID
;
690 if ((p
->p_flag
& P_EXEC
) == P_EXEC
)
691 pbsd_shortp
->pbsi_flags
|= PROC_FLAG_EXEC
;
692 if ((p
->p_flag
& P_DELAYIDLESLEEP
) == P_DELAYIDLESLEEP
)
693 pbsd_shortp
->pbsi_flags
|= PROC_FLAG_DELAYIDLESLEEP
;
695 switch(PROC_CONTROL_STATE(p
)) {
697 pbsd_shortp
->pbsi_flags
|= PROC_FLAG_PC_THROTTLE
;
700 pbsd_shortp
->pbsi_flags
|= PROC_FLAG_PC_SUSP
;
703 pbsd_shortp
->pbsi_flags
|= PROC_FLAG_PC_KILL
;
707 switch(PROC_ACTION_STATE(p
)) {
709 pbsd_shortp
->pbsi_flags
|= PROC_FLAG_PA_THROTTLE
;
712 pbsd_shortp
->pbsi_flags
|= PROC_FLAG_PA_SUSP
;
716 /* if process is a zombie skip bg state */
717 if ((zombie
== 0) && (p
->p_stat
!= SZOMB
) && (p
->task
!= TASK_NULL
))
718 proc_get_darwinbgstate(p
->task
, &pbsd_shortp
->pbsi_flags
);
720 pbsd_shortp
->pbsi_uid
= p
->p_uid
;
721 pbsd_shortp
->pbsi_gid
= p
->p_gid
;
722 pbsd_shortp
->pbsi_ruid
= p
->p_ruid
;
723 pbsd_shortp
->pbsi_rgid
= p
->p_rgid
;
724 pbsd_shortp
->pbsi_svuid
= p
->p_svuid
;
725 pbsd_shortp
->pbsi_svgid
= p
->p_svgid
;
731 proc_pidtaskinfo(proc_t p
, struct proc_taskinfo
* ptinfo
)
737 bzero(ptinfo
, sizeof(struct proc_taskinfo
));
738 fill_taskprocinfo(task
, (struct proc_taskinfo_internal
*)ptinfo
);
746 proc_pidthreadinfo(proc_t p
, uint64_t arg
, int thuniqueid
, struct proc_threadinfo
*pthinfo
)
749 uint64_t threadaddr
= (uint64_t)arg
;
751 bzero(pthinfo
, sizeof(struct proc_threadinfo
));
753 error
= fill_taskthreadinfo(p
->task
, threadaddr
, thuniqueid
, (struct proc_threadinfo_internal
*)pthinfo
, NULL
, NULL
);
762 bsd_getthreadname(void *uth
, char *buffer
)
764 struct uthread
*ut
= (struct uthread
*)uth
;
766 bcopy(ut
->pth_name
,buffer
,MAXTHREADNAMESIZE
);
770 bsd_threadcdir(void * uth
, void *vptr
, int *vidp
)
772 struct uthread
* ut
= (struct uthread
*)uth
;
774 vnode_t
*vpp
= (vnode_t
*)vptr
;
788 proc_pidthreadpathinfo(proc_t p
, uint64_t arg
, struct proc_threadwithpathinfo
*pinfo
)
793 uint64_t threadaddr
= (uint64_t)arg
;
796 bzero(pinfo
, sizeof(struct proc_threadwithpathinfo
));
798 error
= fill_taskthreadinfo(p
->task
, threadaddr
, 0, (struct proc_threadinfo_internal
*)&pinfo
->pt
, (void *)&vp
, &vid
);
802 if ((vp
!= NULLVP
) && ((vnode_getwithvid(vp
, vid
)) == 0)) {
803 error
= fill_vnodeinfo(vp
, &pinfo
->pvip
.vip_vi
) ;
806 vn_getpath(vp
, &pinfo
->pvip
.vip_path
[0], &count
);
807 pinfo
->pvip
.vip_path
[MAXPATHLEN
-1] = 0;
817 proc_pidlistthreads(proc_t p
, user_addr_t buffer
, uint32_t buffersize
, int32_t *retval
)
826 count
= buffersize
/(sizeof(uint64_t));
827 numthreads
= get_numthreads(p
->task
);
831 if (numthreads
> count
)
834 kbuf
= (void *)kalloc(numthreads
* sizeof(uint64_t));
837 bzero(kbuf
, numthreads
* sizeof(uint64_t));
839 ret
= fill_taskthreadlist(p
->task
, kbuf
, numthreads
);
841 error
= copyout(kbuf
, buffer
, ret
);
842 kfree(kbuf
, numthreads
* sizeof(uint64_t));
851 proc_pidregioninfo(proc_t p
, uint64_t arg
, user_addr_t buffer
, __unused
uint32_t buffersize
, int32_t *retval
)
853 struct proc_regioninfo preginfo
;
856 bzero(&preginfo
, sizeof(struct proc_regioninfo
));
857 ret
= fill_procregioninfo( p
->task
, arg
, (struct proc_regioninfo_internal
*)&preginfo
, (uintptr_t *)0, (uint32_t *)0);
860 error
= copyout(&preginfo
, buffer
, sizeof(struct proc_regioninfo
));
862 *retval
= sizeof(struct proc_regioninfo
);
868 proc_pidregionpathinfo(proc_t p
, uint64_t arg
, user_addr_t buffer
, __unused
uint32_t buffersize
, int32_t *retval
)
870 struct proc_regionwithpathinfo preginfo
;
872 uintptr_t vnodeaddr
= 0;
877 bzero(&preginfo
, sizeof(struct proc_regionwithpathinfo
));
879 ret
= fill_procregioninfo( p
->task
, arg
, (struct proc_regioninfo_internal
*)&preginfo
.prp_prinfo
, (uintptr_t *)&vnodeaddr
, (uint32_t *)&vnodeid
);
883 vp
= (vnode_t
)vnodeaddr
;
884 if ((vnode_getwithvid(vp
, vnodeid
)) == 0) {
885 /* FILL THE VNODEINFO */
886 error
= fill_vnodeinfo(vp
, &preginfo
.prp_vip
.vip_vi
);
888 vn_getpath(vp
, &preginfo
.prp_vip
.vip_path
[0], &count
);
889 /* Always make sure it is null terminated */
890 preginfo
.prp_vip
.vip_path
[MAXPATHLEN
-1] = 0;
894 error
= copyout(&preginfo
, buffer
, sizeof(struct proc_regionwithpathinfo
));
896 *retval
= sizeof(struct proc_regionwithpathinfo
);
901 proc_pidregionpathinfo2(proc_t p
, uint64_t arg
, user_addr_t buffer
, __unused
uint32_t buffersize
, int32_t *retval
)
903 struct proc_regionwithpathinfo preginfo
;
905 uintptr_t vnodeaddr
= 0;
910 bzero(&preginfo
, sizeof(struct proc_regionwithpathinfo
));
912 ret
= fill_procregioninfo_onlymappedvnodes( p
->task
, arg
, (struct proc_regioninfo_internal
*)&preginfo
.prp_prinfo
, (uintptr_t *)&vnodeaddr
, (uint32_t *)&vnodeid
);
918 vp
= (vnode_t
)vnodeaddr
;
919 if ((vnode_getwithvid(vp
, vnodeid
)) == 0) {
920 /* FILL THE VNODEINFO */
921 error
= fill_vnodeinfo(vp
, &preginfo
.prp_vip
.vip_vi
);
923 vn_getpath(vp
, &preginfo
.prp_vip
.vip_path
[0], &count
);
924 /* Always make sure it is null terminated */
925 preginfo
.prp_vip
.vip_path
[MAXPATHLEN
-1] = 0;
931 error
= copyout(&preginfo
, buffer
, sizeof(struct proc_regionwithpathinfo
));
933 *retval
= sizeof(struct proc_regionwithpathinfo
);
938 proc_pidregionpathinfo3(proc_t p
, uint64_t arg
, user_addr_t buffer
, __unused
uint32_t buffersize
, int32_t *retval
)
940 struct proc_regionwithpathinfo preginfo
;
948 /* Loop while looking for vnodes that match dev_t filter */
950 bzero(&preginfo
, sizeof(struct proc_regionwithpathinfo
));
954 ret
= fill_procregioninfo_onlymappedvnodes( p
->task
, addr
, (struct proc_regioninfo_internal
*)&preginfo
.prp_prinfo
, (uintptr_t *)&vnodeaddr
, (uint32_t *)&vnodeid
);
960 vp
= (vnode_t
)vnodeaddr
;
961 if ((vnode_getwithvid(vp
, vnodeid
)) == 0) {
962 /* Check if the vnode matches the filter, otherwise loop looking for the next memory region backed by a vnode */
963 struct vnode_attr va
;
965 memset(&va
, 0, sizeof(va
));
967 VATTR_WANTED(&va
, va_fsid
);
969 ret
= vnode_getattr(vp
, &va
, vfs_context_current());
975 if (va
.va_fsid
== arg
) {
976 /* FILL THE VNODEINFO */
977 error
= fill_vnodeinfo(vp
, &preginfo
.prp_vip
.vip_vi
);
979 vn_getpath(vp
, &preginfo
.prp_vip
.vip_path
[0], &count
);
980 /* Always make sure it is null terminated */
981 preginfo
.prp_vip
.vip_path
[MAXPATHLEN
-1] = 0;
990 addr
= preginfo
.prp_prinfo
.pri_address
+ preginfo
.prp_prinfo
.pri_size
;
993 error
= copyout(&preginfo
, buffer
, sizeof(struct proc_regionwithpathinfo
));
995 *retval
= sizeof(struct proc_regionwithpathinfo
);
1000 * Path is relative to current process directory; may different from current
1004 proc_pidvnodepathinfo(proc_t p
, __unused
uint64_t arg
, user_addr_t buffer
, __unused
uint32_t buffersize
, int32_t *retval
)
1006 struct proc_vnodepathinfo pvninfo
;
1008 vnode_t vncdirvp
= NULLVP
;
1009 uint32_t vncdirid
=0;
1010 vnode_t vnrdirvp
= NULLVP
;
1011 uint32_t vnrdirid
=0;
1014 bzero(&pvninfo
, sizeof(struct proc_vnodepathinfo
));
1017 if (p
->p_fd
->fd_cdir
) {
1018 vncdirvp
= p
->p_fd
->fd_cdir
;
1019 vncdirid
= p
->p_fd
->fd_cdir
->v_id
;
1021 if (p
->p_fd
->fd_rdir
) {
1022 vnrdirvp
= p
->p_fd
->fd_rdir
;
1023 vnrdirid
= p
->p_fd
->fd_rdir
->v_id
;
1027 if (vncdirvp
!= NULLVP
) {
1028 if ((error
= vnode_getwithvid(vncdirvp
, vncdirid
)) == 0) {
1029 /* FILL THE VNODEINFO */
1030 error
= fill_vnodeinfo(vncdirvp
, &pvninfo
.pvi_cdir
.vip_vi
);
1033 vn_getpath(vncdirvp
, &pvninfo
.pvi_cdir
.vip_path
[0], &count
);
1034 pvninfo
.pvi_cdir
.vip_path
[MAXPATHLEN
-1] = 0;
1036 vnode_put(vncdirvp
);
1042 if ((error
== 0) && (vnrdirvp
!= NULLVP
)) {
1043 if ((error
= vnode_getwithvid(vnrdirvp
, vnrdirid
)) == 0) {
1044 /* FILL THE VNODEINFO */
1045 error
= fill_vnodeinfo(vnrdirvp
, &pvninfo
.pvi_rdir
.vip_vi
);
1048 vn_getpath(vnrdirvp
, &pvninfo
.pvi_rdir
.vip_path
[0], &count
);
1049 pvninfo
.pvi_rdir
.vip_path
[MAXPATHLEN
-1] = 0;
1051 vnode_put(vnrdirvp
);
1057 error
= copyout(&pvninfo
, buffer
, sizeof(struct proc_vnodepathinfo
));
1059 *retval
= sizeof(struct proc_vnodepathinfo
);
1066 proc_pidpathinfo(proc_t p
, __unused
uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, __unused
int32_t *retval
)
1070 vnode_t nvp
= NULLVP
;
1071 int len
= buffersize
;
1079 buf
= (char *)kalloc(buffersize
);
1084 vid
= vnode_vid(tvp
);
1085 error
= vnode_getwithvid(tvp
, vid
);
1087 error
= vn_getpath_fsenter(tvp
, buf
, &len
);
1090 error
= vnode_lookup(buf
, 0, &nvp
, vfs_context_current());
1091 if ((error
== 0) && ( nvp
!= NULLVP
))
1094 error
= copyout(buf
, buffer
, len
);
1098 kfree(buf
, buffersize
);
1104 proc_pidworkqueueinfo(proc_t p
, struct proc_workqueueinfo
*pwqinfo
)
1108 bzero(pwqinfo
, sizeof(struct proc_workqueueinfo
));
1110 error
= fill_procworkqueue(p
, pwqinfo
);
1120 proc_piduniqidentifierinfo(proc_t p
, struct proc_uniqidentifierinfo
*p_uniqidinfo
)
1122 p_uniqidinfo
->p_uniqueid
= proc_uniqueid(p
);
1123 proc_getexecutableuuid(p
, (unsigned char *)&p_uniqidinfo
->p_uuid
, sizeof(p_uniqidinfo
->p_uuid
));
1124 p_uniqidinfo
->p_puniqueid
= proc_puniqueid(p
);
1125 p_uniqidinfo
->p_reserve2
= 0;
1126 p_uniqidinfo
->p_reserve3
= 0;
1127 p_uniqidinfo
->p_reserve4
= 0;
1132 proc_piduuidinfo(pid_t pid
, uuid_t uuid_buf
, uint32_t buffersize
)
1134 struct proc
* p
= PROC_NULL
;
1137 if (buffersize
< sizeof(uuid_t
))
1140 if ((p
= proc_find(pid
)) == PROC_NULL
) {
1141 p
= proc_find_zombref(pid
);
1144 if (p
== PROC_NULL
) {
1148 proc_getexecutableuuid(p
, (unsigned char *)uuid_buf
, buffersize
);
1151 proc_drop_zombref(p
);
1159 * Function to get the uuid and pid of the originator of the voucher.
1162 proc_pidoriginatorpid_uuid(uuid_t uuid
, uint32_t buffersize
, pid_t
*pid
)
1164 pid_t originator_pid
;
1169 * Get the current voucher origin pid. The pid returned here
1170 * might not be valid or may have been recycled.
1172 kr
= thread_get_current_voucher_origin_pid(&originator_pid
);
1173 /* If errors, convert errors to appropriate format */
1175 if (kr
== KERN_INVALID_TASK
)
1177 else if (kr
== KERN_INVALID_VALUE
)
1184 *pid
= originator_pid
;
1185 error
= proc_piduuidinfo(originator_pid
, uuid
, buffersize
);
1190 * Function to get the uuid of the originator of the voucher.
1193 proc_pidoriginatoruuid(uuid_t uuid
, uint32_t buffersize
)
1195 pid_t originator_pid
;
1196 return (proc_pidoriginatorpid_uuid(uuid
, buffersize
, &originator_pid
));
1199 /***************************** proc_pidoriginatorinfo ***************************/
1202 proc_pidoriginatorinfo(int pid
, int flavor
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
)
1204 int error
= ENOTSUP
;
1208 case PROC_PIDORIGINATOR_UUID
:
1209 size
= PROC_PIDORIGINATOR_UUID_SIZE
;
1211 case PROC_PIDORIGINATOR_BGSTATE
:
1212 size
= PROC_PIDORIGINATOR_BGSTATE_SIZE
;
1214 case PROC_PIDORIGINATOR_PID_UUID
:
1215 size
= PROC_PIDORIGINATOR_PID_UUID_SIZE
;
1221 if (buffersize
< size
)
1224 if (pid
!= 0 && pid
!= proc_selfpid())
1228 case PROC_PIDORIGINATOR_UUID
: {
1231 error
= proc_pidoriginatoruuid(uuid
, sizeof(uuid
));
1235 error
= copyout(uuid
, buffer
, size
);
1241 case PROC_PIDORIGINATOR_PID_UUID
: {
1242 struct proc_originatorinfo originator_info
;
1244 error
= proc_pidoriginatorpid_uuid(originator_info
.originator_uuid
,
1245 sizeof(uuid_t
), &originator_info
.originator_pid
);
1249 originator_info
.p_reserve2
= 0;
1250 originator_info
.p_reserve3
= 0;
1251 originator_info
.p_reserve4
= 0;
1253 error
= copyout(&originator_info
, buffer
, size
);
1259 case PROC_PIDORIGINATOR_BGSTATE
: {
1260 uint32_t is_backgrounded
;
1261 error
= proc_get_originatorbgstate(&is_backgrounded
);
1265 error
= copyout(&is_backgrounded
, buffer
, size
);
1278 /***************************** proc_listcoalitions ***************************/
1279 int proc_listcoalitions(int flavor
, int type
, user_addr_t buffer
,
1280 uint32_t buffersize
, int32_t *retval
)
1282 #if CONFIG_COALITIONS
1283 int error
= ENOTSUP
;
1286 void *coalinfo
= NULL
;
1287 uint32_t k_buffersize
= 0, copyout_sz
= 0;
1288 int ncoals
= 0, ncoals_
= 0;
1290 /* struct procinfo_coalinfo; */
1293 case LISTCOALITIONS_ALL_COALS
:
1294 elem_size
= LISTCOALITIONS_ALL_COALS_SIZE
;
1297 case LISTCOALITIONS_SINGLE_TYPE
:
1298 elem_size
= LISTCOALITIONS_SINGLE_TYPE_SIZE
;
1305 /* find the total number of coalitions */
1306 ncoals
= coalitions_get_list(coal_type
, NULL
, 0);
1308 if (ncoals
== 0 || buffer
== 0 || buffersize
== 0) {
1310 * user just wants buffer size
1311 * or there are no coalitions
1314 *retval
= (int)(ncoals
* elem_size
);
1318 k_buffersize
= ncoals
* elem_size
;
1319 coalinfo
= kalloc((vm_size_t
)k_buffersize
);
1324 bzero(coalinfo
, k_buffersize
);
1327 case LISTCOALITIONS_ALL_COALS
:
1328 case LISTCOALITIONS_SINGLE_TYPE
:
1329 ncoals_
= coalitions_get_list(coal_type
, coalinfo
, ncoals
);
1332 panic("memory corruption?!");
1336 /* all the coalitions disappeared... weird but valid */
1343 * Some coalitions may have disappeared between our initial check,
1344 * and the the actual list acquisition.
1345 * Only copy out what we really need.
1347 copyout_sz
= k_buffersize
;
1348 if (ncoals_
< ncoals
)
1349 copyout_sz
= ncoals_
* elem_size
;
1352 * copy the list up to user space
1353 * (we're guaranteed to have a non-null pointer/size here)
1355 error
= copyout(coalinfo
, buffer
,
1356 copyout_sz
< buffersize
? copyout_sz
: buffersize
);
1359 *retval
= (int)copyout_sz
;
1363 kfree(coalinfo
, k_buffersize
);
1367 /* no coalition support */
1378 /********************************** proc_pidinfo ********************************/
1382 proc_pidinfo(int pid
, int flavor
, uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
)
1384 struct proc
* p
= PROC_NULL
;
1385 int error
= ENOTSUP
;
1388 int shortversion
= 0;
1392 int uniqidversion
= 0;
1393 boolean_t check_same_user
;
1396 case PROC_PIDLISTFDS
:
1397 size
= PROC_PIDLISTFD_SIZE
;
1398 if (buffer
== (user_addr_t
)0)
1401 case PROC_PIDTBSDINFO
:
1402 size
= PROC_PIDTBSDINFO_SIZE
;
1404 case PROC_PIDTASKINFO
:
1405 size
= PROC_PIDTASKINFO_SIZE
;
1407 case PROC_PIDTASKALLINFO
:
1408 size
= PROC_PIDTASKALLINFO_SIZE
;
1410 case PROC_PIDTHREADINFO
:
1411 size
= PROC_PIDTHREADINFO_SIZE
;
1413 case PROC_PIDLISTTHREADS
:
1414 size
= PROC_PIDLISTTHREADS_SIZE
;
1416 case PROC_PIDREGIONINFO
:
1417 size
= PROC_PIDREGIONINFO_SIZE
;
1419 case PROC_PIDREGIONPATHINFO
:
1420 size
= PROC_PIDREGIONPATHINFO_SIZE
;
1422 case PROC_PIDVNODEPATHINFO
:
1423 size
= PROC_PIDVNODEPATHINFO_SIZE
;
1425 case PROC_PIDTHREADPATHINFO
:
1426 size
= PROC_PIDTHREADPATHINFO_SIZE
;
1428 case PROC_PIDPATHINFO
:
1431 case PROC_PIDWORKQUEUEINFO
:
1432 /* kernel does not have workq info */
1436 size
= PROC_PIDWORKQUEUEINFO_SIZE
;
1438 case PROC_PIDT_SHORTBSDINFO
:
1439 size
= PROC_PIDT_SHORTBSDINFO_SIZE
;
1441 case PROC_PIDLISTFILEPORTS
:
1442 size
= PROC_PIDLISTFILEPORTS_SIZE
;
1443 if (buffer
== (user_addr_t
)0)
1446 case PROC_PIDTHREADID64INFO
:
1447 size
= PROC_PIDTHREADID64INFO_SIZE
;
1449 case PROC_PIDUNIQIDENTIFIERINFO
:
1450 size
= PROC_PIDUNIQIDENTIFIERINFO_SIZE
;
1452 case PROC_PIDT_BSDINFOWITHUNIQID
:
1453 size
= PROC_PIDT_BSDINFOWITHUNIQID_SIZE
;
1455 case PROC_PIDARCHINFO
:
1456 size
= PROC_PIDARCHINFO_SIZE
;
1458 case PROC_PIDCOALITIONINFO
:
1459 size
= PROC_PIDCOALITIONINFO_SIZE
;
1461 case PROC_PIDNOTEEXIT
:
1463 * Set findzomb explicitly because arg passed
1464 * in is used as note exit status bits.
1466 size
= PROC_PIDNOTEEXIT_SIZE
;
1469 case PROC_PIDREGIONPATHINFO2
:
1470 size
= PROC_PIDREGIONPATHINFO2_SIZE
;
1472 case PROC_PIDREGIONPATHINFO3
:
1473 size
= PROC_PIDREGIONPATHINFO3_SIZE
;
1479 if (buffersize
< size
)
1482 if ((flavor
== PROC_PIDPATHINFO
) && (buffersize
> PROC_PIDPATHINFO_MAXSIZE
)) {
1486 /* Check if we need to look for zombies */
1487 if ((flavor
== PROC_PIDTBSDINFO
) || (flavor
== PROC_PIDT_SHORTBSDINFO
) || (flavor
== PROC_PIDT_BSDINFOWITHUNIQID
)
1488 || (flavor
== PROC_PIDUNIQIDENTIFIERINFO
)) {
1493 if ((p
= proc_find(pid
)) == PROC_NULL
) {
1495 p
= proc_find_zombref(pid
);
1496 if (p
== PROC_NULL
) {
1505 /* Certain operations don't require privileges */
1507 case PROC_PIDT_SHORTBSDINFO
:
1508 case PROC_PIDUNIQIDENTIFIERINFO
:
1509 case PROC_PIDPATHINFO
:
1510 case PROC_PIDCOALITIONINFO
:
1511 check_same_user
= NO_CHECK_SAME_USER
;
1514 check_same_user
= CHECK_SAME_USER
;
1518 /* Do we have permission to look into this? */
1519 if ((error
= proc_security_policy(p
, PROC_INFO_CALL_PIDINFO
, flavor
, check_same_user
)))
1523 case PROC_PIDLISTFDS
: {
1524 error
= proc_pidfdlist(p
, buffer
, buffersize
, retval
);
1528 case PROC_PIDUNIQIDENTIFIERINFO
: {
1529 struct proc_uniqidentifierinfo p_uniqidinfo
;
1531 proc_piduniqidentifierinfo(p
, &p_uniqidinfo
);
1532 error
= copyout(&p_uniqidinfo
, buffer
, sizeof(struct proc_uniqidentifierinfo
));
1534 *retval
= sizeof(struct proc_uniqidentifierinfo
);
1538 case PROC_PIDT_SHORTBSDINFO
:
1540 case PROC_PIDT_BSDINFOWITHUNIQID
:
1541 case PROC_PIDTBSDINFO
: {
1542 struct proc_bsdinfo pbsd
;
1543 struct proc_bsdshortinfo pbsd_short
;
1544 struct proc_bsdinfowithuniqid pbsd_uniqid
;
1546 if (flavor
== PROC_PIDT_BSDINFOWITHUNIQID
)
1549 if (shortversion
!= 0) {
1550 error
= proc_pidshortbsdinfo(p
, &pbsd_short
, zombie
);
1552 error
= proc_pidbsdinfo(p
, &pbsd
, zombie
);
1553 if (uniqidversion
!= 0) {
1554 proc_piduniqidentifierinfo(p
, &pbsd_uniqid
.p_uniqidentifier
);
1555 pbsd_uniqid
.pbsd
= pbsd
;
1560 if (shortversion
!= 0) {
1561 error
= copyout(&pbsd_short
, buffer
, sizeof(struct proc_bsdshortinfo
));
1563 *retval
= sizeof(struct proc_bsdshortinfo
);
1564 } else if (uniqidversion
!= 0) {
1565 error
= copyout(&pbsd_uniqid
, buffer
, sizeof(struct proc_bsdinfowithuniqid
));
1567 *retval
= sizeof(struct proc_bsdinfowithuniqid
);
1569 error
= copyout(&pbsd
, buffer
, sizeof(struct proc_bsdinfo
));
1571 *retval
= sizeof(struct proc_bsdinfo
);
1577 case PROC_PIDTASKINFO
: {
1578 struct proc_taskinfo ptinfo
;
1580 error
= proc_pidtaskinfo(p
, &ptinfo
);
1582 error
= copyout(&ptinfo
, buffer
, sizeof(struct proc_taskinfo
));
1584 *retval
= sizeof(struct proc_taskinfo
);
1589 case PROC_PIDTASKALLINFO
: {
1590 struct proc_taskallinfo pall
;
1592 error
= proc_pidbsdinfo(p
, &pall
.pbsd
, 0);
1593 error
= proc_pidtaskinfo(p
, &pall
.ptinfo
);
1595 error
= copyout(&pall
, buffer
, sizeof(struct proc_taskallinfo
));
1597 *retval
= sizeof(struct proc_taskallinfo
);
1602 case PROC_PIDTHREADID64INFO
:
1604 case PROC_PIDTHREADINFO
:{
1605 struct proc_threadinfo pthinfo
;
1607 error
= proc_pidthreadinfo(p
, arg
, thuniqueid
, &pthinfo
);
1609 error
= copyout(&pthinfo
, buffer
, sizeof(struct proc_threadinfo
));
1611 *retval
= sizeof(struct proc_threadinfo
);
1616 case PROC_PIDLISTTHREADS
:{
1617 error
= proc_pidlistthreads(p
, buffer
, buffersize
, retval
);
1621 case PROC_PIDREGIONINFO
:{
1622 error
= proc_pidregioninfo(p
, arg
, buffer
, buffersize
, retval
);
1627 case PROC_PIDREGIONPATHINFO
:{
1628 error
= proc_pidregionpathinfo(p
, arg
, buffer
, buffersize
, retval
);
1632 case PROC_PIDREGIONPATHINFO2
:{
1633 error
= proc_pidregionpathinfo2(p
, arg
, buffer
, buffersize
, retval
);
1637 case PROC_PIDREGIONPATHINFO3
:{
1638 error
= proc_pidregionpathinfo3(p
, arg
, buffer
, buffersize
, retval
);
1642 case PROC_PIDVNODEPATHINFO
:{
1643 error
= proc_pidvnodepathinfo(p
, arg
, buffer
, buffersize
, retval
);
1648 case PROC_PIDTHREADPATHINFO
:{
1649 struct proc_threadwithpathinfo pinfo
;
1651 error
= proc_pidthreadpathinfo(p
, arg
, &pinfo
);
1653 error
= copyout((caddr_t
)&pinfo
, buffer
, sizeof(struct proc_threadwithpathinfo
));
1655 *retval
= sizeof(struct proc_threadwithpathinfo
);
1660 case PROC_PIDPATHINFO
: {
1661 error
= proc_pidpathinfo(p
, arg
, buffer
, buffersize
, retval
);
1666 case PROC_PIDWORKQUEUEINFO
:{
1667 struct proc_workqueueinfo pwqinfo
;
1669 error
= proc_pidworkqueueinfo(p
, &pwqinfo
);
1671 error
= copyout(&pwqinfo
, buffer
, sizeof(struct proc_workqueueinfo
));
1673 *retval
= sizeof(struct proc_workqueueinfo
);
1678 case PROC_PIDLISTFILEPORTS
: {
1679 error
= proc_pidfileportlist(p
, buffer
, buffersize
,
1684 case PROC_PIDARCHINFO
: {
1685 struct proc_archinfo pai
;
1686 proc_archinfo(p
, &pai
);
1687 error
= copyout(&pai
, buffer
, sizeof(struct proc_archinfo
));
1689 *retval
= sizeof(struct proc_archinfo
);
1694 case PROC_PIDCOALITIONINFO
: {
1695 struct proc_pidcoalitioninfo pci
;
1696 proc_pidcoalitioninfo(p
, &pci
);
1697 error
= copyout(&pci
, buffer
, sizeof(struct proc_pidcoalitioninfo
));
1699 *retval
= sizeof(struct proc_pidcoalitioninfo
);
1704 case PROC_PIDNOTEEXIT
: {
1706 error
= proc_pidnoteexit(p
, arg
, &data
);
1708 error
= copyout(&data
, buffer
, sizeof(data
));
1710 *retval
= sizeof(data
);
1724 proc_drop_zombref(p
);
1730 pid_vnodeinfo(vnode_t vp
, uint32_t vid
, struct fileproc
* fp
, proc_t proc
, int fd
, user_addr_t buffer
, __unused
uint32_t buffersize
, int32_t * retval
)
1732 struct vnode_fdinfo vfi
;
1735 if ((error
= vnode_getwithvid(vp
, vid
)) != 0) {
1738 bzero(&vfi
, sizeof(struct vnode_fdinfo
));
1739 fill_fileinfo(fp
, proc
, fd
, &vfi
.pfi
);
1740 error
= fill_vnodeinfo(vp
, &vfi
.pvi
);
1743 error
= copyout((caddr_t
)&vfi
, buffer
, sizeof(struct vnode_fdinfo
));
1745 *retval
= sizeof(struct vnode_fdinfo
);
1751 pid_vnodeinfopath(vnode_t vp
, uint32_t vid
, struct fileproc
* fp
, proc_t proc
, int fd
, user_addr_t buffer
, __unused
uint32_t buffersize
, int32_t * retval
)
1753 struct vnode_fdinfowithpath vfip
;
1754 int count
, error
= 0;
1756 if ((error
= vnode_getwithvid(vp
, vid
)) != 0) {
1759 bzero(&vfip
, sizeof(struct vnode_fdinfowithpath
));
1760 fill_fileinfo(fp
, proc
, fd
, &vfip
.pfi
);
1761 error
= fill_vnodeinfo(vp
, &vfip
.pvip
.vip_vi
) ;
1764 vn_getpath(vp
, &vfip
.pvip
.vip_path
[0], &count
);
1765 vfip
.pvip
.vip_path
[MAXPATHLEN
-1] = 0;
1767 error
= copyout((caddr_t
)&vfip
, buffer
, sizeof(struct vnode_fdinfowithpath
));
1769 *retval
= sizeof(struct vnode_fdinfowithpath
);
1776 fill_fileinfo(struct fileproc
* fp
, proc_t proc
, int fd
, struct proc_fileinfo
* fproc
)
1778 fproc
->fi_openflags
= fp
->f_fglob
->fg_flag
;
1779 fproc
->fi_status
= 0;
1780 fproc
->fi_offset
= fp
->f_fglob
->fg_offset
;
1781 fproc
->fi_type
= FILEGLOB_DTYPE(fp
->f_fglob
);
1782 if (fp
->f_fglob
->fg_count
> 1)
1783 fproc
->fi_status
|= PROC_FP_SHARED
;
1784 if (proc
!= PROC_NULL
) {
1785 if ((FDFLAGS_GET(proc
, fd
) & UF_EXCLOSE
) != 0)
1786 fproc
->fi_status
|= PROC_FP_CLEXEC
;
1787 if ((FDFLAGS_GET(proc
, fd
) & UF_FORKCLOSE
) != 0)
1788 fproc
->fi_status
|= PROC_FP_CLFORK
;
1790 if (FILEPROC_TYPE(fp
) == FTYPE_GUARDED
) {
1791 fproc
->fi_status
|= PROC_FP_GUARDED
;
1792 fproc
->fi_guardflags
= 0;
1793 if (fp_isguarded(fp
, GUARD_CLOSE
))
1794 fproc
->fi_guardflags
|= PROC_FI_GUARD_CLOSE
;
1795 if (fp_isguarded(fp
, GUARD_DUP
))
1796 fproc
->fi_guardflags
|= PROC_FI_GUARD_DUP
;
1797 if (fp_isguarded(fp
, GUARD_SOCKET_IPC
))
1798 fproc
->fi_guardflags
|= PROC_FI_GUARD_SOCKET_IPC
;
1799 if (fp_isguarded(fp
, GUARD_FILEPORT
))
1800 fproc
->fi_guardflags
|= PROC_FI_GUARD_FILEPORT
;
1807 fill_vnodeinfo(vnode_t vp
, struct vnode_info
*vinfo
)
1809 vfs_context_t context
;
1813 bzero(&sb
, sizeof(struct stat64
));
1814 context
= vfs_context_create((vfs_context_t
)0);
1815 error
= vn_stat(vp
, &sb
, NULL
, 1, context
);
1816 (void)vfs_context_rele(context
);
1818 munge_vinfo_stat(&sb
, &vinfo
->vi_stat
);
1823 if (vp
->v_mount
!= dead_mountp
) {
1824 vinfo
->vi_fsid
= vp
->v_mount
->mnt_vfsstat
.f_fsid
;
1826 vinfo
->vi_fsid
.val
[0] = 0;
1827 vinfo
->vi_fsid
.val
[1] = 0;
1829 vinfo
->vi_type
= vp
->v_type
;
1835 pid_socketinfo(socket_t so
, struct fileproc
*fp
, proc_t proc
, int fd
, user_addr_t buffer
, __unused
uint32_t buffersize
, int32_t * retval
)
1838 struct socket_fdinfo s
;
1841 bzero(&s
, sizeof(struct socket_fdinfo
));
1842 fill_fileinfo(fp
, proc
, fd
, &s
.pfi
);
1843 if ((error
= fill_socketinfo(so
, &s
.psi
)) == 0) {
1844 if ((error
= copyout(&s
, buffer
, sizeof(struct socket_fdinfo
))) == 0)
1845 *retval
= sizeof(struct socket_fdinfo
);
1849 #pragma unused(so, fp, proc, fd, buffer)
1856 pid_pseminfo(struct psemnode
*psem
, struct fileproc
*fp
, proc_t proc
, int fd
, user_addr_t buffer
, __unused
uint32_t buffersize
, int32_t * retval
)
1858 struct psem_fdinfo pseminfo
;
1861 bzero(&pseminfo
, sizeof(struct psem_fdinfo
));
1862 fill_fileinfo(fp
, proc
, fd
, &pseminfo
.pfi
);
1864 if ((error
= fill_pseminfo(psem
, &pseminfo
.pseminfo
)) == 0) {
1865 if ((error
= copyout(&pseminfo
, buffer
, sizeof(struct psem_fdinfo
))) == 0)
1866 *retval
= sizeof(struct psem_fdinfo
);
1873 pid_pshminfo(struct pshmnode
*pshm
, struct fileproc
*fp
, proc_t proc
, int fd
, user_addr_t buffer
, __unused
uint32_t buffersize
, int32_t * retval
)
1875 struct pshm_fdinfo pshminfo
;
1878 bzero(&pshminfo
, sizeof(struct pshm_fdinfo
));
1879 fill_fileinfo(fp
, proc
, fd
, &pshminfo
.pfi
);
1881 if ((error
= fill_pshminfo(pshm
, &pshminfo
.pshminfo
)) == 0) {
1882 if ((error
= copyout(&pshminfo
, buffer
, sizeof(struct pshm_fdinfo
))) == 0)
1883 *retval
= sizeof(struct pshm_fdinfo
);
1890 pid_pipeinfo(struct pipe
* p
, struct fileproc
*fp
, proc_t proc
, int fd
, user_addr_t buffer
, __unused
uint32_t buffersize
, int32_t * retval
)
1892 struct pipe_fdinfo pipeinfo
;
1895 bzero(&pipeinfo
, sizeof(struct pipe_fdinfo
));
1896 fill_fileinfo(fp
, proc
, fd
, &pipeinfo
.pfi
);
1897 if ((error
= fill_pipeinfo(p
, &pipeinfo
.pipeinfo
)) == 0) {
1898 if ((error
= copyout(&pipeinfo
, buffer
, sizeof(struct pipe_fdinfo
))) == 0)
1899 *retval
= sizeof(struct pipe_fdinfo
);
1906 pid_kqueueinfo(struct kqueue
* kq
, struct fileproc
*fp
, proc_t proc
, int fd
, user_addr_t buffer
, __unused
uint32_t buffersize
, int32_t * retval
)
1908 struct kqueue_fdinfo kqinfo
;
1911 bzero(&kqinfo
, sizeof(struct kqueue_fdinfo
));
1913 /* not all kq's are associated with a file (e.g. workqkq) */
1916 fill_fileinfo(fp
, proc
, fd
, &kqinfo
.pfi
);
1919 if ((error
= fill_kqueueinfo(kq
, &kqinfo
.kqueueinfo
)) == 0) {
1920 if ((error
= copyout(&kqinfo
, buffer
, sizeof(struct kqueue_fdinfo
))) == 0)
1921 *retval
= sizeof(struct kqueue_fdinfo
);
1928 pid_atalkinfo(__unused
struct atalk
* at
, __unused
struct fileproc
*fp
, __unused proc_t proc
, __unused
int fd
, __unused user_addr_t buffer
, __unused
uint32_t buffersize
, __unused
int32_t * retval
)
1935 /************************** proc_pidfdinfo routine ***************************/
1937 proc_pidfdinfo(int pid
, int flavor
, int fd
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
)
1940 int error
= ENOTSUP
;
1941 struct fileproc
* fp
= NULL
;
1945 case PROC_PIDFDVNODEINFO
:
1946 size
= PROC_PIDFDVNODEINFO_SIZE
;
1948 case PROC_PIDFDVNODEPATHINFO
:
1949 size
= PROC_PIDFDVNODEPATHINFO_SIZE
;
1951 case PROC_PIDFDSOCKETINFO
:
1952 size
= PROC_PIDFDSOCKETINFO_SIZE
;
1954 case PROC_PIDFDPSEMINFO
:
1955 size
= PROC_PIDFDPSEMINFO_SIZE
;
1957 case PROC_PIDFDPSHMINFO
:
1958 size
= PROC_PIDFDPSHMINFO_SIZE
;
1960 case PROC_PIDFDPIPEINFO
:
1961 size
= PROC_PIDFDPIPEINFO_SIZE
;
1963 case PROC_PIDFDKQUEUEINFO
:
1964 size
= PROC_PIDFDKQUEUEINFO_SIZE
;
1966 case PROC_PIDFDKQUEUE_EXTINFO
:
1967 size
= PROC_PIDFDKQUEUE_EXTINFO_SIZE
;
1968 if (buffer
== (user_addr_t
)0)
1971 case PROC_PIDFDATALKINFO
:
1972 size
= PROC_PIDFDATALKINFO_SIZE
;
1980 if (buffersize
< size
)
1983 if ((p
= proc_find(pid
)) == PROC_NULL
) {
1988 /* Do we have permission to look into this? */
1989 if ((error
= proc_security_policy(p
, PROC_INFO_CALL_PIDFDINFO
, flavor
, CHECK_SAME_USER
)))
1993 case PROC_PIDFDVNODEINFO
: {
1997 if ((error
= fp_getfvpandvid(p
, fd
, &fp
, &vp
, &vid
)) !=0) {
2000 /* no need to be under the fdlock */
2001 error
= pid_vnodeinfo(vp
, vid
, fp
, p
, fd
, buffer
, buffersize
, retval
);
2005 case PROC_PIDFDVNODEPATHINFO
: {
2009 if ((error
= fp_getfvpandvid(p
, fd
, &fp
, &vp
, &vid
)) !=0) {
2013 /* no need to be under the fdlock */
2014 error
= pid_vnodeinfopath(vp
, vid
, fp
, p
, fd
, buffer
, buffersize
, retval
);
2018 case PROC_PIDFDSOCKETINFO
: {
2021 if ((error
= fp_getfsock(p
, fd
, &fp
, &so
)) !=0) {
2024 /* no need to be under the fdlock */
2025 error
= pid_socketinfo(so
, fp
, p
, fd
, buffer
, buffersize
, retval
);
2029 case PROC_PIDFDPSEMINFO
: {
2030 struct psemnode
* psem
;
2032 if ((error
= fp_getfpsem(p
, fd
, &fp
, &psem
)) !=0) {
2035 /* no need to be under the fdlock */
2036 error
= pid_pseminfo(psem
, fp
, p
, fd
, buffer
, buffersize
, retval
);
2040 case PROC_PIDFDPSHMINFO
: {
2041 struct pshmnode
* pshm
;
2043 if ((error
= fp_getfpshm(p
, fd
, &fp
, &pshm
)) !=0) {
2046 /* no need to be under the fdlock */
2047 error
= pid_pshminfo(pshm
, fp
, p
, fd
, buffer
, buffersize
, retval
);
2051 case PROC_PIDFDPIPEINFO
: {
2052 struct pipe
* cpipe
;
2054 if ((error
= fp_getfpipe(p
, fd
, &fp
, &cpipe
)) !=0) {
2057 /* no need to be under the fdlock */
2058 error
= pid_pipeinfo(cpipe
, fp
, p
, fd
, buffer
, buffersize
, retval
);
2062 case PROC_PIDFDKQUEUEINFO
: {
2066 if ((kq
= p
->p_wqkqueue
) == NULL
) {
2067 /* wqkqueue is initialized on-demand */
2071 } else if ((error
= fp_getfkq(p
, fd
, &fp
, &kq
)) != 0) {
2075 /* no need to be under the fdlock */
2076 error
= pid_kqueueinfo(kq
, fp
, p
, fd
, buffer
, buffersize
, retval
);
2080 case PROC_PIDFDKQUEUE_EXTINFO
: {
2084 if ((kq
= p
->p_wqkqueue
) == NULL
) {
2085 /* wqkqueue is initialized on-demand */
2089 } else if ((error
= fp_getfkq(p
, fd
, &fp
, &kq
)) != 0) {
2092 error
= pid_kqueue_extinfo(p
, kq
, buffer
, buffersize
, retval
);
2103 fp_drop(p
, fd
, fp
, 0);
2112 * Helper function for proc_pidfileportinfo
2115 struct fileport_info_args
{
2117 user_addr_t fia_buffer
;
2118 uint32_t fia_buffersize
;
2119 int32_t *fia_retval
;
2122 static kern_return_t
2123 proc_fileport_info(__unused mach_port_name_t name
,
2124 struct fileglob
*fg
, void *arg
)
2126 struct fileport_info_args
*fia
= arg
;
2127 struct fileproc __fileproc
, *fp
= &__fileproc
;
2130 bzero(fp
, sizeof (*fp
));
2133 switch (fia
->fia_flavor
) {
2134 case PROC_PIDFILEPORTVNODEPATHINFO
: {
2137 if (FILEGLOB_DTYPE(fg
) != DTYPE_VNODE
) {
2141 vp
= (struct vnode
*)fg
->fg_data
;
2142 error
= pid_vnodeinfopath(vp
, vnode_vid(vp
), fp
, PROC_NULL
, 0,
2143 fia
->fia_buffer
, fia
->fia_buffersize
, fia
->fia_retval
);
2146 case PROC_PIDFILEPORTSOCKETINFO
: {
2149 if (FILEGLOB_DTYPE(fg
) != DTYPE_SOCKET
) {
2153 so
= (socket_t
)fg
->fg_data
;
2154 error
= pid_socketinfo(so
, fp
, PROC_NULL
, 0,
2155 fia
->fia_buffer
, fia
->fia_buffersize
, fia
->fia_retval
);
2158 case PROC_PIDFILEPORTPSHMINFO
: {
2159 struct pshmnode
*pshm
;
2161 if (FILEGLOB_DTYPE(fg
) != DTYPE_PSXSHM
) {
2162 error
= EBADF
; /* ick - mirror fp_getfpshm */
2165 pshm
= (struct pshmnode
*)fg
->fg_data
;
2166 error
= pid_pshminfo(pshm
, fp
, PROC_NULL
, 0,
2167 fia
->fia_buffer
, fia
->fia_buffersize
, fia
->fia_retval
);
2170 case PROC_PIDFILEPORTPIPEINFO
: {
2173 if (FILEGLOB_DTYPE(fg
) != DTYPE_PIPE
) {
2174 error
= EBADF
; /* ick - mirror fp_getfpipe */
2177 cpipe
= (struct pipe
*)fg
->fg_data
;
2178 error
= pid_pipeinfo(cpipe
, fp
, PROC_NULL
, 0,
2179 fia
->fia_buffer
, fia
->fia_buffersize
, fia
->fia_retval
);
2190 /************************* proc_pidfileportinfo routine *********************/
2192 proc_pidfileportinfo(int pid
, int flavor
, mach_port_name_t name
,
2193 user_addr_t buffer
, uint32_t buffersize
, int32_t *retval
)
2196 int error
= ENOTSUP
;
2198 struct fileport_info_args fia
;
2200 /* fileport types are restricted by file_issendable() */
2203 case PROC_PIDFILEPORTVNODEPATHINFO
:
2204 size
= PROC_PIDFILEPORTVNODEPATHINFO_SIZE
;
2206 case PROC_PIDFILEPORTSOCKETINFO
:
2207 size
= PROC_PIDFILEPORTSOCKETINFO_SIZE
;
2209 case PROC_PIDFILEPORTPSHMINFO
:
2210 size
= PROC_PIDFILEPORTPSHMINFO_SIZE
;
2212 case PROC_PIDFILEPORTPIPEINFO
:
2213 size
= PROC_PIDFILEPORTPIPEINFO_SIZE
;
2219 if (buffersize
< size
)
2221 if ((p
= proc_find(pid
)) == PROC_NULL
) {
2226 /* Do we have permission to look into this? */
2227 if ((error
= proc_security_policy(p
, PROC_INFO_CALL_PIDFILEPORTINFO
, flavor
, CHECK_SAME_USER
)))
2230 fia
.fia_flavor
= flavor
;
2231 fia
.fia_buffer
= buffer
;
2232 fia
.fia_buffersize
= buffersize
;
2233 fia
.fia_retval
= retval
;
2235 if (fileport_invoke(p
->task
, name
,
2236 proc_fileport_info
, &fia
, &error
) != KERN_SUCCESS
)
2245 proc_security_policy(proc_t targetp
, __unused
int callnum
, __unused
int flavor
, boolean_t check_same_user
)
2250 if ((error
= mac_proc_check_proc_info(current_proc(), targetp
, callnum
, flavor
)))
2254 /* The 'listpids' call doesn't have a target proc */
2255 if (targetp
== PROC_NULL
) {
2256 assert(callnum
== PROC_INFO_CALL_LISTPIDS
&& check_same_user
== NO_CHECK_SAME_USER
);
2261 * Check for 'get information for processes owned by other users' privilege
2262 * root has this privilege by default
2264 if (priv_check_cred(kauth_cred_get(), PRIV_GLOBAL_PROC_INFO
, 0) == 0)
2265 check_same_user
= FALSE
;
2267 if (check_same_user
) {
2268 kauth_cred_t target_cred
;
2271 target_cred
= kauth_cred_proc_ref(targetp
);
2272 target_uid
= kauth_cred_getuid(target_cred
);
2273 kauth_cred_unref(&target_cred
);
2275 if (kauth_getuid() != target_uid
)
2283 proc_kernmsgbuf(user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
)
2285 if (suser(kauth_cred_get(), (u_short
*)0) == 0) {
2286 return(log_dmesg(buffer
, buffersize
, retval
));
2291 /* ********* process control sets on self only */
2293 proc_setcontrol(int pid
, int flavor
, uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, __unused
int32_t * retval
)
2295 struct proc
* pself
= PROC_NULL
;
2297 uint32_t pcontrol
= (uint32_t)arg
;
2298 struct uthread
*ut
= NULL
;
2301 pself
= current_proc();
2302 if (pid
!= pself
->p_pid
)
2305 /* Do we have permission to look into this? */
2306 if ((error
= proc_security_policy(pself
, PROC_INFO_CALL_SETCONTROL
, flavor
, NO_CHECK_SAME_USER
)))
2310 case PROC_SELFSET_PCONTROL
: {
2311 if (pcontrol
> P_PCMAX
)
2314 /* reset existing control setting while retaining action state */
2315 pself
->p_pcaction
&= PROC_ACTION_MASK
;
2316 /* set new control state */
2317 pself
->p_pcaction
|= pcontrol
;
2322 case PROC_SELFSET_THREADNAME
: {
2323 /* PROC_SELFSET_THREADNAME_SIZE = (MAXTHREADNAMESIZE -1) */
2324 if(buffersize
> PROC_SELFSET_THREADNAME_SIZE
)
2325 return ENAMETOOLONG
;
2326 ut
= current_uthread();
2330 ut
->pth_name
= (char*)kalloc(MAXTHREADNAMESIZE
);
2334 bzero(ut
->pth_name
, MAXTHREADNAMESIZE
);
2335 error
= copyin(buffer
, ut
->pth_name
, buffersize
);
2339 case PROC_SELFSET_VMRSRCOWNER
: {
2340 /* need to to be superuser */
2341 if (suser(kauth_cred_get(), (u_short
*)0) != 0) {
2347 /* reset existing control setting while retaining action state */
2348 pself
->p_lflag
|= P_LVMRSRCOWNER
;
2353 case PROC_SELFSET_DELAYIDLESLEEP
: {
2354 /* mark or clear the process property to delay idle sleep disk IO */
2356 OSBitOrAtomic(P_DELAYIDLESLEEP
, &pself
->p_flag
);
2358 OSBitAndAtomic(~((uint32_t)P_DELAYIDLESLEEP
), &pself
->p_flag
);
2370 #if CONFIG_MEMORYSTATUS
2373 proc_dirtycontrol(int pid
, int flavor
, uint64_t arg
, int32_t *retval
) {
2374 struct proc
*target_p
;
2376 uint32_t pcontrol
= (uint32_t)arg
;
2377 kauth_cred_t my_cred
, target_cred
;
2378 boolean_t self
= FALSE
;
2379 boolean_t child
= FALSE
;
2380 boolean_t zombref
= FALSE
;
2383 target_p
= proc_find(pid
);
2385 if (target_p
== PROC_NULL
) {
2386 if (flavor
== PROC_DIRTYCONTROL_GET
) {
2387 target_p
= proc_find_zombref(pid
);
2391 if (target_p
== PROC_NULL
)
2396 my_cred
= kauth_cred_get();
2397 target_cred
= kauth_cred_proc_ref(target_p
);
2399 /* Do we have permission to look into this? */
2400 if ((error
= proc_security_policy(target_p
, PROC_INFO_CALL_DIRTYCONTROL
, flavor
, NO_CHECK_SAME_USER
)))
2403 selfpid
= proc_selfpid();
2404 if (pid
== selfpid
) {
2406 } else if (target_p
->p_ppid
== selfpid
) {
2411 case PROC_DIRTYCONTROL_TRACK
: {
2412 /* Only allow the process itself, its parent, or root */
2413 if ((self
== FALSE
) && (child
== FALSE
) && kauth_cred_issuser(kauth_cred_get()) != TRUE
) {
2418 error
= memorystatus_dirty_track(target_p
, pcontrol
);
2422 case PROC_DIRTYCONTROL_SET
: {
2423 /* Check privileges; use cansignal() here since the process could be terminated */
2424 if (!cansignal(current_proc(), my_cred
, target_p
, SIGKILL
, 0)) {
2429 error
= memorystatus_dirty_set(target_p
, self
, pcontrol
);
2433 case PROC_DIRTYCONTROL_GET
: {
2434 /* No permissions check - dirty state is freely available */
2436 *retval
= memorystatus_dirty_get(target_p
);
2443 case PROC_DIRTYCONTROL_CLEAR
: {
2444 /* Check privileges; use cansignal() here since the process could be terminated */
2445 if (!cansignal(current_proc(), my_cred
, target_p
, SIGKILL
, 0)) {
2450 error
= memorystatus_dirty_clear(target_p
, pcontrol
);
2457 proc_drop_zombref(target_p
);
2459 proc_rele(target_p
);
2461 kauth_cred_unref(&target_cred
);
2468 proc_dirtycontrol(__unused
int pid
, __unused
int flavor
, __unused
uint64_t arg
, __unused
int32_t *retval
) {
2472 #endif /* CONFIG_MEMORYSTATUS */
2475 * proc_terminate() provides support for sudden termination.
2476 * SIGKILL is issued to tracked, clean processes; otherwise,
2481 proc_terminate(int pid
, int32_t *retval
)
2485 kauth_cred_t uc
= kauth_cred_get();
2489 /* XXX: Check if these are necessary */
2490 AUDIT_ARG(pid
, pid
);
2491 AUDIT_ARG(signum
, sig
);
2494 if (pid
<= 0 || retval
== NULL
) {
2498 if ((p
= proc_find(pid
)) == NULL
) {
2503 /* XXX: Check if these are necessary */
2504 AUDIT_ARG(process
, p
);
2507 /* Check privileges; if SIGKILL can be issued, then SIGTERM is also OK */
2508 if (!cansignal(current_proc(), uc
, p
, SIGKILL
, 0)) {
2513 /* Not allowed to sudden terminate yourself */
2514 if (p
== current_proc()) {
2519 #if CONFIG_MEMORYSTATUS
2520 /* Determine requisite signal to issue */
2521 sig
= memorystatus_on_terminate(p
);
2526 proc_set_task_policy(p
->task
, THREAD_NULL
, TASK_POLICY_ATTRIBUTE
,
2527 TASK_POLICY_TERMINATED
, TASK_POLICY_ENABLE
);
2539 * copy stat64 structure into vinfo_stat structure.
2542 munge_vinfo_stat(struct stat64
*sbp
, struct vinfo_stat
*vsbp
)
2544 bzero(vsbp
, sizeof(struct vinfo_stat
));
2546 vsbp
->vst_dev
= sbp
->st_dev
;
2547 vsbp
->vst_mode
= sbp
->st_mode
;
2548 vsbp
->vst_nlink
= sbp
->st_nlink
;
2549 vsbp
->vst_ino
= sbp
->st_ino
;
2550 vsbp
->vst_uid
= sbp
->st_uid
;
2551 vsbp
->vst_gid
= sbp
->st_gid
;
2552 vsbp
->vst_atime
= sbp
->st_atimespec
.tv_sec
;
2553 vsbp
->vst_atimensec
= sbp
->st_atimespec
.tv_nsec
;
2554 vsbp
->vst_mtime
= sbp
->st_mtimespec
.tv_sec
;
2555 vsbp
->vst_mtimensec
= sbp
->st_mtimespec
.tv_nsec
;
2556 vsbp
->vst_ctime
= sbp
->st_ctimespec
.tv_sec
;
2557 vsbp
->vst_ctimensec
= sbp
->st_ctimespec
.tv_nsec
;
2558 vsbp
->vst_birthtime
= sbp
->st_birthtimespec
.tv_sec
;
2559 vsbp
->vst_birthtimensec
= sbp
->st_birthtimespec
.tv_nsec
;
2560 vsbp
->vst_size
= sbp
->st_size
;
2561 vsbp
->vst_blocks
= sbp
->st_blocks
;
2562 vsbp
->vst_blksize
= sbp
->st_blksize
;
2563 vsbp
->vst_flags
= sbp
->st_flags
;
2564 vsbp
->vst_gen
= sbp
->st_gen
;
2565 vsbp
->vst_rdev
= sbp
->st_rdev
;
2566 vsbp
->vst_qspare
[0] = sbp
->st_qspare
[0];
2567 vsbp
->vst_qspare
[1] = sbp
->st_qspare
[1];
2571 proc_pid_rusage(int pid
, int flavor
, user_addr_t buffer
, __unused
int32_t *retval
)
2577 if ((p
= proc_find(pid
)) == PROC_NULL
) {
2578 if ((p
= proc_find_zombref(pid
)) == PROC_NULL
) {
2584 /* Do we have permission to look into this? */
2585 if ((error
= proc_security_policy(p
, PROC_INFO_CALL_PIDRUSAGE
, flavor
, CHECK_SAME_USER
)))
2588 error
= proc_get_rusage(p
, flavor
, buffer
, zombie
);
2592 proc_drop_zombref(p
);
2600 proc_archinfo(proc_t p
, struct proc_archinfo
*pai
)
2603 pai
->p_cputype
= p
->p_cputype
;
2604 pai
->p_cpusubtype
= p
->p_cpusubtype
;
2609 proc_pidcoalitioninfo(proc_t p
, struct proc_pidcoalitioninfo
*ppci
)
2611 bzero(ppci
, sizeof(*ppci
));
2612 proc_coalitionids(p
, ppci
->coalition_id
);
2618 * Wrapper to provide NOTE_EXIT_DETAIL and NOTE_EXITSTATUS
2619 * It mimics the data that is typically captured by the
2620 * EVFILT_PROC, NOTE_EXIT event mechanism.
2621 * See filt_proc() in kern_event.c.
2624 proc_pidnoteexit(proc_t p
, uint64_t flags
, uint32_t *data
)
2626 uint32_t exit_data
= 0;
2627 uint32_t exit_flags
= (uint32_t)flags
;
2632 * Allow access to the parent of the exiting
2633 * child or the parent debugger only.
2636 pid_t selfpid
= proc_selfpid();
2638 if (p
->p_ppid
== selfpid
)
2639 break; /* parent => ok */
2641 if ((p
->p_lflag
& P_LTRACED
) != 0 &&
2642 (p
->p_oppid
== selfpid
))
2643 break; /* parent-in-waiting => ok */
2649 if ((exit_flags
& NOTE_EXITSTATUS
) != 0) {
2650 /* The signal and exit status */
2651 exit_data
|= (p
->p_xstat
& NOTE_PDATAMASK
);
2654 if ((exit_flags
& NOTE_EXIT_DETAIL
) != 0) {
2655 /* The exit detail */
2656 if ((p
->p_lflag
& P_LTERM_DECRYPTFAIL
) != 0) {
2657 exit_data
|= NOTE_EXIT_DECRYPTFAIL
;
2660 if ((p
->p_lflag
& P_LTERM_JETSAM
) != 0) {
2661 exit_data
|= NOTE_EXIT_MEMORY
;
2663 switch (p
->p_lflag
& P_JETSAM_MASK
) {
2664 case P_JETSAM_VMPAGESHORTAGE
:
2665 exit_data
|= NOTE_EXIT_MEMORY_VMPAGESHORTAGE
;
2667 case P_JETSAM_VMTHRASHING
:
2668 exit_data
|= NOTE_EXIT_MEMORY_VMTHRASHING
;
2670 case P_JETSAM_FCTHRASHING
:
2671 exit_data
|= NOTE_EXIT_MEMORY_FCTHRASHING
;
2673 case P_JETSAM_VNODE
:
2674 exit_data
|= NOTE_EXIT_MEMORY_VNODE
;
2676 case P_JETSAM_HIWAT
:
2677 exit_data
|= NOTE_EXIT_MEMORY_HIWAT
;
2680 exit_data
|= NOTE_EXIT_MEMORY_PID
;
2682 case P_JETSAM_IDLEEXIT
:
2683 exit_data
|= NOTE_EXIT_MEMORY_IDLE
;
2688 if ((p
->p_csflags
& CS_KILLED
) != 0) {
2689 exit_data
|= NOTE_EXIT_CSERROR
;