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>
94 uint64_t get_dispatchqueue_offset_from_proc(void *);
95 uint64_t get_dispatchqueue_serialno_offset_from_proc(void *);
96 int proc_info_internal(int callnum
, int pid
, int flavor
, uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
);
99 * TODO: Replace the noinline attribute below. Currently, it serves
100 * to avoid stack bloat caused by inlining multiple functions that
101 * have large stack footprints; when the functions are independent
102 * of each other (will not both be called in any given call to the
103 * caller), this only serves to bloat the stack, as we allocate
104 * space for both functions, despite the fact that we only need a
105 * fraction of that space.
107 * Long term, these functions should not be allocating everything on
108 * the stack, and should move large allocations (the huge structs
109 * that proc info deals in) to the heap, or eliminate them if
112 * The functions that most desperately need to improve stack usage
113 * (starting with the worst offenders):
114 * proc_pidvnodepathinfo
116 * proc_pidregionpathinfo
122 * proc_pidoriginatorinfo
125 /* protos for proc_info calls */
126 int __attribute__ ((noinline
)) proc_listpids(uint32_t type
, uint32_t tyoneinfo
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
);
127 int __attribute__ ((noinline
)) proc_pidinfo(int pid
, int flavor
, uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
);
128 int __attribute__ ((noinline
)) proc_pidfdinfo(int pid
, int flavor
,int fd
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
);
129 int __attribute__ ((noinline
)) proc_kernmsgbuf(user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
);
130 int __attribute__ ((noinline
)) proc_setcontrol(int pid
, int flavor
, uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
);
131 int __attribute__ ((noinline
)) proc_pidfileportinfo(int pid
, int flavor
, mach_port_name_t name
, user_addr_t buffer
, uint32_t buffersize
, int32_t *retval
);
132 int __attribute__ ((noinline
)) proc_dirtycontrol(int pid
, int flavor
, uint64_t arg
, int32_t * retval
);
133 int __attribute__ ((noinline
)) proc_terminate(int pid
, int32_t * retval
);
134 int __attribute__ ((noinline
)) proc_pid_rusage(int pid
, int flavor
, user_addr_t buffer
, int32_t * retval
);
135 int __attribute__ ((noinline
)) proc_pidoriginatorinfo(int pid
, int flavor
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
);
137 /* protos for procpidinfo calls */
138 int __attribute__ ((noinline
)) proc_pidfdlist(proc_t p
, user_addr_t buffer
, uint32_t buffersize
, int32_t *retval
);
139 int __attribute__ ((noinline
)) proc_pidbsdinfo(proc_t p
, struct proc_bsdinfo
*pbsd
, int zombie
);
140 int __attribute__ ((noinline
)) proc_pidshortbsdinfo(proc_t p
, struct proc_bsdshortinfo
*pbsd_shortp
, int zombie
);
141 int __attribute__ ((noinline
)) proc_pidtaskinfo(proc_t p
, struct proc_taskinfo
*ptinfo
);
142 int __attribute__ ((noinline
)) proc_pidthreadinfo(proc_t p
, uint64_t arg
, int thuniqueid
, struct proc_threadinfo
*pthinfo
);
143 int __attribute__ ((noinline
)) proc_pidthreadpathinfo(proc_t p
, uint64_t arg
, struct proc_threadwithpathinfo
*pinfo
);
144 int __attribute__ ((noinline
)) proc_pidlistthreads(proc_t p
, user_addr_t buffer
, uint32_t buffersize
, int32_t *retval
);
145 int __attribute__ ((noinline
)) proc_pidregioninfo(proc_t p
, uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, int32_t *retval
);
146 int __attribute__ ((noinline
)) proc_pidregionpathinfo(proc_t p
, uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, int32_t *retval
);
147 int __attribute__ ((noinline
)) proc_pidregionpathinfo2(proc_t p
, uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, int32_t *retval
);
148 int __attribute__ ((noinline
)) proc_pidregionpathinfo3(proc_t p
, uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, int32_t *retval
);
149 int __attribute__ ((noinline
)) proc_pidvnodepathinfo(proc_t p
, uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, int32_t *retval
);
150 int __attribute__ ((noinline
)) proc_pidpathinfo(proc_t p
, uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, int32_t *retval
);
151 int __attribute__ ((noinline
)) proc_pidworkqueueinfo(proc_t p
, struct proc_workqueueinfo
*pwqinfo
);
152 int __attribute__ ((noinline
)) proc_pidfileportlist(proc_t p
, user_addr_t buffer
, uint32_t buffersize
, int32_t *retval
);
153 void __attribute__ ((noinline
)) proc_piduniqidentifierinfo(proc_t p
, struct proc_uniqidentifierinfo
*p_uniqidinfo
);
154 void __attribute__ ((noinline
)) proc_archinfo(proc_t p
, struct proc_archinfo
*pai
);
155 void __attribute__ ((noinline
)) proc_pidcoalitioninfo(proc_t p
, struct proc_pidcoalitioninfo
*pci
);
156 int __attribute__ ((noinline
)) proc_pidnoteexit(proc_t p
, uint64_t arg
, uint32_t *data
);
159 /* protos for proc_pidfdinfo calls */
160 int __attribute__ ((noinline
)) pid_vnodeinfo(vnode_t vp
, uint32_t vid
, struct fileproc
* fp
, int closeonexec
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
);
161 int __attribute__ ((noinline
)) pid_vnodeinfopath(vnode_t vp
, uint32_t vid
, struct fileproc
* fp
, int closeonexec
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
);
162 int __attribute__ ((noinline
)) pid_socketinfo(socket_t so
, struct fileproc
*fp
, int closeonexec
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
);
163 int __attribute__ ((noinline
)) pid_pseminfo(struct psemnode
* psem
, struct fileproc
* fp
, int closeonexec
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
);
164 int __attribute__ ((noinline
)) pid_pshminfo(struct pshmnode
* pshm
, struct fileproc
* fp
, int closeonexec
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
);
165 int __attribute__ ((noinline
)) pid_pipeinfo(struct pipe
* p
, struct fileproc
* fp
, int closeonexec
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
);
166 int __attribute__ ((noinline
)) pid_kqueueinfo(struct kqueue
* kq
, struct fileproc
* fp
, int closeonexec
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
);
167 int __attribute__ ((noinline
)) pid_atalkinfo(struct atalk
* at
, struct fileproc
* fp
, int closeonexec
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
);
170 /* protos for misc */
172 int fill_vnodeinfo(vnode_t vp
, struct vnode_info
*vinfo
);
173 void fill_fileinfo(struct fileproc
* fp
, int closeonexec
, struct proc_fileinfo
* finfo
);
174 int proc_security_policy(proc_t targetp
, int callnum
, int flavor
, boolean_t check_same_user
);
175 static void munge_vinfo_stat(struct stat64
*sbp
, struct vinfo_stat
*vsbp
);
176 static int proc_piduuidinfo(pid_t pid
, uuid_t uuid_buf
, uint32_t buffersize
);
178 extern int cansignal(struct proc
*, kauth_cred_t
, struct proc
*, int, int);
179 extern int proc_get_rusage(proc_t proc
, int flavor
, user_addr_t buffer
, int is_zombie
);
181 #define CHECK_SAME_USER TRUE
182 #define NO_CHECK_SAME_USER FALSE
184 uint64_t get_dispatchqueue_offset_from_proc(void *p
)
187 proc_t pself
= (proc_t
)p
;
188 return (pself
->p_dispatchqueue_offset
);
194 uint64_t get_dispatchqueue_serialno_offset_from_proc(void *p
)
197 proc_t pself
= (proc_t
)p
;
198 return (pself
->p_dispatchqueue_serialno_offset
);
204 /***************************** proc_info ********************/
207 proc_info(__unused
struct proc
*p
, struct proc_info_args
* uap
, int32_t *retval
)
209 return(proc_info_internal(uap
->callnum
, uap
->pid
, uap
->flavor
, uap
->arg
, uap
->buffer
, uap
->buffersize
, retval
));
214 proc_info_internal(int callnum
, int pid
, int flavor
, uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
)
218 case PROC_INFO_CALL_LISTPIDS
:
219 /* pid contains type and flavor contains typeinfo */
220 return(proc_listpids(pid
, flavor
, buffer
, buffersize
, retval
));
221 case PROC_INFO_CALL_PIDINFO
:
222 return(proc_pidinfo(pid
, flavor
, arg
, buffer
, buffersize
, retval
));
223 case PROC_INFO_CALL_PIDFDINFO
:
224 return(proc_pidfdinfo(pid
, flavor
, (int)arg
, buffer
, buffersize
, retval
));
225 case PROC_INFO_CALL_KERNMSGBUF
:
226 return(proc_kernmsgbuf(buffer
, buffersize
, retval
));
227 case PROC_INFO_CALL_SETCONTROL
:
228 return(proc_setcontrol(pid
, flavor
, arg
, buffer
, buffersize
, retval
));
229 case PROC_INFO_CALL_PIDFILEPORTINFO
:
230 return(proc_pidfileportinfo(pid
, flavor
, (mach_port_name_t
)arg
, buffer
, buffersize
, retval
));
231 case PROC_INFO_CALL_TERMINATE
:
232 return(proc_terminate(pid
, retval
));
233 case PROC_INFO_CALL_DIRTYCONTROL
:
234 return(proc_dirtycontrol(pid
, flavor
, arg
, retval
));
235 case PROC_INFO_CALL_PIDRUSAGE
:
236 return (proc_pid_rusage(pid
, flavor
, buffer
, retval
));
237 case PROC_INFO_CALL_PIDORIGINATORINFO
:
238 return (proc_pidoriginatorinfo(pid
, flavor
, buffer
, buffersize
, retval
));
246 /******************* proc_listpids routine ****************/
248 proc_listpids(uint32_t type
, uint32_t typeinfo
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
)
250 int numprocs
, wantpids
;
257 struct proclist
*current_list
;
259 /* Do we have permission to look into this? */
260 if ((error
= proc_security_policy(PROC_NULL
, PROC_INFO_CALL_LISTPIDS
, type
, NO_CHECK_SAME_USER
)))
263 /* if the buffer is null, return num of procs */
264 if (buffer
== (user_addr_t
)0) {
265 *retval
= ((nprocs
+20) * sizeof(int));
269 if (buffersize
< sizeof(int)) {
272 wantpids
= buffersize
/sizeof(int);
273 numprocs
= nprocs
+20;
274 if (numprocs
> wantpids
)
277 kbuf
= (char *)kalloc((vm_size_t
)(numprocs
* sizeof(int)));
280 bzero(kbuf
, sizeof(int));
287 current_list
= &allproc
;
289 LIST_FOREACH(p
, current_list
, p_list
) {
293 if (p
->p_pgrpid
!= (pid_t
)typeinfo
)
297 if ((p
->p_ppid
!= (pid_t
)typeinfo
) && (((p
->p_lflag
& P_LTRACED
) == 0) || (p
->p_oppid
!= (pid_t
)typeinfo
)))
305 /* racy but list lock is held */
306 if ((p
->p_flag
& P_CONTROLT
) == 0 ||
307 (p
->p_pgrp
== NULL
) || (p
->p_pgrp
->pg_session
== NULL
) ||
308 (tp
= SESSION_TP(p
->p_pgrp
->pg_session
)) == TTY_NULL
||
309 tp
->t_dev
!= (dev_t
)typeinfo
)
313 if (p
->p_ucred
== NULL
)
316 kauth_cred_t my_cred
;
319 my_cred
= kauth_cred_proc_ref(p
);
320 uid
= kauth_cred_getuid(my_cred
);
321 kauth_cred_unref(&my_cred
);
322 if (uid
!= (uid_t
)typeinfo
)
327 if (p
->p_ucred
== NULL
)
330 kauth_cred_t my_cred
;
333 my_cred
= kauth_cred_proc_ref(p
);
334 uid
= kauth_cred_getruid(my_cred
);
335 kauth_cred_unref(&my_cred
);
336 if (uid
!= (uid_t
)typeinfo
)
353 if ((n
< numprocs
) && (current_list
== &allproc
)) {
354 current_list
= &zombproc
;
361 error
= copyout((caddr_t
)ptr
, buffer
, n
* sizeof(int));
363 *retval
= (n
* sizeof(int));
364 kfree((void *)kbuf
, (vm_size_t
)(numprocs
* sizeof(int)));
370 /********************************** proc_pidfdlist routines ********************************/
373 proc_pidfdlist(proc_t p
, user_addr_t buffer
, uint32_t buffersize
, int32_t *retval
)
377 struct proc_fdinfo
* pfd
;
378 struct fileproc
* fp
;
383 numfds
= p
->p_fd
->fd_nfiles
;
385 if (buffer
== (user_addr_t
) 0) {
387 *retval
= (numfds
* sizeof(struct proc_fdinfo
));
391 /* buffersize is big enough atleast for one struct */
392 needfds
= buffersize
/sizeof(struct proc_fdinfo
);
394 if (numfds
> needfds
)
397 kbuf
= (char *)kalloc((vm_size_t
)(numfds
* sizeof(struct proc_fdinfo
)));
400 bzero(kbuf
, numfds
* sizeof(struct proc_fdinfo
));
404 pfd
= (struct proc_fdinfo
*)kbuf
;
406 for (n
= 0; ((n
< numfds
) && (n
< p
->p_fd
->fd_nfiles
)); n
++) {
407 if (((fp
= p
->p_fd
->fd_ofiles
[n
]) != 0)
408 && ((p
->p_fd
->fd_ofileflags
[n
] & UF_RESERVED
) == 0)) {
409 file_type_t fdtype
= FILEGLOB_DTYPE(fp
->f_fglob
);
411 pfd
->proc_fdtype
= (fdtype
!= DTYPE_ATALK
) ?
412 fdtype
: PROX_FDTYPE_ATALK
;
419 error
= copyout(kbuf
, buffer
, count
* sizeof(struct proc_fdinfo
));
420 kfree((void *)kbuf
, (vm_size_t
)(numfds
* sizeof(struct proc_fdinfo
)));
422 *retval
= (count
* sizeof(struct proc_fdinfo
));
427 * Helper functions for proc_pidfileportlist.
430 proc_fileport_count(__unused mach_port_name_t name
,
431 __unused
struct fileglob
*fg
, void *arg
)
433 uint32_t *counter
= arg
;
439 struct fileport_fdtype_args
{
440 struct proc_fileportinfo
*ffa_pfi
;
441 struct proc_fileportinfo
*ffa_pfi_end
;
445 proc_fileport_fdtype(mach_port_name_t name
, struct fileglob
*fg
, void *arg
)
447 struct fileport_fdtype_args
*ffa
= arg
;
449 if (ffa
->ffa_pfi
!= ffa
->ffa_pfi_end
) {
450 file_type_t fdtype
= FILEGLOB_DTYPE(fg
);
452 ffa
->ffa_pfi
->proc_fdtype
= (fdtype
!= DTYPE_ATALK
) ?
453 fdtype
: PROX_FDTYPE_ATALK
;
454 ffa
->ffa_pfi
->proc_fileport
= name
;
456 return (0); /* keep walking */
458 return (-1); /* stop the walk! */
462 proc_pidfileportlist(proc_t p
,
463 user_addr_t buffer
, uint32_t buffersize
, int32_t *retval
)
467 struct proc_fileportinfo
*pfi
;
468 uint32_t needfileports
, numfileports
;
469 struct fileport_fdtype_args ffa
;
472 needfileports
= buffersize
/ sizeof (*pfi
);
473 if ((user_addr_t
)0 == buffer
|| needfileports
> (uint32_t)maxfiles
) {
475 * Either (i) the user is asking for a fileport count,
476 * or (ii) the number of fileports they're asking for is
477 * larger than the maximum number of open files (!); count
478 * them to bound subsequent heap allocations.
481 switch (fileport_walk(p
->task
,
482 proc_fileport_count
, &numfileports
)) {
485 case KERN_RESOURCE_SHORTAGE
:
487 case KERN_INVALID_TASK
:
493 if (numfileports
== 0) {
494 *retval
= 0; /* none at all, bail */
497 if ((user_addr_t
)0 == buffer
) {
498 numfileports
+= 20; /* accelerate convergence */
499 *retval
= numfileports
* sizeof (*pfi
);
502 if (needfileports
> numfileports
)
503 needfileports
= numfileports
;
506 assert(buffersize
>= PROC_PIDLISTFILEPORTS_SIZE
);
508 kbufsize
= (vm_size_t
)needfileports
* sizeof (*pfi
);
509 pfi
= kbuf
= kalloc(kbufsize
);
512 bzero(kbuf
, kbufsize
);
515 ffa
.ffa_pfi_end
= pfi
+ needfileports
;
517 switch (fileport_walk(p
->task
, proc_fileport_fdtype
, &ffa
)) {
521 if ((numfileports
= pfi
- (typeof(pfi
))kbuf
) == 0)
523 if (numfileports
> needfileports
)
524 panic("more fileports returned than requested");
525 error
= copyout(kbuf
, buffer
, numfileports
* sizeof (*pfi
));
527 case KERN_RESOURCE_SHORTAGE
:
530 case KERN_INVALID_TASK
:
537 kfree(kbuf
, kbufsize
);
539 *retval
= numfileports
* sizeof (*pfi
);
544 proc_pidbsdinfo(proc_t p
, struct proc_bsdinfo
* pbsd
, int zombie
)
546 register struct tty
*tp
;
547 struct session
*sessionp
= NULL
;
549 kauth_cred_t my_cred
;
552 sessionp
= proc_session(p
);
554 my_cred
= kauth_cred_proc_ref(p
);
555 bzero(pbsd
, sizeof(struct proc_bsdinfo
));
556 pbsd
->pbi_status
= p
->p_stat
;
557 pbsd
->pbi_xstatus
= p
->p_xstat
;
558 pbsd
->pbi_pid
= p
->p_pid
;
559 pbsd
->pbi_ppid
= p
->p_ppid
;
560 pbsd
->pbi_uid
= kauth_cred_getuid(my_cred
);
561 pbsd
->pbi_gid
= kauth_cred_getgid(my_cred
);
562 pbsd
->pbi_ruid
= kauth_cred_getruid(my_cred
);
563 pbsd
->pbi_rgid
= kauth_cred_getrgid(my_cred
);
564 pbsd
->pbi_svuid
= kauth_cred_getsvuid(my_cred
);
565 pbsd
->pbi_svgid
= kauth_cred_getsvgid(my_cred
);
566 kauth_cred_unref(&my_cred
);
568 pbsd
->pbi_nice
= p
->p_nice
;
569 pbsd
->pbi_start_tvsec
= p
->p_start
.tv_sec
;
570 pbsd
->pbi_start_tvusec
= p
->p_start
.tv_usec
;
571 bcopy(&p
->p_comm
, &pbsd
->pbi_comm
[0], MAXCOMLEN
);
572 pbsd
->pbi_comm
[MAXCOMLEN
- 1] = '\0';
573 bcopy(&p
->p_name
, &pbsd
->pbi_name
[0], 2*MAXCOMLEN
);
574 pbsd
->pbi_name
[(2*MAXCOMLEN
) - 1] = '\0';
577 if ((p
->p_flag
& P_SYSTEM
) == P_SYSTEM
)
578 pbsd
->pbi_flags
|= PROC_FLAG_SYSTEM
;
579 if ((p
->p_lflag
& P_LTRACED
) == P_LTRACED
)
580 pbsd
->pbi_flags
|= PROC_FLAG_TRACED
;
581 if ((p
->p_lflag
& P_LEXIT
) == P_LEXIT
)
582 pbsd
->pbi_flags
|= PROC_FLAG_INEXIT
;
583 if ((p
->p_lflag
& P_LPPWAIT
) == P_LPPWAIT
)
584 pbsd
->pbi_flags
|= PROC_FLAG_PPWAIT
;
585 if ((p
->p_flag
& P_LP64
) == P_LP64
)
586 pbsd
->pbi_flags
|= PROC_FLAG_LP64
;
587 if ((p
->p_flag
& P_CONTROLT
) == P_CONTROLT
)
588 pbsd
->pbi_flags
|= PROC_FLAG_CONTROLT
;
589 if ((p
->p_flag
& P_THCWD
) == P_THCWD
)
590 pbsd
->pbi_flags
|= PROC_FLAG_THCWD
;
591 if ((p
->p_flag
& P_SUGID
) == P_SUGID
)
592 pbsd
->pbi_flags
|= PROC_FLAG_PSUGID
;
593 if ((p
->p_flag
& P_EXEC
) == P_EXEC
)
594 pbsd
->pbi_flags
|= PROC_FLAG_EXEC
;
596 if (sessionp
!= SESSION_NULL
) {
597 if (SESS_LEADER(p
, sessionp
))
598 pbsd
->pbi_flags
|= PROC_FLAG_SLEADER
;
599 if (sessionp
->s_ttyvp
)
600 pbsd
->pbi_flags
|= PROC_FLAG_CTTY
;
603 if ((p
->p_flag
& P_DELAYIDLESLEEP
) == P_DELAYIDLESLEEP
)
604 pbsd
->pbi_flags
|= PROC_FLAG_DELAYIDLESLEEP
;
606 switch(PROC_CONTROL_STATE(p
)) {
608 pbsd
->pbi_flags
|= PROC_FLAG_PC_THROTTLE
;
611 pbsd
->pbi_flags
|= PROC_FLAG_PC_SUSP
;
614 pbsd
->pbi_flags
|= PROC_FLAG_PC_KILL
;
618 switch(PROC_ACTION_STATE(p
)) {
620 pbsd
->pbi_flags
|= PROC_FLAG_PA_THROTTLE
;
623 pbsd
->pbi_flags
|= PROC_FLAG_PA_SUSP
;
627 /* if process is a zombie skip bg state */
628 if ((zombie
== 0) && (p
->p_stat
!= SZOMB
) && (p
->task
!= TASK_NULL
))
629 proc_get_darwinbgstate(p
->task
, &pbsd
->pbi_flags
);
632 pbsd
->pbi_nfiles
= p
->p_fd
->fd_nfiles
;
634 pbsd
->e_tdev
= NODEV
;
635 if (pg
!= PGRP_NULL
) {
636 pbsd
->pbi_pgid
= p
->p_pgrpid
;
637 pbsd
->pbi_pjobc
= pg
->pg_jobc
;
638 if ((p
->p_flag
& P_CONTROLT
) && (sessionp
!= SESSION_NULL
) && (tp
= SESSION_TP(sessionp
))) {
639 pbsd
->e_tdev
= tp
->t_dev
;
640 pbsd
->e_tpgid
= sessionp
->s_ttypgrpid
;
643 if (sessionp
!= SESSION_NULL
)
644 session_rele(sessionp
);
653 proc_pidshortbsdinfo(proc_t p
, struct proc_bsdshortinfo
* pbsd_shortp
, int zombie
)
655 bzero(pbsd_shortp
, sizeof(struct proc_bsdshortinfo
));
656 pbsd_shortp
->pbsi_pid
= p
->p_pid
;
657 pbsd_shortp
->pbsi_ppid
= p
->p_ppid
;
658 pbsd_shortp
->pbsi_pgid
= p
->p_pgrpid
;
659 pbsd_shortp
->pbsi_status
= p
->p_stat
;
660 bcopy(&p
->p_comm
, &pbsd_shortp
->pbsi_comm
[0], MAXCOMLEN
);
661 pbsd_shortp
->pbsi_comm
[MAXCOMLEN
- 1] = '\0';
663 pbsd_shortp
->pbsi_flags
= 0;
664 if ((p
->p_flag
& P_SYSTEM
) == P_SYSTEM
)
665 pbsd_shortp
->pbsi_flags
|= PROC_FLAG_SYSTEM
;
666 if ((p
->p_lflag
& P_LTRACED
) == P_LTRACED
)
667 pbsd_shortp
->pbsi_flags
|= PROC_FLAG_TRACED
;
668 if ((p
->p_lflag
& P_LEXIT
) == P_LEXIT
)
669 pbsd_shortp
->pbsi_flags
|= PROC_FLAG_INEXIT
;
670 if ((p
->p_lflag
& P_LPPWAIT
) == P_LPPWAIT
)
671 pbsd_shortp
->pbsi_flags
|= PROC_FLAG_PPWAIT
;
672 if ((p
->p_flag
& P_LP64
) == P_LP64
)
673 pbsd_shortp
->pbsi_flags
|= PROC_FLAG_LP64
;
674 if ((p
->p_flag
& P_CONTROLT
) == P_CONTROLT
)
675 pbsd_shortp
->pbsi_flags
|= PROC_FLAG_CONTROLT
;
676 if ((p
->p_flag
& P_THCWD
) == P_THCWD
)
677 pbsd_shortp
->pbsi_flags
|= PROC_FLAG_THCWD
;
678 if ((p
->p_flag
& P_SUGID
) == P_SUGID
)
679 pbsd_shortp
->pbsi_flags
|= PROC_FLAG_PSUGID
;
680 if ((p
->p_flag
& P_EXEC
) == P_EXEC
)
681 pbsd_shortp
->pbsi_flags
|= PROC_FLAG_EXEC
;
682 if ((p
->p_flag
& P_DELAYIDLESLEEP
) == P_DELAYIDLESLEEP
)
683 pbsd_shortp
->pbsi_flags
|= PROC_FLAG_DELAYIDLESLEEP
;
685 switch(PROC_CONTROL_STATE(p
)) {
687 pbsd_shortp
->pbsi_flags
|= PROC_FLAG_PC_THROTTLE
;
690 pbsd_shortp
->pbsi_flags
|= PROC_FLAG_PC_SUSP
;
693 pbsd_shortp
->pbsi_flags
|= PROC_FLAG_PC_KILL
;
697 switch(PROC_ACTION_STATE(p
)) {
699 pbsd_shortp
->pbsi_flags
|= PROC_FLAG_PA_THROTTLE
;
702 pbsd_shortp
->pbsi_flags
|= PROC_FLAG_PA_SUSP
;
706 /* if process is a zombie skip bg state */
707 if ((zombie
== 0) && (p
->p_stat
!= SZOMB
) && (p
->task
!= TASK_NULL
))
708 proc_get_darwinbgstate(p
->task
, &pbsd_shortp
->pbsi_flags
);
710 pbsd_shortp
->pbsi_uid
= p
->p_uid
;
711 pbsd_shortp
->pbsi_gid
= p
->p_gid
;
712 pbsd_shortp
->pbsi_ruid
= p
->p_ruid
;
713 pbsd_shortp
->pbsi_rgid
= p
->p_rgid
;
714 pbsd_shortp
->pbsi_svuid
= p
->p_svuid
;
715 pbsd_shortp
->pbsi_svgid
= p
->p_svgid
;
721 proc_pidtaskinfo(proc_t p
, struct proc_taskinfo
* ptinfo
)
727 bzero(ptinfo
, sizeof(struct proc_taskinfo
));
728 fill_taskprocinfo(task
, (struct proc_taskinfo_internal
*)ptinfo
);
736 proc_pidthreadinfo(proc_t p
, uint64_t arg
, int thuniqueid
, struct proc_threadinfo
*pthinfo
)
739 uint64_t threadaddr
= (uint64_t)arg
;
741 bzero(pthinfo
, sizeof(struct proc_threadinfo
));
743 error
= fill_taskthreadinfo(p
->task
, threadaddr
, thuniqueid
, (struct proc_threadinfo_internal
*)pthinfo
, NULL
, NULL
);
752 bsd_getthreadname(void *uth
, char *buffer
)
754 struct uthread
*ut
= (struct uthread
*)uth
;
756 bcopy(ut
->pth_name
,buffer
,MAXTHREADNAMESIZE
);
760 bsd_threadcdir(void * uth
, void *vptr
, int *vidp
)
762 struct uthread
* ut
= (struct uthread
*)uth
;
764 vnode_t
*vpp
= (vnode_t
*)vptr
;
778 proc_pidthreadpathinfo(proc_t p
, uint64_t arg
, struct proc_threadwithpathinfo
*pinfo
)
783 uint64_t threadaddr
= (uint64_t)arg
;
786 bzero(pinfo
, sizeof(struct proc_threadwithpathinfo
));
788 error
= fill_taskthreadinfo(p
->task
, threadaddr
, 0, (struct proc_threadinfo_internal
*)&pinfo
->pt
, (void *)&vp
, &vid
);
792 if ((vp
!= NULLVP
) && ((vnode_getwithvid(vp
, vid
)) == 0)) {
793 error
= fill_vnodeinfo(vp
, &pinfo
->pvip
.vip_vi
) ;
796 vn_getpath(vp
, &pinfo
->pvip
.vip_path
[0], &count
);
797 pinfo
->pvip
.vip_path
[MAXPATHLEN
-1] = 0;
807 proc_pidlistthreads(proc_t p
, user_addr_t buffer
, uint32_t buffersize
, int32_t *retval
)
816 count
= buffersize
/(sizeof(uint64_t));
817 numthreads
= get_numthreads(p
->task
);
821 if (numthreads
> count
)
824 kbuf
= (void *)kalloc(numthreads
* sizeof(uint64_t));
827 bzero(kbuf
, numthreads
* sizeof(uint64_t));
829 ret
= fill_taskthreadlist(p
->task
, kbuf
, numthreads
);
831 error
= copyout(kbuf
, buffer
, ret
);
832 kfree(kbuf
, numthreads
* sizeof(uint64_t));
841 proc_pidregioninfo(proc_t p
, uint64_t arg
, user_addr_t buffer
, __unused
uint32_t buffersize
, int32_t *retval
)
843 struct proc_regioninfo preginfo
;
846 bzero(&preginfo
, sizeof(struct proc_regioninfo
));
847 ret
= fill_procregioninfo( p
->task
, arg
, (struct proc_regioninfo_internal
*)&preginfo
, (uintptr_t *)0, (uint32_t *)0);
850 error
= copyout(&preginfo
, buffer
, sizeof(struct proc_regioninfo
));
852 *retval
= sizeof(struct proc_regioninfo
);
858 proc_pidregionpathinfo(proc_t p
, uint64_t arg
, user_addr_t buffer
, __unused
uint32_t buffersize
, int32_t *retval
)
860 struct proc_regionwithpathinfo preginfo
;
862 uintptr_t vnodeaddr
= 0;
867 bzero(&preginfo
, sizeof(struct proc_regionwithpathinfo
));
869 ret
= fill_procregioninfo( p
->task
, arg
, (struct proc_regioninfo_internal
*)&preginfo
.prp_prinfo
, (uintptr_t *)&vnodeaddr
, (uint32_t *)&vnodeid
);
873 vp
= (vnode_t
)vnodeaddr
;
874 if ((vnode_getwithvid(vp
, vnodeid
)) == 0) {
875 /* FILL THE VNODEINFO */
876 error
= fill_vnodeinfo(vp
, &preginfo
.prp_vip
.vip_vi
);
878 vn_getpath(vp
, &preginfo
.prp_vip
.vip_path
[0], &count
);
879 /* Always make sure it is null terminated */
880 preginfo
.prp_vip
.vip_path
[MAXPATHLEN
-1] = 0;
884 error
= copyout(&preginfo
, buffer
, sizeof(struct proc_regionwithpathinfo
));
886 *retval
= sizeof(struct proc_regionwithpathinfo
);
891 proc_pidregionpathinfo2(proc_t p
, uint64_t arg
, user_addr_t buffer
, __unused
uint32_t buffersize
, int32_t *retval
)
893 struct proc_regionwithpathinfo preginfo
;
895 uintptr_t vnodeaddr
= 0;
900 bzero(&preginfo
, sizeof(struct proc_regionwithpathinfo
));
902 ret
= fill_procregioninfo_onlymappedvnodes( p
->task
, arg
, (struct proc_regioninfo_internal
*)&preginfo
.prp_prinfo
, (uintptr_t *)&vnodeaddr
, (uint32_t *)&vnodeid
);
908 vp
= (vnode_t
)vnodeaddr
;
909 if ((vnode_getwithvid(vp
, vnodeid
)) == 0) {
910 /* FILL THE VNODEINFO */
911 error
= fill_vnodeinfo(vp
, &preginfo
.prp_vip
.vip_vi
);
913 vn_getpath(vp
, &preginfo
.prp_vip
.vip_path
[0], &count
);
914 /* Always make sure it is null terminated */
915 preginfo
.prp_vip
.vip_path
[MAXPATHLEN
-1] = 0;
921 error
= copyout(&preginfo
, buffer
, sizeof(struct proc_regionwithpathinfo
));
923 *retval
= sizeof(struct proc_regionwithpathinfo
);
928 proc_pidregionpathinfo3(proc_t p
, uint64_t arg
, user_addr_t buffer
, __unused
uint32_t buffersize
, int32_t *retval
)
930 struct proc_regionwithpathinfo preginfo
;
938 /* Loop while looking for vnodes that match dev_t filter */
940 bzero(&preginfo
, sizeof(struct proc_regionwithpathinfo
));
944 ret
= fill_procregioninfo_onlymappedvnodes( p
->task
, addr
, (struct proc_regioninfo_internal
*)&preginfo
.prp_prinfo
, (uintptr_t *)&vnodeaddr
, (uint32_t *)&vnodeid
);
950 vp
= (vnode_t
)vnodeaddr
;
951 if ((vnode_getwithvid(vp
, vnodeid
)) == 0) {
952 /* Check if the vnode matches the filter, otherwise loop looking for the next memory region backed by a vnode */
953 struct vnode_attr va
;
955 memset(&va
, 0, sizeof(va
));
957 VATTR_WANTED(&va
, va_fsid
);
959 ret
= vnode_getattr(vp
, &va
, vfs_context_current());
965 if (va
.va_fsid
== arg
) {
966 /* FILL THE VNODEINFO */
967 error
= fill_vnodeinfo(vp
, &preginfo
.prp_vip
.vip_vi
);
969 vn_getpath(vp
, &preginfo
.prp_vip
.vip_path
[0], &count
);
970 /* Always make sure it is null terminated */
971 preginfo
.prp_vip
.vip_path
[MAXPATHLEN
-1] = 0;
980 addr
= preginfo
.prp_prinfo
.pri_address
+ preginfo
.prp_prinfo
.pri_size
;
983 error
= copyout(&preginfo
, buffer
, sizeof(struct proc_regionwithpathinfo
));
985 *retval
= sizeof(struct proc_regionwithpathinfo
);
990 * Path is relative to current process directory; may different from current
994 proc_pidvnodepathinfo(proc_t p
, __unused
uint64_t arg
, user_addr_t buffer
, __unused
uint32_t buffersize
, int32_t *retval
)
996 struct proc_vnodepathinfo pvninfo
;
998 vnode_t vncdirvp
= NULLVP
;
1000 vnode_t vnrdirvp
= NULLVP
;
1001 uint32_t vnrdirid
=0;
1004 bzero(&pvninfo
, sizeof(struct proc_vnodepathinfo
));
1007 if (p
->p_fd
->fd_cdir
) {
1008 vncdirvp
= p
->p_fd
->fd_cdir
;
1009 vncdirid
= p
->p_fd
->fd_cdir
->v_id
;
1011 if (p
->p_fd
->fd_rdir
) {
1012 vnrdirvp
= p
->p_fd
->fd_rdir
;
1013 vnrdirid
= p
->p_fd
->fd_rdir
->v_id
;
1017 if (vncdirvp
!= NULLVP
) {
1018 if ((error
= vnode_getwithvid(vncdirvp
, vncdirid
)) == 0) {
1019 /* FILL THE VNODEINFO */
1020 error
= fill_vnodeinfo(vncdirvp
, &pvninfo
.pvi_cdir
.vip_vi
);
1023 vn_getpath(vncdirvp
, &pvninfo
.pvi_cdir
.vip_path
[0], &count
);
1024 pvninfo
.pvi_cdir
.vip_path
[MAXPATHLEN
-1] = 0;
1026 vnode_put(vncdirvp
);
1032 if ((error
== 0) && (vnrdirvp
!= NULLVP
)) {
1033 if ((error
= vnode_getwithvid(vnrdirvp
, vnrdirid
)) == 0) {
1034 /* FILL THE VNODEINFO */
1035 error
= fill_vnodeinfo(vnrdirvp
, &pvninfo
.pvi_rdir
.vip_vi
);
1038 vn_getpath(vnrdirvp
, &pvninfo
.pvi_rdir
.vip_path
[0], &count
);
1039 pvninfo
.pvi_rdir
.vip_path
[MAXPATHLEN
-1] = 0;
1041 vnode_put(vnrdirvp
);
1047 error
= copyout(&pvninfo
, buffer
, sizeof(struct proc_vnodepathinfo
));
1049 *retval
= sizeof(struct proc_vnodepathinfo
);
1056 proc_pidpathinfo(proc_t p
, __unused
uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, __unused
int32_t *retval
)
1060 vnode_t nvp
= NULLVP
;
1061 int len
= buffersize
;
1069 buf
= (char *)kalloc(buffersize
);
1074 vid
= vnode_vid(tvp
);
1075 error
= vnode_getwithvid(tvp
, vid
);
1077 error
= vn_getpath_fsenter(tvp
, buf
, &len
);
1080 error
= vnode_lookup(buf
, 0, &nvp
, vfs_context_current());
1081 if ((error
== 0) && ( nvp
!= NULLVP
))
1084 error
= copyout(buf
, buffer
, len
);
1088 kfree(buf
, buffersize
);
1094 proc_pidworkqueueinfo(proc_t p
, struct proc_workqueueinfo
*pwqinfo
)
1098 bzero(pwqinfo
, sizeof(struct proc_workqueueinfo
));
1100 error
= fill_procworkqueue(p
, pwqinfo
);
1110 proc_piduniqidentifierinfo(proc_t p
, struct proc_uniqidentifierinfo
*p_uniqidinfo
)
1112 p_uniqidinfo
->p_uniqueid
= proc_uniqueid(p
);
1113 proc_getexecutableuuid(p
, (unsigned char *)&p_uniqidinfo
->p_uuid
, sizeof(p_uniqidinfo
->p_uuid
));
1114 p_uniqidinfo
->p_puniqueid
= proc_puniqueid(p
);
1115 p_uniqidinfo
->p_reserve2
= 0;
1116 p_uniqidinfo
->p_reserve3
= 0;
1117 p_uniqidinfo
->p_reserve4
= 0;
1122 proc_piduuidinfo(pid_t pid
, uuid_t uuid_buf
, uint32_t buffersize
)
1124 struct proc
* p
= PROC_NULL
;
1127 if (buffersize
< sizeof(uuid_t
))
1130 if ((p
= proc_find(pid
)) == PROC_NULL
) {
1131 p
= proc_find_zombref(pid
);
1134 if (p
== PROC_NULL
) {
1138 proc_getexecutableuuid(p
, (unsigned char *)uuid_buf
, buffersize
);
1141 proc_drop_zombref(p
);
1149 * Function to get the uuid of the originator of the voucher.
1152 proc_pidoriginatoruuid(uuid_t uuid
, uint32_t buffersize
)
1154 pid_t originator_pid
;
1159 * Get the current voucher origin pid. The pid returned here
1160 * might not be valid or may have been recycled.
1162 kr
= thread_get_current_voucher_origin_pid(&originator_pid
);
1163 /* If errors, convert errors to appropriate format */
1165 if (kr
== KERN_INVALID_TASK
)
1167 else if (kr
== KERN_INVALID_VALUE
)
1174 error
= proc_piduuidinfo(originator_pid
, uuid
, buffersize
);
1178 /***************************** proc_pidoriginatorinfo ***************************/
1181 proc_pidoriginatorinfo(int pid
, int flavor
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
)
1183 int error
= ENOTSUP
;
1187 case PROC_PIDORIGINATOR_UUID
:
1188 size
= PROC_PIDORIGINATOR_UUID_SIZE
;
1190 case PROC_PIDORIGINATOR_BGSTATE
:
1191 size
= PROC_PIDORIGINATOR_BGSTATE_SIZE
;
1197 if (buffersize
< size
)
1200 if (pid
!= 0 && pid
!= proc_selfpid())
1204 case PROC_PIDORIGINATOR_UUID
: {
1207 error
= proc_pidoriginatoruuid(uuid
, sizeof(uuid
));
1211 error
= copyout(uuid
, buffer
, size
);
1217 case PROC_PIDORIGINATOR_BGSTATE
: {
1218 uint32_t is_backgrounded
;
1219 error
= proc_get_originatorbgstate(&is_backgrounded
);
1223 error
= copyout(&is_backgrounded
, buffer
, size
);
1236 /********************************** proc_pidinfo ********************************/
1240 proc_pidinfo(int pid
, int flavor
, uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
)
1242 struct proc
* p
= PROC_NULL
;
1243 int error
= ENOTSUP
;
1246 int shortversion
= 0;
1250 int uniqidversion
= 0;
1251 boolean_t check_same_user
;
1254 case PROC_PIDLISTFDS
:
1255 size
= PROC_PIDLISTFD_SIZE
;
1256 if (buffer
== (user_addr_t
)0)
1259 case PROC_PIDTBSDINFO
:
1260 size
= PROC_PIDTBSDINFO_SIZE
;
1262 case PROC_PIDTASKINFO
:
1263 size
= PROC_PIDTASKINFO_SIZE
;
1265 case PROC_PIDTASKALLINFO
:
1266 size
= PROC_PIDTASKALLINFO_SIZE
;
1268 case PROC_PIDTHREADINFO
:
1269 size
= PROC_PIDTHREADINFO_SIZE
;
1271 case PROC_PIDLISTTHREADS
:
1272 size
= PROC_PIDLISTTHREADS_SIZE
;
1274 case PROC_PIDREGIONINFO
:
1275 size
= PROC_PIDREGIONINFO_SIZE
;
1277 case PROC_PIDREGIONPATHINFO
:
1278 size
= PROC_PIDREGIONPATHINFO_SIZE
;
1280 case PROC_PIDVNODEPATHINFO
:
1281 size
= PROC_PIDVNODEPATHINFO_SIZE
;
1283 case PROC_PIDTHREADPATHINFO
:
1284 size
= PROC_PIDTHREADPATHINFO_SIZE
;
1286 case PROC_PIDPATHINFO
:
1289 case PROC_PIDWORKQUEUEINFO
:
1290 /* kernel does not have workq info */
1294 size
= PROC_PIDWORKQUEUEINFO_SIZE
;
1296 case PROC_PIDT_SHORTBSDINFO
:
1297 size
= PROC_PIDT_SHORTBSDINFO_SIZE
;
1299 case PROC_PIDLISTFILEPORTS
:
1300 size
= PROC_PIDLISTFILEPORTS_SIZE
;
1301 if (buffer
== (user_addr_t
)0)
1304 case PROC_PIDTHREADID64INFO
:
1305 size
= PROC_PIDTHREADID64INFO_SIZE
;
1307 case PROC_PIDUNIQIDENTIFIERINFO
:
1308 size
= PROC_PIDUNIQIDENTIFIERINFO_SIZE
;
1310 case PROC_PIDT_BSDINFOWITHUNIQID
:
1311 size
= PROC_PIDT_BSDINFOWITHUNIQID_SIZE
;
1313 case PROC_PIDARCHINFO
:
1314 size
= PROC_PIDARCHINFO_SIZE
;
1316 case PROC_PIDCOALITIONINFO
:
1317 size
= PROC_PIDCOALITIONINFO_SIZE
;
1319 case PROC_PIDNOTEEXIT
:
1321 * Set findzomb explicitly because arg passed
1322 * in is used as note exit status bits.
1324 size
= PROC_PIDNOTEEXIT_SIZE
;
1327 case PROC_PIDREGIONPATHINFO2
:
1328 size
= PROC_PIDREGIONPATHINFO2_SIZE
;
1330 case PROC_PIDREGIONPATHINFO3
:
1331 size
= PROC_PIDREGIONPATHINFO3_SIZE
;
1337 if (buffersize
< size
)
1340 if ((flavor
== PROC_PIDPATHINFO
) && (buffersize
> PROC_PIDPATHINFO_MAXSIZE
)) {
1344 /* Check if we need to look for zombies */
1345 if ((flavor
== PROC_PIDTBSDINFO
) || (flavor
== PROC_PIDT_SHORTBSDINFO
) || (flavor
== PROC_PIDT_BSDINFOWITHUNIQID
)
1346 || (flavor
== PROC_PIDUNIQIDENTIFIERINFO
)) {
1351 if ((p
= proc_find(pid
)) == PROC_NULL
) {
1353 p
= proc_find_zombref(pid
);
1354 if (p
== PROC_NULL
) {
1363 /* Certain operations don't require privileges */
1365 case PROC_PIDT_SHORTBSDINFO
:
1366 case PROC_PIDUNIQIDENTIFIERINFO
:
1367 case PROC_PIDPATHINFO
:
1368 check_same_user
= NO_CHECK_SAME_USER
;
1371 check_same_user
= CHECK_SAME_USER
;
1375 /* Do we have permission to look into this? */
1376 if ((error
= proc_security_policy(p
, PROC_INFO_CALL_PIDINFO
, flavor
, check_same_user
)))
1380 case PROC_PIDLISTFDS
: {
1381 error
= proc_pidfdlist(p
, buffer
, buffersize
, retval
);
1385 case PROC_PIDUNIQIDENTIFIERINFO
: {
1386 struct proc_uniqidentifierinfo p_uniqidinfo
;
1388 proc_piduniqidentifierinfo(p
, &p_uniqidinfo
);
1389 error
= copyout(&p_uniqidinfo
, buffer
, sizeof(struct proc_uniqidentifierinfo
));
1391 *retval
= sizeof(struct proc_uniqidentifierinfo
);
1395 case PROC_PIDT_SHORTBSDINFO
:
1397 case PROC_PIDT_BSDINFOWITHUNIQID
:
1398 case PROC_PIDTBSDINFO
: {
1399 struct proc_bsdinfo pbsd
;
1400 struct proc_bsdshortinfo pbsd_short
;
1401 struct proc_bsdinfowithuniqid pbsd_uniqid
;
1403 if (flavor
== PROC_PIDT_BSDINFOWITHUNIQID
)
1406 if (shortversion
!= 0) {
1407 error
= proc_pidshortbsdinfo(p
, &pbsd_short
, zombie
);
1409 error
= proc_pidbsdinfo(p
, &pbsd
, zombie
);
1410 if (uniqidversion
!= 0) {
1411 proc_piduniqidentifierinfo(p
, &pbsd_uniqid
.p_uniqidentifier
);
1412 pbsd_uniqid
.pbsd
= pbsd
;
1417 if (shortversion
!= 0) {
1418 error
= copyout(&pbsd_short
, buffer
, sizeof(struct proc_bsdshortinfo
));
1420 *retval
= sizeof(struct proc_bsdshortinfo
);
1421 } else if (uniqidversion
!= 0) {
1422 error
= copyout(&pbsd_uniqid
, buffer
, sizeof(struct proc_bsdinfowithuniqid
));
1424 *retval
= sizeof(struct proc_bsdinfowithuniqid
);
1426 error
= copyout(&pbsd
, buffer
, sizeof(struct proc_bsdinfo
));
1428 *retval
= sizeof(struct proc_bsdinfo
);
1434 case PROC_PIDTASKINFO
: {
1435 struct proc_taskinfo ptinfo
;
1437 error
= proc_pidtaskinfo(p
, &ptinfo
);
1439 error
= copyout(&ptinfo
, buffer
, sizeof(struct proc_taskinfo
));
1441 *retval
= sizeof(struct proc_taskinfo
);
1446 case PROC_PIDTASKALLINFO
: {
1447 struct proc_taskallinfo pall
;
1449 error
= proc_pidbsdinfo(p
, &pall
.pbsd
, 0);
1450 error
= proc_pidtaskinfo(p
, &pall
.ptinfo
);
1452 error
= copyout(&pall
, buffer
, sizeof(struct proc_taskallinfo
));
1454 *retval
= sizeof(struct proc_taskallinfo
);
1459 case PROC_PIDTHREADID64INFO
:
1461 case PROC_PIDTHREADINFO
:{
1462 struct proc_threadinfo pthinfo
;
1464 error
= proc_pidthreadinfo(p
, arg
, thuniqueid
, &pthinfo
);
1466 error
= copyout(&pthinfo
, buffer
, sizeof(struct proc_threadinfo
));
1468 *retval
= sizeof(struct proc_threadinfo
);
1473 case PROC_PIDLISTTHREADS
:{
1474 error
= proc_pidlistthreads(p
, buffer
, buffersize
, retval
);
1478 case PROC_PIDREGIONINFO
:{
1479 error
= proc_pidregioninfo(p
, arg
, buffer
, buffersize
, retval
);
1484 case PROC_PIDREGIONPATHINFO
:{
1485 error
= proc_pidregionpathinfo(p
, arg
, buffer
, buffersize
, retval
);
1489 case PROC_PIDREGIONPATHINFO2
:{
1490 error
= proc_pidregionpathinfo2(p
, arg
, buffer
, buffersize
, retval
);
1494 case PROC_PIDREGIONPATHINFO3
:{
1495 error
= proc_pidregionpathinfo3(p
, arg
, buffer
, buffersize
, retval
);
1499 case PROC_PIDVNODEPATHINFO
:{
1500 error
= proc_pidvnodepathinfo(p
, arg
, buffer
, buffersize
, retval
);
1505 case PROC_PIDTHREADPATHINFO
:{
1506 struct proc_threadwithpathinfo pinfo
;
1508 error
= proc_pidthreadpathinfo(p
, arg
, &pinfo
);
1510 error
= copyout((caddr_t
)&pinfo
, buffer
, sizeof(struct proc_threadwithpathinfo
));
1512 *retval
= sizeof(struct proc_threadwithpathinfo
);
1517 case PROC_PIDPATHINFO
: {
1518 error
= proc_pidpathinfo(p
, arg
, buffer
, buffersize
, retval
);
1523 case PROC_PIDWORKQUEUEINFO
:{
1524 struct proc_workqueueinfo pwqinfo
;
1526 error
= proc_pidworkqueueinfo(p
, &pwqinfo
);
1528 error
= copyout(&pwqinfo
, buffer
, sizeof(struct proc_workqueueinfo
));
1530 *retval
= sizeof(struct proc_workqueueinfo
);
1535 case PROC_PIDLISTFILEPORTS
: {
1536 error
= proc_pidfileportlist(p
, buffer
, buffersize
,
1541 case PROC_PIDARCHINFO
: {
1542 struct proc_archinfo pai
;
1543 proc_archinfo(p
, &pai
);
1544 error
= copyout(&pai
, buffer
, sizeof(struct proc_archinfo
));
1546 *retval
= sizeof(struct proc_archinfo
);
1550 case PROC_PIDCOALITIONINFO
: {
1551 struct proc_pidcoalitioninfo pci
;
1552 proc_pidcoalitioninfo(p
, &pci
);
1553 error
= copyout(&pci
, buffer
, sizeof(struct proc_pidcoalitioninfo
));
1555 *retval
= sizeof(struct proc_pidcoalitioninfo
);
1560 case PROC_PIDNOTEEXIT
: {
1562 error
= proc_pidnoteexit(p
, arg
, &data
);
1564 error
= copyout(&data
, buffer
, sizeof(data
));
1566 *retval
= sizeof(data
);
1580 proc_drop_zombref(p
);
1586 pid_vnodeinfo(vnode_t vp
, uint32_t vid
, struct fileproc
* fp
, int closeonexec
, user_addr_t buffer
, __unused
uint32_t buffersize
, int32_t * retval
)
1588 struct vnode_fdinfo vfi
;
1591 if ((error
= vnode_getwithvid(vp
, vid
)) != 0) {
1594 bzero(&vfi
, sizeof(struct vnode_fdinfo
));
1595 fill_fileinfo(fp
, closeonexec
, &vfi
.pfi
);
1596 error
= fill_vnodeinfo(vp
, &vfi
.pvi
);
1599 error
= copyout((caddr_t
)&vfi
, buffer
, sizeof(struct vnode_fdinfo
));
1601 *retval
= sizeof(struct vnode_fdinfo
);
1607 pid_vnodeinfopath(vnode_t vp
, uint32_t vid
, struct fileproc
* fp
, int closeonexec
, user_addr_t buffer
, __unused
uint32_t buffersize
, int32_t * retval
)
1609 struct vnode_fdinfowithpath vfip
;
1610 int count
, error
= 0;
1612 if ((error
= vnode_getwithvid(vp
, vid
)) != 0) {
1615 bzero(&vfip
, sizeof(struct vnode_fdinfowithpath
));
1616 fill_fileinfo(fp
, closeonexec
, &vfip
.pfi
);
1617 error
= fill_vnodeinfo(vp
, &vfip
.pvip
.vip_vi
) ;
1620 vn_getpath(vp
, &vfip
.pvip
.vip_path
[0], &count
);
1621 vfip
.pvip
.vip_path
[MAXPATHLEN
-1] = 0;
1623 error
= copyout((caddr_t
)&vfip
, buffer
, sizeof(struct vnode_fdinfowithpath
));
1625 *retval
= sizeof(struct vnode_fdinfowithpath
);
1632 fill_fileinfo(struct fileproc
* fp
, int closeonexec
, struct proc_fileinfo
* fproc
)
1634 fproc
->fi_openflags
= fp
->f_fglob
->fg_flag
;
1635 fproc
->fi_status
= 0;
1636 fproc
->fi_offset
= fp
->f_fglob
->fg_offset
;
1637 fproc
->fi_type
= FILEGLOB_DTYPE(fp
->f_fglob
);
1638 if (fp
->f_fglob
->fg_count
> 1)
1639 fproc
->fi_status
|= PROC_FP_SHARED
;
1640 if (closeonexec
!= 0)
1641 fproc
->fi_status
|= PROC_FP_CLEXEC
;
1643 if (FILEPROC_TYPE(fp
) == FTYPE_GUARDED
) {
1644 fproc
->fi_status
|= PROC_FP_GUARDED
;
1645 fproc
->fi_guardflags
= 0;
1646 if (fp_isguarded(fp
, GUARD_CLOSE
))
1647 fproc
->fi_guardflags
|= PROC_FI_GUARD_CLOSE
;
1648 if (fp_isguarded(fp
, GUARD_DUP
))
1649 fproc
->fi_guardflags
|= PROC_FI_GUARD_DUP
;
1650 if (fp_isguarded(fp
, GUARD_SOCKET_IPC
))
1651 fproc
->fi_guardflags
|= PROC_FI_GUARD_SOCKET_IPC
;
1652 if (fp_isguarded(fp
, GUARD_FILEPORT
))
1653 fproc
->fi_guardflags
|= PROC_FI_GUARD_FILEPORT
;
1660 fill_vnodeinfo(vnode_t vp
, struct vnode_info
*vinfo
)
1662 vfs_context_t context
;
1666 context
= vfs_context_create((vfs_context_t
)0);
1667 error
= vn_stat(vp
, &sb
, NULL
, 1, context
);
1668 (void)vfs_context_rele(context
);
1670 munge_vinfo_stat(&sb
, &vinfo
->vi_stat
);
1675 if (vp
->v_mount
!= dead_mountp
) {
1676 vinfo
->vi_fsid
= vp
->v_mount
->mnt_vfsstat
.f_fsid
;
1678 vinfo
->vi_fsid
.val
[0] = 0;
1679 vinfo
->vi_fsid
.val
[1] = 0;
1681 vinfo
->vi_type
= vp
->v_type
;
1687 pid_socketinfo(socket_t so
, struct fileproc
*fp
, int closeonexec
, user_addr_t buffer
, __unused
uint32_t buffersize
, int32_t * retval
)
1690 struct socket_fdinfo s
;
1693 bzero(&s
, sizeof(struct socket_fdinfo
));
1694 fill_fileinfo(fp
, closeonexec
, &s
.pfi
);
1695 if ((error
= fill_socketinfo(so
, &s
.psi
)) == 0) {
1696 if ((error
= copyout(&s
, buffer
, sizeof(struct socket_fdinfo
))) == 0)
1697 *retval
= sizeof(struct socket_fdinfo
);
1701 #pragma unused(so, fp, closeonexec, buffer)
1708 pid_pseminfo(struct psemnode
*psem
, struct fileproc
*fp
, int closeonexec
, user_addr_t buffer
, __unused
uint32_t buffersize
, int32_t * retval
)
1710 struct psem_fdinfo pseminfo
;
1713 bzero(&pseminfo
, sizeof(struct psem_fdinfo
));
1714 fill_fileinfo(fp
, closeonexec
, &pseminfo
.pfi
);
1716 if ((error
= fill_pseminfo(psem
, &pseminfo
.pseminfo
)) == 0) {
1717 if ((error
= copyout(&pseminfo
, buffer
, sizeof(struct psem_fdinfo
))) == 0)
1718 *retval
= sizeof(struct psem_fdinfo
);
1725 pid_pshminfo(struct pshmnode
*pshm
, struct fileproc
*fp
, int closeonexec
, user_addr_t buffer
, __unused
uint32_t buffersize
, int32_t * retval
)
1727 struct pshm_fdinfo pshminfo
;
1730 bzero(&pshminfo
, sizeof(struct pshm_fdinfo
));
1731 fill_fileinfo(fp
, closeonexec
, &pshminfo
.pfi
);
1733 if ((error
= fill_pshminfo(pshm
, &pshminfo
.pshminfo
)) == 0) {
1734 if ((error
= copyout(&pshminfo
, buffer
, sizeof(struct pshm_fdinfo
))) == 0)
1735 *retval
= sizeof(struct pshm_fdinfo
);
1742 pid_pipeinfo(struct pipe
* p
, struct fileproc
*fp
, int closeonexec
, user_addr_t buffer
, __unused
uint32_t buffersize
, int32_t * retval
)
1744 struct pipe_fdinfo pipeinfo
;
1747 bzero(&pipeinfo
, sizeof(struct pipe_fdinfo
));
1748 fill_fileinfo(fp
, closeonexec
, &pipeinfo
.pfi
);
1749 if ((error
= fill_pipeinfo(p
, &pipeinfo
.pipeinfo
)) == 0) {
1750 if ((error
= copyout(&pipeinfo
, buffer
, sizeof(struct pipe_fdinfo
))) == 0)
1751 *retval
= sizeof(struct pipe_fdinfo
);
1758 pid_kqueueinfo(struct kqueue
* kq
, struct fileproc
*fp
, int closeonexec
, user_addr_t buffer
, __unused
uint32_t buffersize
, int32_t * retval
)
1760 struct kqueue_fdinfo kqinfo
;
1763 bzero(&kqinfo
, sizeof(struct kqueue_fdinfo
));
1765 fill_fileinfo(fp
, closeonexec
, &kqinfo
.pfi
);
1767 if ((error
= fill_kqueueinfo(kq
, &kqinfo
.kqueueinfo
)) == 0) {
1768 if ((error
= copyout(&kqinfo
, buffer
, sizeof(struct kqueue_fdinfo
))) == 0)
1769 *retval
= sizeof(struct kqueue_fdinfo
);
1776 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
)
1783 /************************** proc_pidfdinfo routine ***************************/
1785 proc_pidfdinfo(int pid
, int flavor
, int fd
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
)
1788 int error
= ENOTSUP
;
1789 struct fileproc
* fp
;
1791 int closeonexec
= 0;
1794 case PROC_PIDFDVNODEINFO
:
1795 size
= PROC_PIDFDVNODEINFO_SIZE
;
1797 case PROC_PIDFDVNODEPATHINFO
:
1798 size
= PROC_PIDFDVNODEPATHINFO_SIZE
;
1800 case PROC_PIDFDSOCKETINFO
:
1801 size
= PROC_PIDFDSOCKETINFO_SIZE
;
1803 case PROC_PIDFDPSEMINFO
:
1804 size
= PROC_PIDFDPSEMINFO_SIZE
;
1806 case PROC_PIDFDPSHMINFO
:
1807 size
= PROC_PIDFDPSHMINFO_SIZE
;
1809 case PROC_PIDFDPIPEINFO
:
1810 size
= PROC_PIDFDPIPEINFO_SIZE
;
1812 case PROC_PIDFDKQUEUEINFO
:
1813 size
= PROC_PIDFDKQUEUEINFO_SIZE
;
1815 case PROC_PIDFDATALKINFO
:
1816 size
= PROC_PIDFDATALKINFO_SIZE
;
1824 if (buffersize
< size
)
1827 if ((p
= proc_find(pid
)) == PROC_NULL
) {
1832 /* Do we have permission to look into this? */
1833 if ((error
= proc_security_policy(p
, PROC_INFO_CALL_PIDFDINFO
, flavor
, CHECK_SAME_USER
)))
1837 case PROC_PIDFDVNODEINFO
: {
1841 if ((error
= fp_getfvpandvid(p
, fd
, &fp
, &vp
, &vid
)) !=0) {
1844 /* no need to be under the fdlock */
1845 closeonexec
= p
->p_fd
->fd_ofileflags
[fd
] & UF_EXCLOSE
;
1846 error
= pid_vnodeinfo(vp
, vid
, fp
, closeonexec
, buffer
, buffersize
, retval
);
1850 case PROC_PIDFDVNODEPATHINFO
: {
1854 if ((error
= fp_getfvpandvid(p
, fd
, &fp
, &vp
, &vid
)) !=0) {
1858 /* no need to be under the fdlock */
1859 closeonexec
= p
->p_fd
->fd_ofileflags
[fd
] & UF_EXCLOSE
;
1860 error
= pid_vnodeinfopath(vp
, vid
, fp
, closeonexec
, buffer
, buffersize
, retval
);
1864 case PROC_PIDFDSOCKETINFO
: {
1867 if ((error
= fp_getfsock(p
, fd
, &fp
, &so
)) !=0) {
1870 /* no need to be under the fdlock */
1871 closeonexec
= p
->p_fd
->fd_ofileflags
[fd
] & UF_EXCLOSE
;
1872 error
= pid_socketinfo(so
, fp
, closeonexec
, buffer
, buffersize
, retval
);
1876 case PROC_PIDFDPSEMINFO
: {
1877 struct psemnode
* psem
;
1879 if ((error
= fp_getfpsem(p
, fd
, &fp
, &psem
)) !=0) {
1882 /* no need to be under the fdlock */
1883 closeonexec
= p
->p_fd
->fd_ofileflags
[fd
] & UF_EXCLOSE
;
1884 error
= pid_pseminfo(psem
, fp
, closeonexec
, buffer
, buffersize
, retval
);
1888 case PROC_PIDFDPSHMINFO
: {
1889 struct pshmnode
* pshm
;
1891 if ((error
= fp_getfpshm(p
, fd
, &fp
, &pshm
)) !=0) {
1894 /* no need to be under the fdlock */
1895 closeonexec
= p
->p_fd
->fd_ofileflags
[fd
] & UF_EXCLOSE
;
1896 error
= pid_pshminfo(pshm
, fp
, closeonexec
, buffer
, buffersize
, retval
);
1900 case PROC_PIDFDPIPEINFO
: {
1901 struct pipe
* cpipe
;
1903 if ((error
= fp_getfpipe(p
, fd
, &fp
, &cpipe
)) !=0) {
1906 /* no need to be under the fdlock */
1907 closeonexec
= p
->p_fd
->fd_ofileflags
[fd
] & UF_EXCLOSE
;
1908 error
= pid_pipeinfo(cpipe
, fp
, closeonexec
, buffer
, buffersize
, retval
);
1912 case PROC_PIDFDKQUEUEINFO
: {
1915 if ((error
= fp_getfkq(p
, fd
, &fp
, &kq
)) !=0) {
1918 /* no need to be under the fdlock */
1919 closeonexec
= p
->p_fd
->fd_ofileflags
[fd
] & UF_EXCLOSE
;
1920 error
= pid_kqueueinfo(kq
, fp
, closeonexec
, buffer
, buffersize
, retval
);
1930 fp_drop(p
, fd
, fp
, 0);
1938 * Helper function for proc_pidfileportinfo
1941 struct fileport_info_args
{
1943 user_addr_t fia_buffer
;
1944 uint32_t fia_buffersize
;
1945 int32_t *fia_retval
;
1948 static kern_return_t
1949 proc_fileport_info(__unused mach_port_name_t name
,
1950 struct fileglob
*fg
, void *arg
)
1952 struct fileport_info_args
*fia
= arg
;
1953 struct fileproc __fileproc
, *fp
= &__fileproc
;
1956 bzero(fp
, sizeof (*fp
));
1959 switch (fia
->fia_flavor
) {
1960 case PROC_PIDFILEPORTVNODEPATHINFO
: {
1963 if (FILEGLOB_DTYPE(fg
) != DTYPE_VNODE
) {
1967 vp
= (struct vnode
*)fg
->fg_data
;
1968 error
= pid_vnodeinfopath(vp
, vnode_vid(vp
), fp
, 0,
1969 fia
->fia_buffer
, fia
->fia_buffersize
, fia
->fia_retval
);
1972 case PROC_PIDFILEPORTSOCKETINFO
: {
1975 if (FILEGLOB_DTYPE(fg
) != DTYPE_SOCKET
) {
1979 so
= (socket_t
)fg
->fg_data
;
1980 error
= pid_socketinfo(so
, fp
, 0,
1981 fia
->fia_buffer
, fia
->fia_buffersize
, fia
->fia_retval
);
1984 case PROC_PIDFILEPORTPSHMINFO
: {
1985 struct pshmnode
*pshm
;
1987 if (FILEGLOB_DTYPE(fg
) != DTYPE_PSXSHM
) {
1988 error
= EBADF
; /* ick - mirror fp_getfpshm */
1991 pshm
= (struct pshmnode
*)fg
->fg_data
;
1992 error
= pid_pshminfo(pshm
, fp
, 0,
1993 fia
->fia_buffer
, fia
->fia_buffersize
, fia
->fia_retval
);
1996 case PROC_PIDFILEPORTPIPEINFO
: {
1999 if (FILEGLOB_DTYPE(fg
) != DTYPE_PIPE
) {
2000 error
= EBADF
; /* ick - mirror fp_getfpipe */
2003 cpipe
= (struct pipe
*)fg
->fg_data
;
2004 error
= pid_pipeinfo(cpipe
, fp
, 0,
2005 fia
->fia_buffer
, fia
->fia_buffersize
, fia
->fia_retval
);
2016 /************************* proc_pidfileportinfo routine *********************/
2018 proc_pidfileportinfo(int pid
, int flavor
, mach_port_name_t name
,
2019 user_addr_t buffer
, uint32_t buffersize
, int32_t *retval
)
2022 int error
= ENOTSUP
;
2024 struct fileport_info_args fia
;
2026 /* fileport types are restricted by filetype_issendable() */
2029 case PROC_PIDFILEPORTVNODEPATHINFO
:
2030 size
= PROC_PIDFILEPORTVNODEPATHINFO_SIZE
;
2032 case PROC_PIDFILEPORTSOCKETINFO
:
2033 size
= PROC_PIDFILEPORTSOCKETINFO_SIZE
;
2035 case PROC_PIDFILEPORTPSHMINFO
:
2036 size
= PROC_PIDFILEPORTPSHMINFO_SIZE
;
2038 case PROC_PIDFILEPORTPIPEINFO
:
2039 size
= PROC_PIDFILEPORTPIPEINFO_SIZE
;
2045 if (buffersize
< size
)
2047 if ((p
= proc_find(pid
)) == PROC_NULL
) {
2052 /* Do we have permission to look into this? */
2053 if ((error
= proc_security_policy(p
, PROC_INFO_CALL_PIDFILEPORTINFO
, flavor
, CHECK_SAME_USER
)))
2056 fia
.fia_flavor
= flavor
;
2057 fia
.fia_buffer
= buffer
;
2058 fia
.fia_buffersize
= buffersize
;
2059 fia
.fia_retval
= retval
;
2061 if (fileport_invoke(p
->task
, name
,
2062 proc_fileport_info
, &fia
, &error
) != KERN_SUCCESS
)
2071 proc_security_policy(proc_t targetp
, __unused
int callnum
, __unused
int flavor
, boolean_t check_same_user
)
2076 if ((error
= mac_proc_check_proc_info(current_proc(), targetp
, callnum
, flavor
)))
2080 /* The 'listpids' call doesn't have a target proc */
2081 if (targetp
== PROC_NULL
) {
2082 assert(callnum
== PROC_INFO_CALL_LISTPIDS
&& check_same_user
== NO_CHECK_SAME_USER
);
2087 * Check for 'get information for processes owned by other users' privilege
2088 * root has this privilege by default
2090 if (priv_check_cred(kauth_cred_get(), PRIV_GLOBAL_PROC_INFO
, 0) == 0)
2091 check_same_user
= FALSE
;
2093 if (check_same_user
) {
2094 kauth_cred_t target_cred
;
2097 target_cred
= kauth_cred_proc_ref(targetp
);
2098 target_uid
= kauth_cred_getuid(target_cred
);
2099 kauth_cred_unref(&target_cred
);
2101 if (kauth_getuid() != target_uid
)
2109 proc_kernmsgbuf(user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
)
2111 if (suser(kauth_cred_get(), (u_short
*)0) == 0) {
2112 return(log_dmesg(buffer
, buffersize
, retval
));
2117 /* ********* process control sets on self only */
2119 proc_setcontrol(int pid
, int flavor
, uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, __unused
int32_t * retval
)
2121 struct proc
* pself
= PROC_NULL
;
2123 uint32_t pcontrol
= (uint32_t)arg
;
2124 struct uthread
*ut
= NULL
;
2127 pself
= current_proc();
2128 if (pid
!= pself
->p_pid
)
2131 /* Do we have permission to look into this? */
2132 if ((error
= proc_security_policy(pself
, PROC_INFO_CALL_SETCONTROL
, flavor
, NO_CHECK_SAME_USER
)))
2136 case PROC_SELFSET_PCONTROL
: {
2137 if (pcontrol
> P_PCMAX
)
2140 /* reset existing control setting while retaining action state */
2141 pself
->p_pcaction
&= PROC_ACTION_MASK
;
2142 /* set new control state */
2143 pself
->p_pcaction
|= pcontrol
;
2148 case PROC_SELFSET_THREADNAME
: {
2149 /* PROC_SELFSET_THREADNAME_SIZE = (MAXTHREADNAMESIZE -1) */
2150 if(buffersize
> PROC_SELFSET_THREADNAME_SIZE
)
2151 return ENAMETOOLONG
;
2152 ut
= current_uthread();
2156 ut
->pth_name
= (char*)kalloc(MAXTHREADNAMESIZE
);
2160 bzero(ut
->pth_name
, MAXTHREADNAMESIZE
);
2161 error
= copyin(buffer
, ut
->pth_name
, buffersize
);
2165 case PROC_SELFSET_VMRSRCOWNER
: {
2166 /* need to to be superuser */
2167 if (suser(kauth_cred_get(), (u_short
*)0) != 0) {
2173 /* reset existing control setting while retaining action state */
2174 pself
->p_lflag
|= P_LVMRSRCOWNER
;
2179 case PROC_SELFSET_DELAYIDLESLEEP
: {
2180 /* mark or clear the process property to delay idle sleep disk IO */
2182 OSBitOrAtomic(P_DELAYIDLESLEEP
, &pself
->p_flag
);
2184 OSBitAndAtomic(~((uint32_t)P_DELAYIDLESLEEP
), &pself
->p_flag
);
2196 #if CONFIG_MEMORYSTATUS
2199 proc_dirtycontrol(int pid
, int flavor
, uint64_t arg
, int32_t *retval
) {
2200 struct proc
*target_p
;
2202 uint32_t pcontrol
= (uint32_t)arg
;
2203 kauth_cred_t my_cred
, target_cred
;
2204 boolean_t self
= FALSE
;
2205 boolean_t child
= FALSE
;
2206 boolean_t zombref
= FALSE
;
2209 target_p
= proc_find(pid
);
2211 if (target_p
== PROC_NULL
) {
2212 if (flavor
== PROC_DIRTYCONTROL_GET
) {
2213 target_p
= proc_find_zombref(pid
);
2217 if (target_p
== PROC_NULL
)
2222 my_cred
= kauth_cred_get();
2223 target_cred
= kauth_cred_proc_ref(target_p
);
2225 /* Do we have permission to look into this? */
2226 if ((error
= proc_security_policy(target_p
, PROC_INFO_CALL_DIRTYCONTROL
, flavor
, NO_CHECK_SAME_USER
)))
2229 selfpid
= proc_selfpid();
2230 if (pid
== selfpid
) {
2232 } else if (target_p
->p_ppid
== selfpid
) {
2237 case PROC_DIRTYCONTROL_TRACK
: {
2238 /* Only allow the process itself, its parent, or root */
2239 if ((self
== FALSE
) && (child
== FALSE
) && kauth_cred_issuser(kauth_cred_get()) != TRUE
) {
2244 error
= memorystatus_dirty_track(target_p
, pcontrol
);
2248 case PROC_DIRTYCONTROL_SET
: {
2249 /* Check privileges; use cansignal() here since the process could be terminated */
2250 if (!cansignal(current_proc(), my_cred
, target_p
, SIGKILL
, 0)) {
2255 error
= memorystatus_dirty_set(target_p
, self
, pcontrol
);
2259 case PROC_DIRTYCONTROL_GET
: {
2260 /* No permissions check - dirty state is freely available */
2262 *retval
= memorystatus_dirty_get(target_p
);
2269 case PROC_DIRTYCONTROL_CLEAR
: {
2270 /* Check privileges; use cansignal() here since the process could be terminated */
2271 if (!cansignal(current_proc(), my_cred
, target_p
, SIGKILL
, 0)) {
2276 error
= memorystatus_dirty_clear(target_p
, pcontrol
);
2283 proc_drop_zombref(target_p
);
2285 proc_rele(target_p
);
2287 kauth_cred_unref(&target_cred
);
2294 proc_dirtycontrol(__unused
int pid
, __unused
int flavor
, __unused
uint64_t arg
, __unused
int32_t *retval
) {
2298 #endif /* CONFIG_MEMORYSTATUS */
2301 * proc_terminate() provides support for sudden termination.
2302 * SIGKILL is issued to tracked, clean processes; otherwise,
2307 proc_terminate(int pid
, int32_t *retval
)
2311 kauth_cred_t uc
= kauth_cred_get();
2315 /* XXX: Check if these are necessary */
2316 AUDIT_ARG(pid
, pid
);
2317 AUDIT_ARG(signum
, sig
);
2320 if (pid
<= 0 || retval
== NULL
) {
2324 if ((p
= proc_find(pid
)) == NULL
) {
2329 /* XXX: Check if these are necessary */
2330 AUDIT_ARG(process
, p
);
2333 /* Check privileges; if SIGKILL can be issued, then SIGTERM is also OK */
2334 if (!cansignal(current_proc(), uc
, p
, SIGKILL
, 0)) {
2339 /* Not allowed to sudden terminate yourself */
2340 if (p
== current_proc()) {
2345 #if CONFIG_MEMORYSTATUS
2346 /* Determine requisite signal to issue */
2347 sig
= memorystatus_on_terminate(p
);
2352 proc_set_task_policy(p
->task
, THREAD_NULL
, TASK_POLICY_ATTRIBUTE
,
2353 TASK_POLICY_TERMINATED
, TASK_POLICY_ENABLE
);
2365 * copy stat64 structure into vinfo_stat structure.
2368 munge_vinfo_stat(struct stat64
*sbp
, struct vinfo_stat
*vsbp
)
2370 bzero(vsbp
, sizeof(struct vinfo_stat
));
2372 vsbp
->vst_dev
= sbp
->st_dev
;
2373 vsbp
->vst_mode
= sbp
->st_mode
;
2374 vsbp
->vst_nlink
= sbp
->st_nlink
;
2375 vsbp
->vst_ino
= sbp
->st_ino
;
2376 vsbp
->vst_uid
= sbp
->st_uid
;
2377 vsbp
->vst_gid
= sbp
->st_gid
;
2378 vsbp
->vst_atime
= sbp
->st_atimespec
.tv_sec
;
2379 vsbp
->vst_atimensec
= sbp
->st_atimespec
.tv_nsec
;
2380 vsbp
->vst_mtime
= sbp
->st_mtimespec
.tv_sec
;
2381 vsbp
->vst_mtimensec
= sbp
->st_mtimespec
.tv_nsec
;
2382 vsbp
->vst_ctime
= sbp
->st_ctimespec
.tv_sec
;
2383 vsbp
->vst_ctimensec
= sbp
->st_ctimespec
.tv_nsec
;
2384 vsbp
->vst_birthtime
= sbp
->st_birthtimespec
.tv_sec
;
2385 vsbp
->vst_birthtimensec
= sbp
->st_birthtimespec
.tv_nsec
;
2386 vsbp
->vst_size
= sbp
->st_size
;
2387 vsbp
->vst_blocks
= sbp
->st_blocks
;
2388 vsbp
->vst_blksize
= sbp
->st_blksize
;
2389 vsbp
->vst_flags
= sbp
->st_flags
;
2390 vsbp
->vst_gen
= sbp
->st_gen
;
2391 vsbp
->vst_rdev
= sbp
->st_rdev
;
2392 vsbp
->vst_qspare
[0] = sbp
->st_qspare
[0];
2393 vsbp
->vst_qspare
[1] = sbp
->st_qspare
[1];
2397 proc_pid_rusage(int pid
, int flavor
, user_addr_t buffer
, __unused
int32_t *retval
)
2403 if ((p
= proc_find(pid
)) == PROC_NULL
) {
2404 if ((p
= proc_find_zombref(pid
)) == PROC_NULL
) {
2410 /* Do we have permission to look into this? */
2411 if ((error
= proc_security_policy(p
, PROC_INFO_CALL_PIDRUSAGE
, flavor
, CHECK_SAME_USER
)))
2414 error
= proc_get_rusage(p
, flavor
, buffer
, zombie
);
2418 proc_drop_zombref(p
);
2426 proc_archinfo(proc_t p
, struct proc_archinfo
*pai
)
2429 pai
->p_cputype
= p
->p_cputype
;
2430 pai
->p_cpusubtype
= p
->p_cpusubtype
;
2435 proc_pidcoalitioninfo(proc_t p
, struct proc_pidcoalitioninfo
*ppci
)
2437 bzero(ppci
, sizeof(*ppci
));
2438 ppci
->coalition_id
= proc_coalitionid(p
);
2444 * Wrapper to provide NOTE_EXIT_DETAIL and NOTE_EXITSTATUS
2445 * It mimics the data that is typically captured by the
2446 * EVFILT_PROC, NOTE_EXIT event mechanism.
2447 * See filt_proc() in kern_event.c.
2450 proc_pidnoteexit(proc_t p
, uint64_t flags
, uint32_t *data
)
2452 uint32_t exit_data
= 0;
2453 uint32_t exit_flags
= (uint32_t)flags
;
2458 * Allow access to the parent of the exiting
2459 * child or the parent debugger only.
2462 pid_t selfpid
= proc_selfpid();
2464 if (p
->p_ppid
== selfpid
)
2465 break; /* parent => ok */
2467 if ((p
->p_lflag
& P_LTRACED
) != 0 &&
2468 (p
->p_oppid
== selfpid
))
2469 break; /* parent-in-waiting => ok */
2475 if ((exit_flags
& NOTE_EXITSTATUS
) != 0) {
2476 /* The signal and exit status */
2477 exit_data
|= (p
->p_xstat
& NOTE_PDATAMASK
);
2480 if ((exit_flags
& NOTE_EXIT_DETAIL
) != 0) {
2481 /* The exit detail */
2482 if ((p
->p_lflag
& P_LTERM_DECRYPTFAIL
) != 0) {
2483 exit_data
|= NOTE_EXIT_DECRYPTFAIL
;
2486 if ((p
->p_lflag
& P_LTERM_JETSAM
) != 0) {
2487 exit_data
|= NOTE_EXIT_MEMORY
;
2489 switch (p
->p_lflag
& P_JETSAM_MASK
) {
2490 case P_JETSAM_VMPAGESHORTAGE
:
2491 exit_data
|= NOTE_EXIT_MEMORY_VMPAGESHORTAGE
;
2493 case P_JETSAM_VMTHRASHING
:
2494 exit_data
|= NOTE_EXIT_MEMORY_VMTHRASHING
;
2496 case P_JETSAM_FCTHRASHING
:
2497 exit_data
|= NOTE_EXIT_MEMORY_FCTHRASHING
;
2499 case P_JETSAM_VNODE
:
2500 exit_data
|= NOTE_EXIT_MEMORY_VNODE
;
2502 case P_JETSAM_HIWAT
:
2503 exit_data
|= NOTE_EXIT_MEMORY_HIWAT
;
2506 exit_data
|= NOTE_EXIT_MEMORY_PID
;
2508 case P_JETSAM_IDLEEXIT
:
2509 exit_data
|= NOTE_EXIT_MEMORY_IDLE
;
2514 if ((p
->p_csflags
& CS_KILLED
) != 0) {
2515 exit_data
|= NOTE_EXIT_CSERROR
;