2 * Copyright (c) 2005-2016 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/reason.h>
49 #include <sys/sysctl.h>
51 #include <sys/aio_kern.h>
52 #include <sys/kern_memorystatus.h>
54 #include <security/audit/audit.h>
56 #include <mach/machine.h>
57 #include <mach/mach_types.h>
58 #include <mach/vm_param.h>
59 #include <kern/task.h>
60 #include <kern/kalloc.h>
61 #include <kern/assert.h>
62 #include <kern/policy_internal.h>
64 #include <vm/vm_kern.h>
65 #include <vm/vm_map.h>
66 #include <mach/host_info.h>
67 #include <mach/task_info.h>
68 #include <mach/thread_info.h>
69 #include <mach/vm_region.h>
71 #include <sys/mount_internal.h>
72 #include <sys/proc_info.h>
73 #include <sys/bsdtask_info.h>
74 #include <sys/kdebug.h>
75 #include <sys/sysproto.h>
76 #include <sys/msgbuf.h>
79 #include <sys/guarded.h>
81 #include <machine/machine_routines.h>
83 #include <kern/ipc_misc.h>
85 #include <vm/vm_protos.h>
87 /* Needed by proc_pidnoteexit() */
88 #include <sys/event.h>
89 #include <sys/codesign.h>
91 /* Needed by proc_listcoalitions() */
92 #ifdef CONFIG_COALITIONS
93 #include <sys/coalition.h>
102 uint64_t get_dispatchqueue_offset_from_proc(void *);
103 uint64_t get_dispatchqueue_serialno_offset_from_proc(void *);
104 int proc_info_internal(int callnum
, int pid
, int flavor
, uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
);
107 * TODO: Replace the noinline attribute below. Currently, it serves
108 * to avoid stack bloat caused by inlining multiple functions that
109 * have large stack footprints; when the functions are independent
110 * of each other (will not both be called in any given call to the
111 * caller), this only serves to bloat the stack, as we allocate
112 * space for both functions, despite the fact that we only need a
113 * fraction of that space.
115 * Long term, these functions should not be allocating everything on
116 * the stack, and should move large allocations (the huge structs
117 * that proc info deals in) to the heap, or eliminate them if
120 * The functions that most desperately need to improve stack usage
121 * (starting with the worst offenders):
122 * proc_pidvnodepathinfo
124 * proc_pidregionpathinfo
130 * proc_pidoriginatorinfo
133 /* protos for proc_info calls */
134 int __attribute__ ((noinline
)) proc_listpids(uint32_t type
, uint32_t tyoneinfo
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
);
135 int __attribute__ ((noinline
)) proc_pidinfo(int pid
, int flavor
, uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
);
136 int __attribute__ ((noinline
)) proc_pidfdinfo(int pid
, int flavor
,int fd
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
);
137 int __attribute__ ((noinline
)) proc_kernmsgbuf(user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
);
138 int __attribute__ ((noinline
)) proc_setcontrol(int pid
, int flavor
, uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
);
139 int __attribute__ ((noinline
)) proc_pidfileportinfo(int pid
, int flavor
, mach_port_name_t name
, user_addr_t buffer
, uint32_t buffersize
, int32_t *retval
);
140 int __attribute__ ((noinline
)) proc_dirtycontrol(int pid
, int flavor
, uint64_t arg
, int32_t * retval
);
141 int __attribute__ ((noinline
)) proc_terminate(int pid
, int32_t * retval
);
142 int __attribute__ ((noinline
)) proc_pid_rusage(int pid
, int flavor
, user_addr_t buffer
, int32_t * retval
);
143 int __attribute__ ((noinline
)) proc_pidoriginatorinfo(int pid
, int flavor
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
);
144 int __attribute__ ((noinline
)) proc_listcoalitions(int flavor
, int coaltype
, user_addr_t buffer
, uint32_t buffersize
, int32_t *retval
);
145 int __attribute__ ((noinline
)) proc_can_use_foreground_hw(int pid
, user_addr_t reason
, uint32_t resonsize
, int32_t *retval
);
147 /* protos for procpidinfo calls */
148 int __attribute__ ((noinline
)) proc_pidfdlist(proc_t p
, user_addr_t buffer
, uint32_t buffersize
, int32_t *retval
);
149 int __attribute__ ((noinline
)) proc_pidbsdinfo(proc_t p
, struct proc_bsdinfo
*pbsd
, int zombie
);
150 int __attribute__ ((noinline
)) proc_pidshortbsdinfo(proc_t p
, struct proc_bsdshortinfo
*pbsd_shortp
, int zombie
);
151 int __attribute__ ((noinline
)) proc_pidtaskinfo(proc_t p
, struct proc_taskinfo
*ptinfo
);
152 int __attribute__ ((noinline
)) proc_pidthreadinfo(proc_t p
, uint64_t arg
, int thuniqueid
, struct proc_threadinfo
*pthinfo
);
153 int __attribute__ ((noinline
)) proc_pidthreadpathinfo(proc_t p
, uint64_t arg
, struct proc_threadwithpathinfo
*pinfo
);
154 int __attribute__ ((noinline
)) proc_pidlistthreads(proc_t p
, user_addr_t buffer
, uint32_t buffersize
, int32_t *retval
);
155 int __attribute__ ((noinline
)) proc_pidregioninfo(proc_t p
, uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, int32_t *retval
);
156 int __attribute__ ((noinline
)) proc_pidregionpathinfo(proc_t p
, uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, int32_t *retval
);
157 int __attribute__ ((noinline
)) proc_pidregionpathinfo2(proc_t p
, uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, int32_t *retval
);
158 int __attribute__ ((noinline
)) proc_pidregionpathinfo3(proc_t p
, uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, int32_t *retval
);
159 int __attribute__ ((noinline
)) proc_pidvnodepathinfo(proc_t p
, uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, int32_t *retval
);
160 int __attribute__ ((noinline
)) proc_pidpathinfo(proc_t p
, uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, int32_t *retval
);
161 int __attribute__ ((noinline
)) proc_pidworkqueueinfo(proc_t p
, struct proc_workqueueinfo
*pwqinfo
);
162 int __attribute__ ((noinline
)) proc_pidfileportlist(proc_t p
, user_addr_t buffer
, uint32_t buffersize
, int32_t *retval
);
163 void __attribute__ ((noinline
)) proc_piduniqidentifierinfo(proc_t p
, struct proc_uniqidentifierinfo
*p_uniqidinfo
);
164 void __attribute__ ((noinline
)) proc_archinfo(proc_t p
, struct proc_archinfo
*pai
);
165 void __attribute__ ((noinline
)) proc_pidcoalitioninfo(proc_t p
, struct proc_pidcoalitioninfo
*pci
);
166 int __attribute__ ((noinline
)) proc_pidnoteexit(proc_t p
, uint64_t arg
, uint32_t *data
);
167 int __attribute__ ((noinline
)) proc_pidexitreasoninfo(proc_t p
, struct proc_exitreasoninfo
*peri
, struct proc_exitreasonbasicinfo
*pberi
);
168 int __attribute__ ((noinline
)) proc_pidoriginatorpid_uuid(uuid_t uuid
, uint32_t buffersize
, pid_t
*pid
);
171 /* protos for proc_pidfdinfo calls */
172 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
);
173 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
);
174 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
);
175 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
);
176 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
);
177 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
);
178 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
);
179 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
);
182 /* protos for misc */
184 int fill_vnodeinfo(vnode_t vp
, struct vnode_info
*vinfo
);
185 void fill_fileinfo(struct fileproc
* fp
, proc_t proc
, int fd
, struct proc_fileinfo
* finfo
);
186 int proc_security_policy(proc_t targetp
, int callnum
, int flavor
, boolean_t check_same_user
);
187 static void munge_vinfo_stat(struct stat64
*sbp
, struct vinfo_stat
*vsbp
);
188 static int proc_piduuidinfo(pid_t pid
, uuid_t uuid_buf
, uint32_t buffersize
);
189 int proc_pidpathinfo_internal(proc_t p
, __unused
uint64_t arg
, char *buf
, uint32_t buffersize
, __unused
int32_t *retval
);
190 int proc_listfd_kqueue(proc_t p
, int32_t *fdlist
, int len
);
191 int proc_kqueue_udata_info(proc_t p
, int32_t fd
, uint64_t *buffer
, int bufsize
);
192 int proc_list_uptrs(proc_t p
, uint64_t *udata_buffer
, int size
);
194 extern int cansignal(struct proc
*, kauth_cred_t
, struct proc
*, int, int);
195 extern int proc_get_rusage(proc_t proc
, int flavor
, user_addr_t buffer
, int is_zombie
);
197 #define CHECK_SAME_USER TRUE
198 #define NO_CHECK_SAME_USER FALSE
200 uint64_t get_dispatchqueue_offset_from_proc(void *p
)
203 proc_t pself
= (proc_t
)p
;
204 return (pself
->p_dispatchqueue_offset
);
210 uint64_t get_dispatchqueue_serialno_offset_from_proc(void *p
)
213 proc_t pself
= (proc_t
)p
;
214 return (pself
->p_dispatchqueue_serialno_offset
);
220 /***************************** proc_info ********************/
223 proc_info(__unused
struct proc
*p
, struct proc_info_args
* uap
, int32_t *retval
)
225 return(proc_info_internal(uap
->callnum
, uap
->pid
, uap
->flavor
, uap
->arg
, uap
->buffer
, uap
->buffersize
, retval
));
230 proc_info_internal(int callnum
, int pid
, int flavor
, uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
)
234 case PROC_INFO_CALL_LISTPIDS
:
235 /* pid contains type and flavor contains typeinfo */
236 return(proc_listpids(pid
, flavor
, buffer
, buffersize
, retval
));
237 case PROC_INFO_CALL_PIDINFO
:
238 return(proc_pidinfo(pid
, flavor
, arg
, buffer
, buffersize
, retval
));
239 case PROC_INFO_CALL_PIDFDINFO
:
240 return(proc_pidfdinfo(pid
, flavor
, (int)arg
, buffer
, buffersize
, retval
));
241 case PROC_INFO_CALL_KERNMSGBUF
:
242 return(proc_kernmsgbuf(buffer
, buffersize
, retval
));
243 case PROC_INFO_CALL_SETCONTROL
:
244 return(proc_setcontrol(pid
, flavor
, arg
, buffer
, buffersize
, retval
));
245 case PROC_INFO_CALL_PIDFILEPORTINFO
:
246 return(proc_pidfileportinfo(pid
, flavor
, (mach_port_name_t
)arg
, buffer
, buffersize
, retval
));
247 case PROC_INFO_CALL_TERMINATE
:
248 return(proc_terminate(pid
, retval
));
249 case PROC_INFO_CALL_DIRTYCONTROL
:
250 return(proc_dirtycontrol(pid
, flavor
, arg
, retval
));
251 case PROC_INFO_CALL_PIDRUSAGE
:
252 return (proc_pid_rusage(pid
, flavor
, buffer
, retval
));
253 case PROC_INFO_CALL_PIDORIGINATORINFO
:
254 return (proc_pidoriginatorinfo(pid
, flavor
, buffer
, buffersize
, retval
));
255 case PROC_INFO_CALL_LISTCOALITIONS
:
256 return proc_listcoalitions(pid
/* flavor */, flavor
/* coaltype */, buffer
,
258 case PROC_INFO_CALL_CANUSEFGHW
:
259 return proc_can_use_foreground_hw(pid
, buffer
, buffersize
, retval
);
267 /******************* proc_listpids routine ****************/
269 proc_listpids(uint32_t type
, uint32_t typeinfo
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
)
271 int numprocs
, wantpids
;
278 struct proclist
*current_list
;
280 /* Do we have permission to look into this? */
281 if ((error
= proc_security_policy(PROC_NULL
, PROC_INFO_CALL_LISTPIDS
, type
, NO_CHECK_SAME_USER
)))
284 /* if the buffer is null, return num of procs */
285 if (buffer
== (user_addr_t
)0) {
286 *retval
= ((nprocs
+20) * sizeof(int));
290 if (buffersize
< sizeof(int)) {
293 wantpids
= buffersize
/sizeof(int);
294 numprocs
= nprocs
+20;
295 if (numprocs
> wantpids
)
298 kbuf
= (char *)kalloc((vm_size_t
)(numprocs
* sizeof(int)));
301 bzero(kbuf
, sizeof(int));
308 current_list
= &allproc
;
310 LIST_FOREACH(p
, current_list
, p_list
) {
314 if (p
->p_pgrpid
!= (pid_t
)typeinfo
)
318 if ((p
->p_ppid
!= (pid_t
)typeinfo
) && (((p
->p_lflag
& P_LTRACED
) == 0) || (p
->p_oppid
!= (pid_t
)typeinfo
)))
326 /* racy but list lock is held */
327 if ((p
->p_flag
& P_CONTROLT
) == 0 ||
328 (p
->p_pgrp
== NULL
) || (p
->p_pgrp
->pg_session
== NULL
) ||
329 (tp
= SESSION_TP(p
->p_pgrp
->pg_session
)) == TTY_NULL
||
330 tp
->t_dev
!= (dev_t
)typeinfo
)
334 if (p
->p_ucred
== NULL
)
337 kauth_cred_t my_cred
;
340 my_cred
= kauth_cred_proc_ref(p
);
341 uid
= kauth_cred_getuid(my_cred
);
342 kauth_cred_unref(&my_cred
);
343 if (uid
!= (uid_t
)typeinfo
)
348 if (p
->p_ucred
== NULL
)
351 kauth_cred_t my_cred
;
354 my_cred
= kauth_cred_proc_ref(p
);
355 uid
= kauth_cred_getruid(my_cred
);
356 kauth_cred_unref(&my_cred
);
357 if (uid
!= (uid_t
)typeinfo
)
374 if ((n
< numprocs
) && (current_list
== &allproc
)) {
375 current_list
= &zombproc
;
382 error
= copyout((caddr_t
)ptr
, buffer
, n
* sizeof(int));
384 *retval
= (n
* sizeof(int));
385 kfree((void *)kbuf
, (vm_size_t
)(numprocs
* sizeof(int)));
391 /********************************** proc_pidfdlist routines ********************************/
394 proc_pidfdlist(proc_t p
, user_addr_t buffer
, uint32_t buffersize
, int32_t *retval
)
398 struct proc_fdinfo
* pfd
;
399 struct fileproc
* fp
;
404 numfds
= p
->p_fd
->fd_nfiles
;
406 if (buffer
== (user_addr_t
) 0) {
408 *retval
= (numfds
* sizeof(struct proc_fdinfo
));
412 /* buffersize is big enough atleast for one struct */
413 needfds
= buffersize
/sizeof(struct proc_fdinfo
);
415 if (numfds
> needfds
)
418 kbuf
= (char *)kalloc((vm_size_t
)(numfds
* sizeof(struct proc_fdinfo
)));
421 bzero(kbuf
, numfds
* sizeof(struct proc_fdinfo
));
425 pfd
= (struct proc_fdinfo
*)kbuf
;
427 for (n
= 0; ((n
< numfds
) && (n
< p
->p_fd
->fd_nfiles
)); n
++) {
428 if (((fp
= p
->p_fd
->fd_ofiles
[n
]) != 0)
429 && ((p
->p_fd
->fd_ofileflags
[n
] & UF_RESERVED
) == 0)) {
430 file_type_t fdtype
= FILEGLOB_DTYPE(fp
->f_fglob
);
432 pfd
->proc_fdtype
= (fdtype
!= DTYPE_ATALK
) ?
433 fdtype
: PROX_FDTYPE_ATALK
;
440 error
= copyout(kbuf
, buffer
, count
* sizeof(struct proc_fdinfo
));
441 kfree((void *)kbuf
, (vm_size_t
)(numfds
* sizeof(struct proc_fdinfo
)));
443 *retval
= (count
* sizeof(struct proc_fdinfo
));
448 * Helper functions for proc_pidfileportlist.
451 proc_fileport_count(__unused mach_port_name_t name
,
452 __unused
struct fileglob
*fg
, void *arg
)
454 uint32_t *counter
= arg
;
460 struct fileport_fdtype_args
{
461 struct proc_fileportinfo
*ffa_pfi
;
462 struct proc_fileportinfo
*ffa_pfi_end
;
466 proc_fileport_fdtype(mach_port_name_t name
, struct fileglob
*fg
, void *arg
)
468 struct fileport_fdtype_args
*ffa
= arg
;
470 if (ffa
->ffa_pfi
!= ffa
->ffa_pfi_end
) {
471 file_type_t fdtype
= FILEGLOB_DTYPE(fg
);
473 ffa
->ffa_pfi
->proc_fdtype
= (fdtype
!= DTYPE_ATALK
) ?
474 fdtype
: PROX_FDTYPE_ATALK
;
475 ffa
->ffa_pfi
->proc_fileport
= name
;
477 return (0); /* keep walking */
479 return (-1); /* stop the walk! */
483 proc_pidfileportlist(proc_t p
,
484 user_addr_t buffer
, uint32_t buffersize
, int32_t *retval
)
488 struct proc_fileportinfo
*pfi
;
489 uint32_t needfileports
, numfileports
;
490 struct fileport_fdtype_args ffa
;
493 needfileports
= buffersize
/ sizeof (*pfi
);
494 if ((user_addr_t
)0 == buffer
|| needfileports
> (uint32_t)maxfiles
) {
496 * Either (i) the user is asking for a fileport count,
497 * or (ii) the number of fileports they're asking for is
498 * larger than the maximum number of open files (!); count
499 * them to bound subsequent heap allocations.
502 switch (fileport_walk(p
->task
,
503 proc_fileport_count
, &numfileports
)) {
506 case KERN_RESOURCE_SHORTAGE
:
508 case KERN_INVALID_TASK
:
514 if (numfileports
== 0) {
515 *retval
= 0; /* none at all, bail */
518 if ((user_addr_t
)0 == buffer
) {
519 numfileports
+= 20; /* accelerate convergence */
520 *retval
= numfileports
* sizeof (*pfi
);
523 if (needfileports
> numfileports
)
524 needfileports
= numfileports
;
527 assert(buffersize
>= PROC_PIDLISTFILEPORTS_SIZE
);
529 kbufsize
= (vm_size_t
)needfileports
* sizeof (*pfi
);
530 pfi
= kbuf
= kalloc(kbufsize
);
533 bzero(kbuf
, kbufsize
);
536 ffa
.ffa_pfi_end
= pfi
+ needfileports
;
538 switch (fileport_walk(p
->task
, proc_fileport_fdtype
, &ffa
)) {
542 if ((numfileports
= pfi
- (typeof(pfi
))kbuf
) == 0)
544 if (numfileports
> needfileports
)
545 panic("more fileports returned than requested");
546 error
= copyout(kbuf
, buffer
, numfileports
* sizeof (*pfi
));
548 case KERN_RESOURCE_SHORTAGE
:
551 case KERN_INVALID_TASK
:
558 kfree(kbuf
, kbufsize
);
560 *retval
= numfileports
* sizeof (*pfi
);
565 proc_pidbsdinfo(proc_t p
, struct proc_bsdinfo
* pbsd
, int zombie
)
568 struct session
*sessionp
= NULL
;
570 kauth_cred_t my_cred
;
573 sessionp
= proc_session(p
);
575 my_cred
= kauth_cred_proc_ref(p
);
576 bzero(pbsd
, sizeof(struct proc_bsdinfo
));
577 pbsd
->pbi_status
= p
->p_stat
;
578 pbsd
->pbi_xstatus
= p
->p_xstat
;
579 pbsd
->pbi_pid
= p
->p_pid
;
580 pbsd
->pbi_ppid
= p
->p_ppid
;
581 pbsd
->pbi_uid
= kauth_cred_getuid(my_cred
);
582 pbsd
->pbi_gid
= kauth_cred_getgid(my_cred
);
583 pbsd
->pbi_ruid
= kauth_cred_getruid(my_cred
);
584 pbsd
->pbi_rgid
= kauth_cred_getrgid(my_cred
);
585 pbsd
->pbi_svuid
= kauth_cred_getsvuid(my_cred
);
586 pbsd
->pbi_svgid
= kauth_cred_getsvgid(my_cred
);
587 kauth_cred_unref(&my_cred
);
589 pbsd
->pbi_nice
= p
->p_nice
;
590 pbsd
->pbi_start_tvsec
= p
->p_start
.tv_sec
;
591 pbsd
->pbi_start_tvusec
= p
->p_start
.tv_usec
;
592 bcopy(&p
->p_comm
, &pbsd
->pbi_comm
[0], MAXCOMLEN
);
593 pbsd
->pbi_comm
[MAXCOMLEN
- 1] = '\0';
594 bcopy(&p
->p_name
, &pbsd
->pbi_name
[0], 2*MAXCOMLEN
);
595 pbsd
->pbi_name
[(2*MAXCOMLEN
) - 1] = '\0';
598 if ((p
->p_flag
& P_SYSTEM
) == P_SYSTEM
)
599 pbsd
->pbi_flags
|= PROC_FLAG_SYSTEM
;
600 if ((p
->p_lflag
& P_LTRACED
) == P_LTRACED
)
601 pbsd
->pbi_flags
|= PROC_FLAG_TRACED
;
602 if ((p
->p_lflag
& P_LEXIT
) == P_LEXIT
)
603 pbsd
->pbi_flags
|= PROC_FLAG_INEXIT
;
604 if ((p
->p_lflag
& P_LPPWAIT
) == P_LPPWAIT
)
605 pbsd
->pbi_flags
|= PROC_FLAG_PPWAIT
;
606 if ((p
->p_flag
& P_LP64
) == P_LP64
)
607 pbsd
->pbi_flags
|= PROC_FLAG_LP64
;
608 if ((p
->p_flag
& P_CONTROLT
) == P_CONTROLT
)
609 pbsd
->pbi_flags
|= PROC_FLAG_CONTROLT
;
610 if ((p
->p_flag
& P_THCWD
) == P_THCWD
)
611 pbsd
->pbi_flags
|= PROC_FLAG_THCWD
;
612 if ((p
->p_flag
& P_SUGID
) == P_SUGID
)
613 pbsd
->pbi_flags
|= PROC_FLAG_PSUGID
;
614 if ((p
->p_flag
& P_EXEC
) == P_EXEC
)
615 pbsd
->pbi_flags
|= PROC_FLAG_EXEC
;
617 if (sessionp
!= SESSION_NULL
) {
618 if (SESS_LEADER(p
, sessionp
))
619 pbsd
->pbi_flags
|= PROC_FLAG_SLEADER
;
620 if (sessionp
->s_ttyvp
)
621 pbsd
->pbi_flags
|= PROC_FLAG_CTTY
;
624 if ((p
->p_flag
& P_DELAYIDLESLEEP
) == P_DELAYIDLESLEEP
)
625 pbsd
->pbi_flags
|= PROC_FLAG_DELAYIDLESLEEP
;
627 switch(PROC_CONTROL_STATE(p
)) {
629 pbsd
->pbi_flags
|= PROC_FLAG_PC_THROTTLE
;
632 pbsd
->pbi_flags
|= PROC_FLAG_PC_SUSP
;
635 pbsd
->pbi_flags
|= PROC_FLAG_PC_KILL
;
639 switch(PROC_ACTION_STATE(p
)) {
641 pbsd
->pbi_flags
|= PROC_FLAG_PA_THROTTLE
;
644 pbsd
->pbi_flags
|= PROC_FLAG_PA_SUSP
;
648 /* if process is a zombie skip bg state */
649 if ((zombie
== 0) && (p
->p_stat
!= SZOMB
) && (p
->task
!= TASK_NULL
))
650 proc_get_darwinbgstate(p
->task
, &pbsd
->pbi_flags
);
653 pbsd
->pbi_nfiles
= p
->p_fd
->fd_nfiles
;
655 pbsd
->e_tdev
= NODEV
;
656 if (pg
!= PGRP_NULL
) {
657 pbsd
->pbi_pgid
= p
->p_pgrpid
;
658 pbsd
->pbi_pjobc
= pg
->pg_jobc
;
659 if ((p
->p_flag
& P_CONTROLT
) && (sessionp
!= SESSION_NULL
) && (tp
= SESSION_TP(sessionp
))) {
660 pbsd
->e_tdev
= tp
->t_dev
;
661 pbsd
->e_tpgid
= sessionp
->s_ttypgrpid
;
664 if (sessionp
!= SESSION_NULL
)
665 session_rele(sessionp
);
674 proc_pidshortbsdinfo(proc_t p
, struct proc_bsdshortinfo
* pbsd_shortp
, int zombie
)
676 bzero(pbsd_shortp
, sizeof(struct proc_bsdshortinfo
));
677 pbsd_shortp
->pbsi_pid
= p
->p_pid
;
678 pbsd_shortp
->pbsi_ppid
= p
->p_ppid
;
679 pbsd_shortp
->pbsi_pgid
= p
->p_pgrpid
;
680 pbsd_shortp
->pbsi_status
= p
->p_stat
;
681 bcopy(&p
->p_comm
, &pbsd_shortp
->pbsi_comm
[0], MAXCOMLEN
);
682 pbsd_shortp
->pbsi_comm
[MAXCOMLEN
- 1] = '\0';
684 pbsd_shortp
->pbsi_flags
= 0;
685 if ((p
->p_flag
& P_SYSTEM
) == P_SYSTEM
)
686 pbsd_shortp
->pbsi_flags
|= PROC_FLAG_SYSTEM
;
687 if ((p
->p_lflag
& P_LTRACED
) == P_LTRACED
)
688 pbsd_shortp
->pbsi_flags
|= PROC_FLAG_TRACED
;
689 if ((p
->p_lflag
& P_LEXIT
) == P_LEXIT
)
690 pbsd_shortp
->pbsi_flags
|= PROC_FLAG_INEXIT
;
691 if ((p
->p_lflag
& P_LPPWAIT
) == P_LPPWAIT
)
692 pbsd_shortp
->pbsi_flags
|= PROC_FLAG_PPWAIT
;
693 if ((p
->p_flag
& P_LP64
) == P_LP64
)
694 pbsd_shortp
->pbsi_flags
|= PROC_FLAG_LP64
;
695 if ((p
->p_flag
& P_CONTROLT
) == P_CONTROLT
)
696 pbsd_shortp
->pbsi_flags
|= PROC_FLAG_CONTROLT
;
697 if ((p
->p_flag
& P_THCWD
) == P_THCWD
)
698 pbsd_shortp
->pbsi_flags
|= PROC_FLAG_THCWD
;
699 if ((p
->p_flag
& P_SUGID
) == P_SUGID
)
700 pbsd_shortp
->pbsi_flags
|= PROC_FLAG_PSUGID
;
701 if ((p
->p_flag
& P_EXEC
) == P_EXEC
)
702 pbsd_shortp
->pbsi_flags
|= PROC_FLAG_EXEC
;
703 if ((p
->p_flag
& P_DELAYIDLESLEEP
) == P_DELAYIDLESLEEP
)
704 pbsd_shortp
->pbsi_flags
|= PROC_FLAG_DELAYIDLESLEEP
;
706 switch(PROC_CONTROL_STATE(p
)) {
708 pbsd_shortp
->pbsi_flags
|= PROC_FLAG_PC_THROTTLE
;
711 pbsd_shortp
->pbsi_flags
|= PROC_FLAG_PC_SUSP
;
714 pbsd_shortp
->pbsi_flags
|= PROC_FLAG_PC_KILL
;
718 switch(PROC_ACTION_STATE(p
)) {
720 pbsd_shortp
->pbsi_flags
|= PROC_FLAG_PA_THROTTLE
;
723 pbsd_shortp
->pbsi_flags
|= PROC_FLAG_PA_SUSP
;
727 /* if process is a zombie skip bg state */
728 if ((zombie
== 0) && (p
->p_stat
!= SZOMB
) && (p
->task
!= TASK_NULL
))
729 proc_get_darwinbgstate(p
->task
, &pbsd_shortp
->pbsi_flags
);
731 pbsd_shortp
->pbsi_uid
= p
->p_uid
;
732 pbsd_shortp
->pbsi_gid
= p
->p_gid
;
733 pbsd_shortp
->pbsi_ruid
= p
->p_ruid
;
734 pbsd_shortp
->pbsi_rgid
= p
->p_rgid
;
735 pbsd_shortp
->pbsi_svuid
= p
->p_svuid
;
736 pbsd_shortp
->pbsi_svgid
= p
->p_svgid
;
742 proc_pidtaskinfo(proc_t p
, struct proc_taskinfo
* ptinfo
)
748 bzero(ptinfo
, sizeof(struct proc_taskinfo
));
749 fill_taskprocinfo(task
, (struct proc_taskinfo_internal
*)ptinfo
);
757 proc_pidthreadinfo(proc_t p
, uint64_t arg
, int thuniqueid
, struct proc_threadinfo
*pthinfo
)
760 uint64_t threadaddr
= (uint64_t)arg
;
762 bzero(pthinfo
, sizeof(struct proc_threadinfo
));
764 error
= fill_taskthreadinfo(p
->task
, threadaddr
, thuniqueid
, (struct proc_threadinfo_internal
*)pthinfo
, NULL
, NULL
);
773 bsd_hasthreadname(void *uth
)
775 struct uthread
*ut
= (struct uthread
*)uth
;
777 /* This doesn't check for the empty string; do we care? */
786 bsd_getthreadname(void *uth
, char *buffer
)
788 struct uthread
*ut
= (struct uthread
*)uth
;
790 bcopy(ut
->pth_name
,buffer
,MAXTHREADNAMESIZE
);
794 * This is known to race with regards to the contents of the thread name; concurrent
795 * callers may result in a garbled name.
798 bsd_setthreadname(void *uth
, const char *name
) {
799 struct uthread
*ut
= (struct uthread
*)uth
;
800 char * name_buf
= NULL
;
803 /* If there is no existing thread name, allocate a buffer for one. */
804 name_buf
= kalloc(MAXTHREADNAMESIZE
);
806 bzero(name_buf
, MAXTHREADNAMESIZE
);
808 /* Someone could conceivably have named the thread at the same time we did. */
809 if (!OSCompareAndSwapPtr(NULL
, name_buf
, &ut
->pth_name
)) {
810 kfree(name_buf
, MAXTHREADNAMESIZE
);
813 kernel_debug_string_simple(TRACE_STRING_THREADNAME_PREV
, ut
->pth_name
);
816 strncpy(ut
->pth_name
, name
, MAXTHREADNAMESIZE
- 1);
817 kernel_debug_string_simple(TRACE_STRING_THREADNAME
, ut
->pth_name
);
821 bsd_copythreadname(void *dst_uth
, void *src_uth
)
823 struct uthread
*dst_ut
= (struct uthread
*)dst_uth
;
824 struct uthread
*src_ut
= (struct uthread
*)src_uth
;
826 if (src_ut
->pth_name
== NULL
)
829 if (dst_ut
->pth_name
== NULL
) {
830 dst_ut
->pth_name
= (char *)kalloc(MAXTHREADNAMESIZE
);
831 if (dst_ut
->pth_name
== NULL
)
835 bcopy(src_ut
->pth_name
, dst_ut
->pth_name
, MAXTHREADNAMESIZE
);
840 bsd_threadcdir(void * uth
, void *vptr
, int *vidp
)
842 struct uthread
* ut
= (struct uthread
*)uth
;
844 vnode_t
*vpp
= (vnode_t
*)vptr
;
858 proc_pidthreadpathinfo(proc_t p
, uint64_t arg
, struct proc_threadwithpathinfo
*pinfo
)
863 uint64_t threadaddr
= (uint64_t)arg
;
866 bzero(pinfo
, sizeof(struct proc_threadwithpathinfo
));
868 error
= fill_taskthreadinfo(p
->task
, threadaddr
, 0, (struct proc_threadinfo_internal
*)&pinfo
->pt
, (void *)&vp
, &vid
);
872 if ((vp
!= NULLVP
) && ((vnode_getwithvid(vp
, vid
)) == 0)) {
873 error
= fill_vnodeinfo(vp
, &pinfo
->pvip
.vip_vi
) ;
876 vn_getpath(vp
, &pinfo
->pvip
.vip_path
[0], &count
);
877 pinfo
->pvip
.vip_path
[MAXPATHLEN
-1] = 0;
887 proc_pidlistthreads(proc_t p
, user_addr_t buffer
, uint32_t buffersize
, int32_t *retval
)
896 count
= buffersize
/(sizeof(uint64_t));
897 numthreads
= get_numthreads(p
->task
);
901 if (numthreads
> count
)
904 kbuf
= (void *)kalloc(numthreads
* sizeof(uint64_t));
907 bzero(kbuf
, numthreads
* sizeof(uint64_t));
909 ret
= fill_taskthreadlist(p
->task
, kbuf
, numthreads
);
911 error
= copyout(kbuf
, buffer
, ret
);
912 kfree(kbuf
, numthreads
* sizeof(uint64_t));
921 proc_pidregioninfo(proc_t p
, uint64_t arg
, user_addr_t buffer
, __unused
uint32_t buffersize
, int32_t *retval
)
923 struct proc_regioninfo preginfo
;
926 bzero(&preginfo
, sizeof(struct proc_regioninfo
));
927 ret
= fill_procregioninfo( p
->task
, arg
, (struct proc_regioninfo_internal
*)&preginfo
, (uintptr_t *)0, (uint32_t *)0);
930 error
= copyout(&preginfo
, buffer
, sizeof(struct proc_regioninfo
));
932 *retval
= sizeof(struct proc_regioninfo
);
938 proc_pidregionpathinfo(proc_t p
, uint64_t arg
, user_addr_t buffer
, __unused
uint32_t buffersize
, int32_t *retval
)
940 struct proc_regionwithpathinfo preginfo
;
942 uintptr_t vnodeaddr
= 0;
947 bzero(&preginfo
, sizeof(struct proc_regionwithpathinfo
));
949 ret
= fill_procregioninfo( p
->task
, arg
, (struct proc_regioninfo_internal
*)&preginfo
.prp_prinfo
, (uintptr_t *)&vnodeaddr
, (uint32_t *)&vnodeid
);
953 vp
= (vnode_t
)vnodeaddr
;
954 if ((vnode_getwithvid(vp
, vnodeid
)) == 0) {
955 /* FILL THE VNODEINFO */
956 error
= fill_vnodeinfo(vp
, &preginfo
.prp_vip
.vip_vi
);
958 vn_getpath(vp
, &preginfo
.prp_vip
.vip_path
[0], &count
);
959 /* Always make sure it is null terminated */
960 preginfo
.prp_vip
.vip_path
[MAXPATHLEN
-1] = 0;
964 error
= copyout(&preginfo
, buffer
, sizeof(struct proc_regionwithpathinfo
));
966 *retval
= sizeof(struct proc_regionwithpathinfo
);
971 proc_pidregionpathinfo2(proc_t p
, uint64_t arg
, user_addr_t buffer
, __unused
uint32_t buffersize
, int32_t *retval
)
973 struct proc_regionwithpathinfo preginfo
;
975 uintptr_t vnodeaddr
= 0;
980 bzero(&preginfo
, sizeof(struct proc_regionwithpathinfo
));
982 ret
= fill_procregioninfo_onlymappedvnodes( p
->task
, arg
, (struct proc_regioninfo_internal
*)&preginfo
.prp_prinfo
, (uintptr_t *)&vnodeaddr
, (uint32_t *)&vnodeid
);
988 vp
= (vnode_t
)vnodeaddr
;
989 if ((vnode_getwithvid(vp
, vnodeid
)) == 0) {
990 /* FILL THE VNODEINFO */
991 error
= fill_vnodeinfo(vp
, &preginfo
.prp_vip
.vip_vi
);
993 vn_getpath(vp
, &preginfo
.prp_vip
.vip_path
[0], &count
);
994 /* Always make sure it is null terminated */
995 preginfo
.prp_vip
.vip_path
[MAXPATHLEN
-1] = 0;
1001 error
= copyout(&preginfo
, buffer
, sizeof(struct proc_regionwithpathinfo
));
1003 *retval
= sizeof(struct proc_regionwithpathinfo
);
1008 proc_pidregionpathinfo3(proc_t p
, uint64_t arg
, user_addr_t buffer
, __unused
uint32_t buffersize
, int32_t *retval
)
1010 struct proc_regionwithpathinfo preginfo
;
1012 uintptr_t vnodeaddr
;
1018 /* Loop while looking for vnodes that match dev_t filter */
1020 bzero(&preginfo
, sizeof(struct proc_regionwithpathinfo
));
1024 ret
= fill_procregioninfo_onlymappedvnodes( p
->task
, addr
, (struct proc_regioninfo_internal
*)&preginfo
.prp_prinfo
, (uintptr_t *)&vnodeaddr
, (uint32_t *)&vnodeid
);
1030 vp
= (vnode_t
)vnodeaddr
;
1031 if ((vnode_getwithvid(vp
, vnodeid
)) == 0) {
1032 /* Check if the vnode matches the filter, otherwise loop looking for the next memory region backed by a vnode */
1033 struct vnode_attr va
;
1035 memset(&va
, 0, sizeof(va
));
1037 VATTR_WANTED(&va
, va_fsid
);
1039 ret
= vnode_getattr(vp
, &va
, vfs_context_current());
1045 if (va
.va_fsid
== arg
) {
1046 /* FILL THE VNODEINFO */
1047 error
= fill_vnodeinfo(vp
, &preginfo
.prp_vip
.vip_vi
);
1049 vn_getpath(vp
, &preginfo
.prp_vip
.vip_path
[0], &count
);
1050 /* Always make sure it is null terminated */
1051 preginfo
.prp_vip
.vip_path
[MAXPATHLEN
-1] = 0;
1060 addr
= preginfo
.prp_prinfo
.pri_address
+ preginfo
.prp_prinfo
.pri_size
;
1063 error
= copyout(&preginfo
, buffer
, sizeof(struct proc_regionwithpathinfo
));
1065 *retval
= sizeof(struct proc_regionwithpathinfo
);
1070 * Path is relative to current process directory; may different from current
1074 proc_pidvnodepathinfo(proc_t p
, __unused
uint64_t arg
, user_addr_t buffer
, __unused
uint32_t buffersize
, int32_t *retval
)
1076 struct proc_vnodepathinfo pvninfo
;
1078 vnode_t vncdirvp
= NULLVP
;
1079 uint32_t vncdirid
=0;
1080 vnode_t vnrdirvp
= NULLVP
;
1081 uint32_t vnrdirid
=0;
1084 bzero(&pvninfo
, sizeof(struct proc_vnodepathinfo
));
1087 if (p
->p_fd
->fd_cdir
) {
1088 vncdirvp
= p
->p_fd
->fd_cdir
;
1089 vncdirid
= p
->p_fd
->fd_cdir
->v_id
;
1091 if (p
->p_fd
->fd_rdir
) {
1092 vnrdirvp
= p
->p_fd
->fd_rdir
;
1093 vnrdirid
= p
->p_fd
->fd_rdir
->v_id
;
1097 if (vncdirvp
!= NULLVP
) {
1098 if ((error
= vnode_getwithvid(vncdirvp
, vncdirid
)) == 0) {
1099 /* FILL THE VNODEINFO */
1100 error
= fill_vnodeinfo(vncdirvp
, &pvninfo
.pvi_cdir
.vip_vi
);
1103 vn_getpath(vncdirvp
, &pvninfo
.pvi_cdir
.vip_path
[0], &count
);
1104 pvninfo
.pvi_cdir
.vip_path
[MAXPATHLEN
-1] = 0;
1106 vnode_put(vncdirvp
);
1112 if ((error
== 0) && (vnrdirvp
!= NULLVP
)) {
1113 if ((error
= vnode_getwithvid(vnrdirvp
, vnrdirid
)) == 0) {
1114 /* FILL THE VNODEINFO */
1115 error
= fill_vnodeinfo(vnrdirvp
, &pvninfo
.pvi_rdir
.vip_vi
);
1118 vn_getpath(vnrdirvp
, &pvninfo
.pvi_rdir
.vip_path
[0], &count
);
1119 pvninfo
.pvi_rdir
.vip_path
[MAXPATHLEN
-1] = 0;
1121 vnode_put(vnrdirvp
);
1127 error
= copyout(&pvninfo
, buffer
, sizeof(struct proc_vnodepathinfo
));
1129 *retval
= sizeof(struct proc_vnodepathinfo
);
1136 proc_pidpathinfo(proc_t p
, __unused
uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, __unused
int32_t *retval
)
1140 int len
= buffersize
;
1148 buf
= (char *)kalloc(buffersize
);
1152 bzero(buf
, buffersize
);
1154 error
= proc_pidpathinfo_internal(p
, arg
, buf
, buffersize
, retval
);
1156 error
= copyout(buf
, buffer
, len
);
1158 kfree(buf
, buffersize
);
1163 proc_pidpathinfo_internal(proc_t p
, __unused
uint64_t arg
, char *buf
, uint32_t buffersize
, __unused
int32_t *retval
)
1167 vnode_t nvp
= NULLVP
;
1168 int len
= buffersize
;
1175 vid
= vnode_vid(tvp
);
1176 error
= vnode_getwithvid(tvp
, vid
);
1178 error
= vn_getpath_fsenter(tvp
, buf
, &len
);
1181 error
= vnode_lookup(buf
, 0, &nvp
, vfs_context_current());
1182 if ((error
== 0) && ( nvp
!= NULLVP
))
1191 proc_pidworkqueueinfo(proc_t p
, struct proc_workqueueinfo
*pwqinfo
)
1195 bzero(pwqinfo
, sizeof(struct proc_workqueueinfo
));
1197 error
= fill_procworkqueue(p
, pwqinfo
);
1207 proc_piduniqidentifierinfo(proc_t p
, struct proc_uniqidentifierinfo
*p_uniqidinfo
)
1209 p_uniqidinfo
->p_uniqueid
= proc_uniqueid(p
);
1210 proc_getexecutableuuid(p
, (unsigned char *)&p_uniqidinfo
->p_uuid
, sizeof(p_uniqidinfo
->p_uuid
));
1211 p_uniqidinfo
->p_puniqueid
= proc_puniqueid(p
);
1212 p_uniqidinfo
->p_reserve2
= 0;
1213 p_uniqidinfo
->p_reserve3
= 0;
1214 p_uniqidinfo
->p_reserve4
= 0;
1219 proc_piduuidinfo(pid_t pid
, uuid_t uuid_buf
, uint32_t buffersize
)
1221 struct proc
* p
= PROC_NULL
;
1224 if (buffersize
< sizeof(uuid_t
))
1227 if ((p
= proc_find(pid
)) == PROC_NULL
) {
1228 p
= proc_find_zombref(pid
);
1231 if (p
== PROC_NULL
) {
1235 proc_getexecutableuuid(p
, (unsigned char *)uuid_buf
, buffersize
);
1238 proc_drop_zombref(p
);
1246 * Function to get the uuid and pid of the originator of the voucher.
1249 proc_pidoriginatorpid_uuid(uuid_t uuid
, uint32_t buffersize
, pid_t
*pid
)
1251 pid_t originator_pid
;
1256 * Get the current voucher origin pid. The pid returned here
1257 * might not be valid or may have been recycled.
1259 kr
= thread_get_current_voucher_origin_pid(&originator_pid
);
1260 /* If errors, convert errors to appropriate format */
1262 if (kr
== KERN_INVALID_TASK
)
1264 else if (kr
== KERN_INVALID_VALUE
)
1271 *pid
= originator_pid
;
1272 error
= proc_piduuidinfo(originator_pid
, uuid
, buffersize
);
1277 * Function to get the uuid of the originator of the voucher.
1280 proc_pidoriginatoruuid(uuid_t uuid
, uint32_t buffersize
)
1282 pid_t originator_pid
;
1283 return (proc_pidoriginatorpid_uuid(uuid
, buffersize
, &originator_pid
));
1286 /***************************** proc_pidoriginatorinfo ***************************/
1289 proc_pidoriginatorinfo(int pid
, int flavor
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
)
1291 int error
= ENOTSUP
;
1295 case PROC_PIDORIGINATOR_UUID
:
1296 size
= PROC_PIDORIGINATOR_UUID_SIZE
;
1298 case PROC_PIDORIGINATOR_BGSTATE
:
1299 size
= PROC_PIDORIGINATOR_BGSTATE_SIZE
;
1301 case PROC_PIDORIGINATOR_PID_UUID
:
1302 size
= PROC_PIDORIGINATOR_PID_UUID_SIZE
;
1308 if (buffersize
< size
)
1311 if (pid
!= 0 && pid
!= proc_selfpid())
1315 case PROC_PIDORIGINATOR_UUID
: {
1318 error
= proc_pidoriginatoruuid(uuid
, sizeof(uuid
));
1322 error
= copyout(uuid
, buffer
, size
);
1328 case PROC_PIDORIGINATOR_PID_UUID
: {
1329 struct proc_originatorinfo originator_info
;
1330 bzero(&originator_info
, sizeof(originator_info
));
1332 error
= proc_pidoriginatorpid_uuid(originator_info
.originator_uuid
,
1333 sizeof(uuid_t
), &originator_info
.originator_pid
);
1337 error
= copyout(&originator_info
, buffer
, size
);
1343 case PROC_PIDORIGINATOR_BGSTATE
: {
1344 uint32_t is_backgrounded
;
1345 error
= proc_get_originatorbgstate(&is_backgrounded
);
1349 error
= copyout(&is_backgrounded
, buffer
, size
);
1362 /***************************** proc_listcoalitions ***************************/
1363 int proc_listcoalitions(int flavor
, int type
, user_addr_t buffer
,
1364 uint32_t buffersize
, int32_t *retval
)
1366 #if CONFIG_COALITIONS
1367 int error
= ENOTSUP
;
1370 void *coalinfo
= NULL
;
1371 uint32_t k_buffersize
= 0, copyout_sz
= 0;
1372 int ncoals
= 0, ncoals_
= 0;
1374 /* struct procinfo_coalinfo; */
1377 case LISTCOALITIONS_ALL_COALS
:
1378 elem_size
= LISTCOALITIONS_ALL_COALS_SIZE
;
1381 case LISTCOALITIONS_SINGLE_TYPE
:
1382 elem_size
= LISTCOALITIONS_SINGLE_TYPE_SIZE
;
1389 /* find the total number of coalitions */
1390 ncoals
= coalitions_get_list(coal_type
, NULL
, 0);
1392 if (ncoals
== 0 || buffer
== 0 || buffersize
== 0) {
1394 * user just wants buffer size
1395 * or there are no coalitions
1398 *retval
= (int)(ncoals
* elem_size
);
1402 k_buffersize
= ncoals
* elem_size
;
1403 coalinfo
= kalloc((vm_size_t
)k_buffersize
);
1408 bzero(coalinfo
, k_buffersize
);
1411 case LISTCOALITIONS_ALL_COALS
:
1412 case LISTCOALITIONS_SINGLE_TYPE
:
1413 ncoals_
= coalitions_get_list(coal_type
, coalinfo
, ncoals
);
1416 panic("memory corruption?!");
1420 /* all the coalitions disappeared... weird but valid */
1427 * Some coalitions may have disappeared between our initial check,
1428 * and the the actual list acquisition.
1429 * Only copy out what we really need.
1431 copyout_sz
= k_buffersize
;
1432 if (ncoals_
< ncoals
)
1433 copyout_sz
= ncoals_
* elem_size
;
1436 * copy the list up to user space
1437 * (we're guaranteed to have a non-null pointer/size here)
1439 error
= copyout(coalinfo
, buffer
,
1440 copyout_sz
< buffersize
? copyout_sz
: buffersize
);
1443 *retval
= (int)copyout_sz
;
1447 kfree(coalinfo
, k_buffersize
);
1451 /* no coalition support */
1462 /*************************** proc_can_use_forgeound_hw **************************/
1463 int proc_can_use_foreground_hw(int pid
, user_addr_t u_reason
, uint32_t reasonsize
, int32_t *retval
)
1465 proc_t p
= PROC_NULL
;
1467 uint32_t reason
= PROC_FGHW_ERROR
;
1469 task_t task
= TASK_NULL
;
1470 #if CONFIG_COALITIONS
1471 coalition_t coal
= COALITION_NULL
;
1478 reason
= PROC_FGHW_ERROR
;
1483 if (p
== PROC_NULL
) {
1485 reason
= PROC_FGHW_ERROR
;
1489 #if CONFIG_COALITIONS
1490 if (p
!= current_proc() &&
1491 !kauth_cred_issuser(kauth_cred_get())) {
1493 reason
= PROC_FGHW_ERROR
;
1498 task_reference(task
);
1499 if (coalition_is_leader(task
, COALITION_TYPE_JETSAM
, &coal
) == FALSE
) {
1500 /* current task is not a coalition leader: find the leader */
1501 task_deallocate(task
);
1502 task
= coalition_get_leader(coal
);
1505 if (task
!= TASK_NULL
) {
1507 * If task is non-null, then it is the coalition leader of the
1508 * current process' coalition. This could be the same task as
1509 * the current_task, and that's OK.
1514 proc_get_darwinbgstate(task
, &flags
);
1515 if ((flags
& PROC_FLAG_APPLICATION
) != PROC_FLAG_APPLICATION
) {
1517 * Coalition leader is not an application, continue
1518 * searching for other ways this task could gain
1521 reason
= PROC_FGHW_DAEMON_LEADER
;
1525 if (proc_get_effective_task_policy(task
, TASK_POLICY_DARWIN_BG
)) {
1527 * If the leader of the current process' coalition has
1528 * been marked as DARWIN_BG, then it definitely should
1529 * not be using foreground hardware resources.
1531 reason
= PROC_FGHW_LEADER_BACKGROUND
;
1535 role
= proc_get_effective_task_policy(task
, TASK_POLICY_ROLE
);
1537 case TASK_FOREGROUND_APPLICATION
: /* DARWIN_ROLE_UI_FOCAL */
1538 case TASK_BACKGROUND_APPLICATION
: /* DARWIN_ROLE_UI */
1540 * The leader of this coalition is a focal, UI app:
1542 * TODO: should extensions/plugins be allowed to use
1546 reason
= PROC_FGHW_OK
;
1548 case TASK_DEFAULT_APPLICATION
: /* DARWIN_ROLE_UI_NON_FOCAL */
1549 case TASK_NONUI_APPLICATION
: /* DARWIN_ROLE_NON_UI */
1550 case TASK_THROTTLE_APPLICATION
:
1551 case TASK_UNSPECIFIED
:
1553 /* non-focal, non-ui apps don't get access */
1554 reason
= PROC_FGHW_LEADER_NONUI
;
1560 if (task
!= TASK_NULL
) {
1561 task_deallocate(task
);
1564 #endif /* CONFIG_COALITIONS */
1567 * There is no reasonable semantic to investigate the currently
1568 * adopted voucher of an arbitrary thread in a non-current process.
1571 if (p
!= current_proc()) {
1577 * In the absence of coalitions, fall back to a voucher-based lookup
1578 * where a daemon can used foreground HW if it's operating on behalf
1579 * of a foreground application.
1580 * NOTE: this is equivalent to a call to
1581 * proc_pidoriginatorinfo(PROC_PIDORIGINATOR_BGSTATE, &isBG, sizeof(isBG))
1584 error
= proc_get_originatorbgstate(&isBG
);
1589 reason
= PROC_FGHW_NO_ORIGINATOR
;
1593 reason
= PROC_FGHW_NO_VOUCHER_ATTR
;
1597 reason
= PROC_FGHW_DAEMON_NO_VOUCHER
;
1601 /* some other error occurred: report that to the caller */
1602 reason
= PROC_FGHW_VOUCHER_ERROR
;
1607 reason
= PROC_FGHW_ORIGINATOR_BACKGROUND
;
1611 * The process itself is either a foreground app, or has
1612 * adopted a voucher originating from an app that's still in
1615 reason
= PROC_FGHW_DAEMON_OK
;
1620 if (task
!= TASK_NULL
)
1621 task_deallocate(task
);
1624 if (reasonsize
>= sizeof(reason
) && u_reason
!= (user_addr_t
)0)
1625 (void)copyout(&reason
, u_reason
, sizeof(reason
));
1630 /********************************** proc_pidinfo ********************************/
1634 proc_pidinfo(int pid
, int flavor
, uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
)
1636 struct proc
* p
= PROC_NULL
;
1637 int error
= ENOTSUP
;
1640 int shortversion
= 0;
1644 int uniqidversion
= 0;
1645 boolean_t check_same_user
;
1648 case PROC_PIDLISTFDS
:
1649 size
= PROC_PIDLISTFD_SIZE
;
1650 if (buffer
== (user_addr_t
)0)
1653 case PROC_PIDTBSDINFO
:
1654 size
= PROC_PIDTBSDINFO_SIZE
;
1656 case PROC_PIDTASKINFO
:
1657 size
= PROC_PIDTASKINFO_SIZE
;
1659 case PROC_PIDTASKALLINFO
:
1660 size
= PROC_PIDTASKALLINFO_SIZE
;
1662 case PROC_PIDTHREADINFO
:
1663 size
= PROC_PIDTHREADINFO_SIZE
;
1665 case PROC_PIDLISTTHREADS
:
1666 size
= PROC_PIDLISTTHREADS_SIZE
;
1668 case PROC_PIDREGIONINFO
:
1669 size
= PROC_PIDREGIONINFO_SIZE
;
1671 case PROC_PIDREGIONPATHINFO
:
1672 size
= PROC_PIDREGIONPATHINFO_SIZE
;
1674 case PROC_PIDVNODEPATHINFO
:
1675 size
= PROC_PIDVNODEPATHINFO_SIZE
;
1677 case PROC_PIDTHREADPATHINFO
:
1678 size
= PROC_PIDTHREADPATHINFO_SIZE
;
1680 case PROC_PIDPATHINFO
:
1683 case PROC_PIDWORKQUEUEINFO
:
1684 /* kernel does not have workq info */
1688 size
= PROC_PIDWORKQUEUEINFO_SIZE
;
1690 case PROC_PIDT_SHORTBSDINFO
:
1691 size
= PROC_PIDT_SHORTBSDINFO_SIZE
;
1693 case PROC_PIDLISTFILEPORTS
:
1694 size
= PROC_PIDLISTFILEPORTS_SIZE
;
1695 if (buffer
== (user_addr_t
)0)
1698 case PROC_PIDTHREADID64INFO
:
1699 size
= PROC_PIDTHREADID64INFO_SIZE
;
1701 case PROC_PIDUNIQIDENTIFIERINFO
:
1702 size
= PROC_PIDUNIQIDENTIFIERINFO_SIZE
;
1704 case PROC_PIDT_BSDINFOWITHUNIQID
:
1705 size
= PROC_PIDT_BSDINFOWITHUNIQID_SIZE
;
1707 case PROC_PIDARCHINFO
:
1708 size
= PROC_PIDARCHINFO_SIZE
;
1710 case PROC_PIDCOALITIONINFO
:
1711 size
= PROC_PIDCOALITIONINFO_SIZE
;
1713 case PROC_PIDNOTEEXIT
:
1715 * Set findzomb explicitly because arg passed
1716 * in is used as note exit status bits.
1718 size
= PROC_PIDNOTEEXIT_SIZE
;
1721 case PROC_PIDEXITREASONINFO
:
1722 size
= PROC_PIDEXITREASONINFO_SIZE
;
1725 case PROC_PIDEXITREASONBASICINFO
:
1726 size
= PROC_PIDEXITREASONBASICINFOSIZE
;
1729 case PROC_PIDREGIONPATHINFO2
:
1730 size
= PROC_PIDREGIONPATHINFO2_SIZE
;
1732 case PROC_PIDREGIONPATHINFO3
:
1733 size
= PROC_PIDREGIONPATHINFO3_SIZE
;
1739 if (buffersize
< size
)
1742 if ((flavor
== PROC_PIDPATHINFO
) && (buffersize
> PROC_PIDPATHINFO_MAXSIZE
)) {
1746 /* Check if we need to look for zombies */
1747 if ((flavor
== PROC_PIDTBSDINFO
) || (flavor
== PROC_PIDT_SHORTBSDINFO
) || (flavor
== PROC_PIDT_BSDINFOWITHUNIQID
)
1748 || (flavor
== PROC_PIDUNIQIDENTIFIERINFO
)) {
1753 if ((p
= proc_find(pid
)) == PROC_NULL
) {
1755 p
= proc_find_zombref(pid
);
1756 if (p
== PROC_NULL
) {
1765 /* Certain operations don't require privileges */
1767 case PROC_PIDT_SHORTBSDINFO
:
1768 case PROC_PIDUNIQIDENTIFIERINFO
:
1769 case PROC_PIDPATHINFO
:
1770 case PROC_PIDCOALITIONINFO
:
1771 check_same_user
= NO_CHECK_SAME_USER
;
1774 check_same_user
= CHECK_SAME_USER
;
1778 /* Do we have permission to look into this? */
1779 if ((error
= proc_security_policy(p
, PROC_INFO_CALL_PIDINFO
, flavor
, check_same_user
)))
1783 case PROC_PIDLISTFDS
: {
1784 error
= proc_pidfdlist(p
, buffer
, buffersize
, retval
);
1788 case PROC_PIDUNIQIDENTIFIERINFO
: {
1789 struct proc_uniqidentifierinfo p_uniqidinfo
;
1790 bzero(&p_uniqidinfo
, sizeof(p_uniqidinfo
));
1791 proc_piduniqidentifierinfo(p
, &p_uniqidinfo
);
1792 error
= copyout(&p_uniqidinfo
, buffer
, sizeof(struct proc_uniqidentifierinfo
));
1794 *retval
= sizeof(struct proc_uniqidentifierinfo
);
1798 case PROC_PIDT_SHORTBSDINFO
:
1800 case PROC_PIDT_BSDINFOWITHUNIQID
:
1801 case PROC_PIDTBSDINFO
: {
1802 struct proc_bsdinfo pbsd
;
1803 struct proc_bsdshortinfo pbsd_short
;
1804 struct proc_bsdinfowithuniqid pbsd_uniqid
;
1806 if (flavor
== PROC_PIDT_BSDINFOWITHUNIQID
)
1809 if (shortversion
!= 0) {
1810 error
= proc_pidshortbsdinfo(p
, &pbsd_short
, zombie
);
1812 error
= proc_pidbsdinfo(p
, &pbsd
, zombie
);
1813 if (uniqidversion
!= 0) {
1814 bzero(&pbsd_uniqid
, sizeof(pbsd_uniqid
));
1815 proc_piduniqidentifierinfo(p
, &pbsd_uniqid
.p_uniqidentifier
);
1816 pbsd_uniqid
.pbsd
= pbsd
;
1821 if (shortversion
!= 0) {
1822 error
= copyout(&pbsd_short
, buffer
, sizeof(struct proc_bsdshortinfo
));
1824 *retval
= sizeof(struct proc_bsdshortinfo
);
1825 } else if (uniqidversion
!= 0) {
1826 error
= copyout(&pbsd_uniqid
, buffer
, sizeof(struct proc_bsdinfowithuniqid
));
1828 *retval
= sizeof(struct proc_bsdinfowithuniqid
);
1830 error
= copyout(&pbsd
, buffer
, sizeof(struct proc_bsdinfo
));
1832 *retval
= sizeof(struct proc_bsdinfo
);
1838 case PROC_PIDTASKINFO
: {
1839 struct proc_taskinfo ptinfo
;
1841 error
= proc_pidtaskinfo(p
, &ptinfo
);
1843 error
= copyout(&ptinfo
, buffer
, sizeof(struct proc_taskinfo
));
1845 *retval
= sizeof(struct proc_taskinfo
);
1850 case PROC_PIDTASKALLINFO
: {
1851 struct proc_taskallinfo pall
;
1852 bzero(&pall
, sizeof(pall
));
1853 error
= proc_pidbsdinfo(p
, &pall
.pbsd
, 0);
1854 error
= proc_pidtaskinfo(p
, &pall
.ptinfo
);
1856 error
= copyout(&pall
, buffer
, sizeof(struct proc_taskallinfo
));
1858 *retval
= sizeof(struct proc_taskallinfo
);
1863 case PROC_PIDTHREADID64INFO
:
1865 case PROC_PIDTHREADINFO
:{
1866 struct proc_threadinfo pthinfo
;
1868 error
= proc_pidthreadinfo(p
, arg
, thuniqueid
, &pthinfo
);
1870 error
= copyout(&pthinfo
, buffer
, sizeof(struct proc_threadinfo
));
1872 *retval
= sizeof(struct proc_threadinfo
);
1877 case PROC_PIDLISTTHREADS
:{
1878 error
= proc_pidlistthreads(p
, buffer
, buffersize
, retval
);
1882 case PROC_PIDREGIONINFO
:{
1883 error
= proc_pidregioninfo(p
, arg
, buffer
, buffersize
, retval
);
1888 case PROC_PIDREGIONPATHINFO
:{
1889 error
= proc_pidregionpathinfo(p
, arg
, buffer
, buffersize
, retval
);
1893 case PROC_PIDREGIONPATHINFO2
:{
1894 error
= proc_pidregionpathinfo2(p
, arg
, buffer
, buffersize
, retval
);
1898 case PROC_PIDREGIONPATHINFO3
:{
1899 error
= proc_pidregionpathinfo3(p
, arg
, buffer
, buffersize
, retval
);
1903 case PROC_PIDVNODEPATHINFO
:{
1904 error
= proc_pidvnodepathinfo(p
, arg
, buffer
, buffersize
, retval
);
1909 case PROC_PIDTHREADPATHINFO
:{
1910 struct proc_threadwithpathinfo pinfo
;
1912 error
= proc_pidthreadpathinfo(p
, arg
, &pinfo
);
1914 error
= copyout((caddr_t
)&pinfo
, buffer
, sizeof(struct proc_threadwithpathinfo
));
1916 *retval
= sizeof(struct proc_threadwithpathinfo
);
1921 case PROC_PIDPATHINFO
: {
1922 error
= proc_pidpathinfo(p
, arg
, buffer
, buffersize
, retval
);
1927 case PROC_PIDWORKQUEUEINFO
:{
1928 struct proc_workqueueinfo pwqinfo
;
1930 error
= proc_pidworkqueueinfo(p
, &pwqinfo
);
1932 error
= copyout(&pwqinfo
, buffer
, sizeof(struct proc_workqueueinfo
));
1934 *retval
= sizeof(struct proc_workqueueinfo
);
1939 case PROC_PIDLISTFILEPORTS
: {
1940 error
= proc_pidfileportlist(p
, buffer
, buffersize
, retval
);
1944 case PROC_PIDARCHINFO
: {
1945 struct proc_archinfo pai
;
1946 bzero(&pai
, sizeof(pai
));
1947 proc_archinfo(p
, &pai
);
1948 error
= copyout(&pai
, buffer
, sizeof(struct proc_archinfo
));
1950 *retval
= sizeof(struct proc_archinfo
);
1955 case PROC_PIDCOALITIONINFO
: {
1956 struct proc_pidcoalitioninfo pci
;
1957 proc_pidcoalitioninfo(p
, &pci
);
1958 error
= copyout(&pci
, buffer
, sizeof(struct proc_pidcoalitioninfo
));
1960 *retval
= sizeof(struct proc_pidcoalitioninfo
);
1965 case PROC_PIDNOTEEXIT
: {
1967 error
= proc_pidnoteexit(p
, arg
, &data
);
1969 error
= copyout(&data
, buffer
, sizeof(data
));
1971 *retval
= sizeof(data
);
1977 case PROC_PIDEXITREASONINFO
: {
1978 struct proc_exitreasoninfo eri
;
1980 error
= copyin(buffer
, &eri
, sizeof(eri
));
1985 error
= proc_pidexitreasoninfo(p
, &eri
, NULL
);
1987 error
= copyout(&eri
, buffer
, sizeof(eri
));
1989 *retval
= sizeof(eri
);
1995 case PROC_PIDEXITREASONBASICINFO
: {
1996 struct proc_exitreasonbasicinfo beri
;
1998 bzero(&beri
, sizeof(struct proc_exitreasonbasicinfo
));
2000 error
= proc_pidexitreasoninfo(p
, NULL
, &beri
);
2002 error
= copyout(&beri
, buffer
, sizeof(beri
));
2004 *retval
= sizeof(beri
);
2018 proc_drop_zombref(p
);
2024 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
)
2026 struct vnode_fdinfo vfi
;
2029 if ((error
= vnode_getwithvid(vp
, vid
)) != 0) {
2032 bzero(&vfi
, sizeof(struct vnode_fdinfo
));
2033 fill_fileinfo(fp
, proc
, fd
, &vfi
.pfi
);
2034 error
= fill_vnodeinfo(vp
, &vfi
.pvi
);
2037 error
= copyout((caddr_t
)&vfi
, buffer
, sizeof(struct vnode_fdinfo
));
2039 *retval
= sizeof(struct vnode_fdinfo
);
2045 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
)
2047 struct vnode_fdinfowithpath vfip
;
2048 int count
, error
= 0;
2050 if ((error
= vnode_getwithvid(vp
, vid
)) != 0) {
2053 bzero(&vfip
, sizeof(struct vnode_fdinfowithpath
));
2054 fill_fileinfo(fp
, proc
, fd
, &vfip
.pfi
);
2055 error
= fill_vnodeinfo(vp
, &vfip
.pvip
.vip_vi
) ;
2058 vn_getpath(vp
, &vfip
.pvip
.vip_path
[0], &count
);
2059 vfip
.pvip
.vip_path
[MAXPATHLEN
-1] = 0;
2061 error
= copyout((caddr_t
)&vfip
, buffer
, sizeof(struct vnode_fdinfowithpath
));
2063 *retval
= sizeof(struct vnode_fdinfowithpath
);
2070 fill_fileinfo(struct fileproc
* fp
, proc_t proc
, int fd
, struct proc_fileinfo
* fproc
)
2072 fproc
->fi_openflags
= fp
->f_fglob
->fg_flag
;
2073 fproc
->fi_status
= 0;
2074 fproc
->fi_offset
= fp
->f_fglob
->fg_offset
;
2075 fproc
->fi_type
= FILEGLOB_DTYPE(fp
->f_fglob
);
2076 if (fp
->f_fglob
->fg_count
> 1)
2077 fproc
->fi_status
|= PROC_FP_SHARED
;
2078 if (proc
!= PROC_NULL
) {
2079 if ((FDFLAGS_GET(proc
, fd
) & UF_EXCLOSE
) != 0)
2080 fproc
->fi_status
|= PROC_FP_CLEXEC
;
2081 if ((FDFLAGS_GET(proc
, fd
) & UF_FORKCLOSE
) != 0)
2082 fproc
->fi_status
|= PROC_FP_CLFORK
;
2084 if (FILEPROC_TYPE(fp
) == FTYPE_GUARDED
) {
2085 fproc
->fi_status
|= PROC_FP_GUARDED
;
2086 fproc
->fi_guardflags
= 0;
2087 if (fp_isguarded(fp
, GUARD_CLOSE
))
2088 fproc
->fi_guardflags
|= PROC_FI_GUARD_CLOSE
;
2089 if (fp_isguarded(fp
, GUARD_DUP
))
2090 fproc
->fi_guardflags
|= PROC_FI_GUARD_DUP
;
2091 if (fp_isguarded(fp
, GUARD_SOCKET_IPC
))
2092 fproc
->fi_guardflags
|= PROC_FI_GUARD_SOCKET_IPC
;
2093 if (fp_isguarded(fp
, GUARD_FILEPORT
))
2094 fproc
->fi_guardflags
|= PROC_FI_GUARD_FILEPORT
;
2101 fill_vnodeinfo(vnode_t vp
, struct vnode_info
*vinfo
)
2103 vfs_context_t context
;
2107 bzero(&sb
, sizeof(struct stat64
));
2108 context
= vfs_context_create((vfs_context_t
)0);
2109 error
= vn_stat(vp
, &sb
, NULL
, 1, context
);
2110 (void)vfs_context_rele(context
);
2112 munge_vinfo_stat(&sb
, &vinfo
->vi_stat
);
2117 if (vp
->v_mount
!= dead_mountp
) {
2118 vinfo
->vi_fsid
= vp
->v_mount
->mnt_vfsstat
.f_fsid
;
2120 vinfo
->vi_fsid
.val
[0] = 0;
2121 vinfo
->vi_fsid
.val
[1] = 0;
2123 vinfo
->vi_type
= vp
->v_type
;
2129 pid_socketinfo(socket_t so
, struct fileproc
*fp
, proc_t proc
, int fd
, user_addr_t buffer
, __unused
uint32_t buffersize
, int32_t * retval
)
2132 struct socket_fdinfo s
;
2135 bzero(&s
, sizeof(struct socket_fdinfo
));
2136 fill_fileinfo(fp
, proc
, fd
, &s
.pfi
);
2137 if ((error
= fill_socketinfo(so
, &s
.psi
)) == 0) {
2138 if ((error
= copyout(&s
, buffer
, sizeof(struct socket_fdinfo
))) == 0)
2139 *retval
= sizeof(struct socket_fdinfo
);
2143 #pragma unused(so, fp, proc, fd, buffer)
2150 pid_pseminfo(struct psemnode
*psem
, struct fileproc
*fp
, proc_t proc
, int fd
, user_addr_t buffer
, __unused
uint32_t buffersize
, int32_t * retval
)
2152 struct psem_fdinfo pseminfo
;
2155 bzero(&pseminfo
, sizeof(struct psem_fdinfo
));
2156 fill_fileinfo(fp
, proc
, fd
, &pseminfo
.pfi
);
2158 if ((error
= fill_pseminfo(psem
, &pseminfo
.pseminfo
)) == 0) {
2159 if ((error
= copyout(&pseminfo
, buffer
, sizeof(struct psem_fdinfo
))) == 0)
2160 *retval
= sizeof(struct psem_fdinfo
);
2167 pid_pshminfo(struct pshmnode
*pshm
, struct fileproc
*fp
, proc_t proc
, int fd
, user_addr_t buffer
, __unused
uint32_t buffersize
, int32_t * retval
)
2169 struct pshm_fdinfo pshminfo
;
2172 bzero(&pshminfo
, sizeof(struct pshm_fdinfo
));
2173 fill_fileinfo(fp
, proc
, fd
, &pshminfo
.pfi
);
2175 if ((error
= fill_pshminfo(pshm
, &pshminfo
.pshminfo
)) == 0) {
2176 if ((error
= copyout(&pshminfo
, buffer
, sizeof(struct pshm_fdinfo
))) == 0)
2177 *retval
= sizeof(struct pshm_fdinfo
);
2184 pid_pipeinfo(struct pipe
* p
, struct fileproc
*fp
, proc_t proc
, int fd
, user_addr_t buffer
, __unused
uint32_t buffersize
, int32_t * retval
)
2186 struct pipe_fdinfo pipeinfo
;
2189 bzero(&pipeinfo
, sizeof(struct pipe_fdinfo
));
2190 fill_fileinfo(fp
, proc
, fd
, &pipeinfo
.pfi
);
2191 if ((error
= fill_pipeinfo(p
, &pipeinfo
.pipeinfo
)) == 0) {
2192 if ((error
= copyout(&pipeinfo
, buffer
, sizeof(struct pipe_fdinfo
))) == 0)
2193 *retval
= sizeof(struct pipe_fdinfo
);
2200 pid_kqueueinfo(struct kqueue
* kq
, struct fileproc
*fp
, proc_t proc
, int fd
, user_addr_t buffer
, __unused
uint32_t buffersize
, int32_t * retval
)
2202 struct kqueue_fdinfo kqinfo
;
2205 bzero(&kqinfo
, sizeof(struct kqueue_fdinfo
));
2207 /* not all kq's are associated with a file (e.g. workqkq) */
2210 fill_fileinfo(fp
, proc
, fd
, &kqinfo
.pfi
);
2213 if ((error
= fill_kqueueinfo(kq
, &kqinfo
.kqueueinfo
)) == 0) {
2214 if ((error
= copyout(&kqinfo
, buffer
, sizeof(struct kqueue_fdinfo
))) == 0)
2215 *retval
= sizeof(struct kqueue_fdinfo
);
2222 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
)
2228 /************************** proc_pidfdinfo routine ***************************/
2230 proc_pidfdinfo(int pid
, int flavor
, int fd
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
)
2233 int error
= ENOTSUP
;
2234 struct fileproc
* fp
= NULL
;
2238 case PROC_PIDFDVNODEINFO
:
2239 size
= PROC_PIDFDVNODEINFO_SIZE
;
2241 case PROC_PIDFDVNODEPATHINFO
:
2242 size
= PROC_PIDFDVNODEPATHINFO_SIZE
;
2244 case PROC_PIDFDSOCKETINFO
:
2245 size
= PROC_PIDFDSOCKETINFO_SIZE
;
2247 case PROC_PIDFDPSEMINFO
:
2248 size
= PROC_PIDFDPSEMINFO_SIZE
;
2250 case PROC_PIDFDPSHMINFO
:
2251 size
= PROC_PIDFDPSHMINFO_SIZE
;
2253 case PROC_PIDFDPIPEINFO
:
2254 size
= PROC_PIDFDPIPEINFO_SIZE
;
2256 case PROC_PIDFDKQUEUEINFO
:
2257 size
= PROC_PIDFDKQUEUEINFO_SIZE
;
2259 case PROC_PIDFDKQUEUE_EXTINFO
:
2260 size
= PROC_PIDFDKQUEUE_EXTINFO_SIZE
;
2261 if (buffer
== (user_addr_t
)0)
2264 case PROC_PIDFDATALKINFO
:
2265 size
= PROC_PIDFDATALKINFO_SIZE
;
2273 if (buffersize
< size
)
2276 if ((p
= proc_find(pid
)) == PROC_NULL
) {
2281 /* Do we have permission to look into this? */
2282 if ((error
= proc_security_policy(p
, PROC_INFO_CALL_PIDFDINFO
, flavor
, CHECK_SAME_USER
)))
2286 case PROC_PIDFDVNODEINFO
: {
2290 if ((error
= fp_getfvpandvid(p
, fd
, &fp
, &vp
, &vid
)) !=0) {
2293 /* no need to be under the fdlock */
2294 error
= pid_vnodeinfo(vp
, vid
, fp
, p
, fd
, buffer
, buffersize
, retval
);
2298 case PROC_PIDFDVNODEPATHINFO
: {
2302 if ((error
= fp_getfvpandvid(p
, fd
, &fp
, &vp
, &vid
)) !=0) {
2306 /* no need to be under the fdlock */
2307 error
= pid_vnodeinfopath(vp
, vid
, fp
, p
, fd
, buffer
, buffersize
, retval
);
2311 case PROC_PIDFDSOCKETINFO
: {
2314 if ((error
= fp_getfsock(p
, fd
, &fp
, &so
)) !=0) {
2317 /* no need to be under the fdlock */
2318 error
= pid_socketinfo(so
, fp
, p
, fd
, buffer
, buffersize
, retval
);
2322 case PROC_PIDFDPSEMINFO
: {
2323 struct psemnode
* psem
;
2325 if ((error
= fp_getfpsem(p
, fd
, &fp
, &psem
)) !=0) {
2328 /* no need to be under the fdlock */
2329 error
= pid_pseminfo(psem
, fp
, p
, fd
, buffer
, buffersize
, retval
);
2333 case PROC_PIDFDPSHMINFO
: {
2334 struct pshmnode
* pshm
;
2336 if ((error
= fp_getfpshm(p
, fd
, &fp
, &pshm
)) !=0) {
2339 /* no need to be under the fdlock */
2340 error
= pid_pshminfo(pshm
, fp
, p
, fd
, buffer
, buffersize
, retval
);
2344 case PROC_PIDFDPIPEINFO
: {
2345 struct pipe
* cpipe
;
2347 if ((error
= fp_getfpipe(p
, fd
, &fp
, &cpipe
)) !=0) {
2350 /* no need to be under the fdlock */
2351 error
= pid_pipeinfo(cpipe
, fp
, p
, fd
, buffer
, buffersize
, retval
);
2355 case PROC_PIDFDKQUEUEINFO
: {
2359 if ((kq
= p
->p_wqkqueue
) == NULL
) {
2360 /* wqkqueue is initialized on-demand */
2364 } else if ((error
= fp_getfkq(p
, fd
, &fp
, &kq
)) != 0) {
2368 /* no need to be under the fdlock */
2369 error
= pid_kqueueinfo(kq
, fp
, p
, fd
, buffer
, buffersize
, retval
);
2373 case PROC_PIDFDKQUEUE_EXTINFO
: {
2377 if ((kq
= p
->p_wqkqueue
) == NULL
) {
2378 /* wqkqueue is initialized on-demand */
2382 } else if ((error
= fp_getfkq(p
, fd
, &fp
, &kq
)) != 0) {
2385 error
= pid_kqueue_extinfo(p
, kq
, buffer
, buffersize
, retval
);
2396 fp_drop(p
, fd
, fp
, 0);
2405 proc_listfd_kqueue(proc_t p
, int32_t *fdlist
, int len
)
2408 struct fileproc
* fp
;
2412 numfds
= p
->p_fd
->fd_nfiles
;
2418 for (n
= 0; ((n
< numfds
) && (n
< p
->p_fd
->fd_nfiles
)); n
++) {
2419 if (((fp
= p
->p_fd
->fd_ofiles
[n
]) != 0)
2420 && ((p
->p_fd
->fd_ofileflags
[n
] & UF_RESERVED
) == 0)
2421 && (FILEGLOB_DTYPE(fp
->f_fglob
) == PROX_FDTYPE_KQUEUE
)) {
2422 fdlist
[count
++] = n
;
2430 proc_kqueue_udata_info(proc_t p
, int32_t fd
, uint64_t *buffer
, int bufsize
)
2433 struct fileproc
* fp
= NULL
;
2437 /* wqkqueue is initialized on-demand */
2438 if ((kq
= p
->p_wqkqueue
) == NULL
) {
2442 int error
= fp_getfkq(p
, fd
, &fp
, &kq
);
2448 retval
= pid_kqueue_udatainfo(p
, kq
, buffer
, bufsize
);
2450 fp_drop(p
, fd
, fp
, 0);
2457 proc_list_uptrs(proc_t p
, uint64_t *udata_buffer
, int size
)
2459 int32_t *fdlist
= NULL
;
2464 int knote_max
= 4096;
2466 int bufsize
= knote_max
* sizeof(uint64_t);
2468 fdlist
= (int32_t *)kalloc((OPEN_MAX
+ 1) * sizeof(int32_t));
2473 nfds
= proc_listfd_kqueue(p
, &fdlist
[1], OPEN_MAX
);
2474 if (nfds
< 0 || nfds
> OPEN_MAX
) {
2475 kfree(fdlist
, (OPEN_MAX
+ 1) * sizeof(int32_t));
2479 /* Add FD -1, the implicit workq kqueue */
2487 bufsize
= knote_max
* sizeof(uint64_t);
2488 buffer
= (uint64_t *)kalloc(bufsize
);
2491 for (i
= 0; i
< nfds
; i
++) {
2493 ret
= proc_kqueue_udata_info(p
, fdlist
[i
], buffer
, bufsize
);
2494 if (bufsize
!= 0 && ret
> knote_max
) {
2495 kfree(buffer
, bufsize
);
2496 knote_max
= ret
+ 32;
2497 bufsize
= knote_max
* sizeof(uint64_t);
2498 buffer
= kalloc(bufsize
);
2505 /* Copy the udata ptrs */
2506 if (size
>= (int)((count
+ ret
) * sizeof(uint64_t))) {
2507 memcpy(&udata_buffer
[count
], buffer
, ret
* sizeof(uint64_t));
2509 count
= count
+ ret
;
2512 kfree(fdlist
, (OPEN_MAX
+ 1) * sizeof(int32_t));
2514 kfree(buffer
, bufsize
);
2520 * Helper function for proc_pidfileportinfo
2523 struct fileport_info_args
{
2525 user_addr_t fia_buffer
;
2526 uint32_t fia_buffersize
;
2527 int32_t *fia_retval
;
2530 static kern_return_t
2531 proc_fileport_info(__unused mach_port_name_t name
,
2532 struct fileglob
*fg
, void *arg
)
2534 struct fileport_info_args
*fia
= arg
;
2535 struct fileproc __fileproc
, *fp
= &__fileproc
;
2538 bzero(fp
, sizeof (*fp
));
2541 switch (fia
->fia_flavor
) {
2542 case PROC_PIDFILEPORTVNODEPATHINFO
: {
2545 if (FILEGLOB_DTYPE(fg
) != DTYPE_VNODE
) {
2549 vp
= (struct vnode
*)fg
->fg_data
;
2550 error
= pid_vnodeinfopath(vp
, vnode_vid(vp
), fp
, PROC_NULL
, 0,
2551 fia
->fia_buffer
, fia
->fia_buffersize
, fia
->fia_retval
);
2554 case PROC_PIDFILEPORTSOCKETINFO
: {
2557 if (FILEGLOB_DTYPE(fg
) != DTYPE_SOCKET
) {
2561 so
= (socket_t
)fg
->fg_data
;
2562 error
= pid_socketinfo(so
, fp
, PROC_NULL
, 0,
2563 fia
->fia_buffer
, fia
->fia_buffersize
, fia
->fia_retval
);
2566 case PROC_PIDFILEPORTPSHMINFO
: {
2567 struct pshmnode
*pshm
;
2569 if (FILEGLOB_DTYPE(fg
) != DTYPE_PSXSHM
) {
2570 error
= EBADF
; /* ick - mirror fp_getfpshm */
2573 pshm
= (struct pshmnode
*)fg
->fg_data
;
2574 error
= pid_pshminfo(pshm
, fp
, PROC_NULL
, 0,
2575 fia
->fia_buffer
, fia
->fia_buffersize
, fia
->fia_retval
);
2578 case PROC_PIDFILEPORTPIPEINFO
: {
2581 if (FILEGLOB_DTYPE(fg
) != DTYPE_PIPE
) {
2582 error
= EBADF
; /* ick - mirror fp_getfpipe */
2585 cpipe
= (struct pipe
*)fg
->fg_data
;
2586 error
= pid_pipeinfo(cpipe
, fp
, PROC_NULL
, 0,
2587 fia
->fia_buffer
, fia
->fia_buffersize
, fia
->fia_retval
);
2598 /************************* proc_pidfileportinfo routine *********************/
2600 proc_pidfileportinfo(int pid
, int flavor
, mach_port_name_t name
,
2601 user_addr_t buffer
, uint32_t buffersize
, int32_t *retval
)
2604 int error
= ENOTSUP
;
2606 struct fileport_info_args fia
;
2608 /* fileport types are restricted by file_issendable() */
2611 case PROC_PIDFILEPORTVNODEPATHINFO
:
2612 size
= PROC_PIDFILEPORTVNODEPATHINFO_SIZE
;
2614 case PROC_PIDFILEPORTSOCKETINFO
:
2615 size
= PROC_PIDFILEPORTSOCKETINFO_SIZE
;
2617 case PROC_PIDFILEPORTPSHMINFO
:
2618 size
= PROC_PIDFILEPORTPSHMINFO_SIZE
;
2620 case PROC_PIDFILEPORTPIPEINFO
:
2621 size
= PROC_PIDFILEPORTPIPEINFO_SIZE
;
2627 if (buffersize
< size
)
2629 if ((p
= proc_find(pid
)) == PROC_NULL
) {
2634 /* Do we have permission to look into this? */
2635 if ((error
= proc_security_policy(p
, PROC_INFO_CALL_PIDFILEPORTINFO
, flavor
, CHECK_SAME_USER
)))
2638 fia
.fia_flavor
= flavor
;
2639 fia
.fia_buffer
= buffer
;
2640 fia
.fia_buffersize
= buffersize
;
2641 fia
.fia_retval
= retval
;
2643 if (fileport_invoke(p
->task
, name
,
2644 proc_fileport_info
, &fia
, &error
) != KERN_SUCCESS
)
2653 proc_security_policy(proc_t targetp
, __unused
int callnum
, __unused
int flavor
, boolean_t check_same_user
)
2658 if ((error
= mac_proc_check_proc_info(current_proc(), targetp
, callnum
, flavor
)))
2662 /* The 'listpids' call doesn't have a target proc */
2663 if (targetp
== PROC_NULL
) {
2664 assert(callnum
== PROC_INFO_CALL_LISTPIDS
&& check_same_user
== NO_CHECK_SAME_USER
);
2669 * Check for 'get information for processes owned by other users' privilege
2670 * root has this privilege by default
2672 if (priv_check_cred(kauth_cred_get(), PRIV_GLOBAL_PROC_INFO
, 0) == 0)
2673 check_same_user
= FALSE
;
2675 if (check_same_user
) {
2676 kauth_cred_t target_cred
;
2679 target_cred
= kauth_cred_proc_ref(targetp
);
2680 target_uid
= kauth_cred_getuid(target_cred
);
2681 kauth_cred_unref(&target_cred
);
2683 if (kauth_getuid() != target_uid
)
2691 proc_kernmsgbuf(user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
)
2693 if (suser(kauth_cred_get(), (u_short
*)0) == 0) {
2694 return(log_dmesg(buffer
, buffersize
, retval
));
2699 /* ********* process control sets on self only */
2701 proc_setcontrol(int pid
, int flavor
, uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, __unused
int32_t * retval
)
2703 struct proc
* pself
= PROC_NULL
;
2705 uint32_t pcontrol
= (uint32_t)arg
;
2706 struct uthread
*ut
= NULL
;
2707 char name_buf
[MAXTHREADNAMESIZE
];
2709 pself
= current_proc();
2710 if (pid
!= pself
->p_pid
)
2713 /* Do we have permission to look into this? */
2714 if ((error
= proc_security_policy(pself
, PROC_INFO_CALL_SETCONTROL
, flavor
, NO_CHECK_SAME_USER
)))
2718 case PROC_SELFSET_PCONTROL
: {
2719 if (pcontrol
> P_PCMAX
)
2722 /* reset existing control setting while retaining action state */
2723 pself
->p_pcaction
&= PROC_ACTION_MASK
;
2724 /* set new control state */
2725 pself
->p_pcaction
|= pcontrol
;
2730 case PROC_SELFSET_THREADNAME
: {
2732 * This is a bit ugly, as it copies the name into the kernel, and then
2733 * invokes bsd_setthreadname again to copy it into the uthread name
2734 * buffer. Hopefully this isn't such a hot codepath that an additional
2735 * MAXTHREADNAMESIZE copy is a big issue.
2737 if (buffersize
> (MAXTHREADNAMESIZE
- 1)) {
2738 return ENAMETOOLONG
;
2741 ut
= current_uthread();
2743 bzero(name_buf
, MAXTHREADNAMESIZE
);
2744 error
= copyin(buffer
, name_buf
, buffersize
);
2747 bsd_setthreadname(ut
, name_buf
);
2752 case PROC_SELFSET_VMRSRCOWNER
: {
2753 /* need to to be superuser */
2754 if (suser(kauth_cred_get(), (u_short
*)0) != 0) {
2760 /* reset existing control setting while retaining action state */
2761 pself
->p_lflag
|= P_LVMRSRCOWNER
;
2766 case PROC_SELFSET_DELAYIDLESLEEP
: {
2767 /* mark or clear the process property to delay idle sleep disk IO */
2769 OSBitOrAtomic(P_DELAYIDLESLEEP
, &pself
->p_flag
);
2771 OSBitAndAtomic(~((uint32_t)P_DELAYIDLESLEEP
), &pself
->p_flag
);
2783 #if CONFIG_MEMORYSTATUS
2786 proc_dirtycontrol(int pid
, int flavor
, uint64_t arg
, int32_t *retval
) {
2787 struct proc
*target_p
;
2789 uint32_t pcontrol
= (uint32_t)arg
;
2790 kauth_cred_t my_cred
, target_cred
;
2791 boolean_t self
= FALSE
;
2792 boolean_t child
= FALSE
;
2793 boolean_t zombref
= FALSE
;
2796 target_p
= proc_find(pid
);
2798 if (target_p
== PROC_NULL
) {
2799 if (flavor
== PROC_DIRTYCONTROL_GET
) {
2800 target_p
= proc_find_zombref(pid
);
2804 if (target_p
== PROC_NULL
)
2809 my_cred
= kauth_cred_get();
2810 target_cred
= kauth_cred_proc_ref(target_p
);
2812 /* Do we have permission to look into this? */
2813 if ((error
= proc_security_policy(target_p
, PROC_INFO_CALL_DIRTYCONTROL
, flavor
, NO_CHECK_SAME_USER
)))
2816 selfpid
= proc_selfpid();
2817 if (pid
== selfpid
) {
2819 } else if (target_p
->p_ppid
== selfpid
) {
2824 case PROC_DIRTYCONTROL_TRACK
: {
2825 /* Only allow the process itself, its parent, or root */
2826 if ((self
== FALSE
) && (child
== FALSE
) && kauth_cred_issuser(kauth_cred_get()) != TRUE
) {
2831 error
= memorystatus_dirty_track(target_p
, pcontrol
);
2835 case PROC_DIRTYCONTROL_SET
: {
2836 /* Check privileges; use cansignal() here since the process could be terminated */
2837 if (!cansignal(current_proc(), my_cred
, target_p
, SIGKILL
, 0)) {
2842 error
= memorystatus_dirty_set(target_p
, self
, pcontrol
);
2846 case PROC_DIRTYCONTROL_GET
: {
2847 /* No permissions check - dirty state is freely available */
2849 *retval
= memorystatus_dirty_get(target_p
);
2856 case PROC_DIRTYCONTROL_CLEAR
: {
2857 /* Check privileges; use cansignal() here since the process could be terminated */
2858 if (!cansignal(current_proc(), my_cred
, target_p
, SIGKILL
, 0)) {
2863 error
= memorystatus_dirty_clear(target_p
, pcontrol
);
2870 proc_drop_zombref(target_p
);
2872 proc_rele(target_p
);
2874 kauth_cred_unref(&target_cred
);
2881 proc_dirtycontrol(__unused
int pid
, __unused
int flavor
, __unused
uint64_t arg
, __unused
int32_t *retval
) {
2885 #endif /* CONFIG_MEMORYSTATUS */
2888 * proc_terminate() provides support for sudden termination.
2889 * SIGKILL is issued to tracked, clean processes; otherwise,
2894 proc_terminate(int pid
, int32_t *retval
)
2898 kauth_cred_t uc
= kauth_cred_get();
2902 /* XXX: Check if these are necessary */
2903 AUDIT_ARG(pid
, pid
);
2904 AUDIT_ARG(signum
, sig
);
2907 if (pid
<= 0 || retval
== NULL
) {
2911 if ((p
= proc_find(pid
)) == NULL
) {
2916 /* XXX: Check if these are necessary */
2917 AUDIT_ARG(process
, p
);
2920 /* Check privileges; if SIGKILL can be issued, then SIGTERM is also OK */
2921 if (!cansignal(current_proc(), uc
, p
, SIGKILL
, 0)) {
2926 /* Not allowed to sudden terminate yourself */
2927 if (p
== current_proc()) {
2932 #if CONFIG_MEMORYSTATUS
2933 /* Determine requisite signal to issue */
2934 sig
= memorystatus_on_terminate(p
);
2939 proc_set_task_policy(p
->task
, TASK_POLICY_ATTRIBUTE
,
2940 TASK_POLICY_TERMINATED
, TASK_POLICY_ENABLE
);
2952 * copy stat64 structure into vinfo_stat structure.
2955 munge_vinfo_stat(struct stat64
*sbp
, struct vinfo_stat
*vsbp
)
2957 bzero(vsbp
, sizeof(struct vinfo_stat
));
2959 vsbp
->vst_dev
= sbp
->st_dev
;
2960 vsbp
->vst_mode
= sbp
->st_mode
;
2961 vsbp
->vst_nlink
= sbp
->st_nlink
;
2962 vsbp
->vst_ino
= sbp
->st_ino
;
2963 vsbp
->vst_uid
= sbp
->st_uid
;
2964 vsbp
->vst_gid
= sbp
->st_gid
;
2965 vsbp
->vst_atime
= sbp
->st_atimespec
.tv_sec
;
2966 vsbp
->vst_atimensec
= sbp
->st_atimespec
.tv_nsec
;
2967 vsbp
->vst_mtime
= sbp
->st_mtimespec
.tv_sec
;
2968 vsbp
->vst_mtimensec
= sbp
->st_mtimespec
.tv_nsec
;
2969 vsbp
->vst_ctime
= sbp
->st_ctimespec
.tv_sec
;
2970 vsbp
->vst_ctimensec
= sbp
->st_ctimespec
.tv_nsec
;
2971 vsbp
->vst_birthtime
= sbp
->st_birthtimespec
.tv_sec
;
2972 vsbp
->vst_birthtimensec
= sbp
->st_birthtimespec
.tv_nsec
;
2973 vsbp
->vst_size
= sbp
->st_size
;
2974 vsbp
->vst_blocks
= sbp
->st_blocks
;
2975 vsbp
->vst_blksize
= sbp
->st_blksize
;
2976 vsbp
->vst_flags
= sbp
->st_flags
;
2977 vsbp
->vst_gen
= sbp
->st_gen
;
2978 vsbp
->vst_rdev
= sbp
->st_rdev
;
2979 vsbp
->vst_qspare
[0] = sbp
->st_qspare
[0];
2980 vsbp
->vst_qspare
[1] = sbp
->st_qspare
[1];
2984 proc_pid_rusage(int pid
, int flavor
, user_addr_t buffer
, __unused
int32_t *retval
)
2990 if ((p
= proc_find(pid
)) == PROC_NULL
) {
2991 if ((p
= proc_find_zombref(pid
)) == PROC_NULL
) {
2997 /* Do we have permission to look into this? */
2998 if ((error
= proc_security_policy(p
, PROC_INFO_CALL_PIDRUSAGE
, flavor
, CHECK_SAME_USER
)))
3001 error
= proc_get_rusage(p
, flavor
, buffer
, zombie
);
3005 proc_drop_zombref(p
);
3013 proc_archinfo(proc_t p
, struct proc_archinfo
*pai
)
3016 pai
->p_cputype
= p
->p_cputype
;
3017 pai
->p_cpusubtype
= p
->p_cpusubtype
;
3022 proc_pidcoalitioninfo(proc_t p
, struct proc_pidcoalitioninfo
*ppci
)
3024 bzero(ppci
, sizeof(*ppci
));
3025 proc_coalitionids(p
, ppci
->coalition_id
);
3029 proc_pidexitreasoninfo(proc_t p
, struct proc_exitreasoninfo
*peri
, struct proc_exitreasonbasicinfo
*pberi
)
3031 uint32_t reason_data_size
= 0;
3033 pid_t selfpid
= proc_selfpid();
3038 * One (and only one) of peri and pberi must be non-NULL.
3040 assert((peri
!= NULL
) || (pberi
!= NULL
));
3041 assert((peri
== NULL
) || (pberi
== NULL
));
3044 * Allow access to the parent of the exiting
3045 * child or the parent debugger only.
3048 if (p
->p_ppid
== selfpid
)
3049 break; /* parent => ok */
3051 if ((p
->p_lflag
& P_LTRACED
) != 0 &&
3052 (p
->p_oppid
== selfpid
))
3053 break; /* parent-in-waiting => ok */
3059 if (p
->p_exit_reason
== OS_REASON_NULL
) {
3064 if (p
->p_exit_reason
->osr_kcd_buf
!= NULL
) {
3065 reason_data_size
= kcdata_memory_get_used_bytes(&p
->p_exit_reason
->osr_kcd_descriptor
);
3069 peri
->eri_namespace
= p
->p_exit_reason
->osr_namespace
;
3070 peri
->eri_code
= p
->p_exit_reason
->osr_code
;
3071 peri
->eri_flags
= p
->p_exit_reason
->osr_flags
;
3073 if ((peri
->eri_kcd_buf
== 0) || (peri
->eri_reason_buf_size
< reason_data_size
)) {
3078 peri
->eri_reason_buf_size
= reason_data_size
;
3079 if (reason_data_size
!= 0) {
3080 error
= copyout(p
->p_exit_reason
->osr_kcd_buf
, peri
->eri_kcd_buf
, reason_data_size
);
3083 pberi
->beri_namespace
= p
->p_exit_reason
->osr_namespace
;
3084 pberi
->beri_code
= p
->p_exit_reason
->osr_code
;
3085 pberi
->beri_flags
= p
->p_exit_reason
->osr_flags
;
3086 pberi
->beri_reason_buf_size
= reason_data_size
;
3095 * Wrapper to provide NOTE_EXIT_DETAIL and NOTE_EXITSTATUS
3096 * It mimics the data that is typically captured by the
3097 * EVFILT_PROC, NOTE_EXIT event mechanism.
3098 * See filt_proc() in kern_event.c.
3101 proc_pidnoteexit(proc_t p
, uint64_t flags
, uint32_t *data
)
3103 uint32_t exit_data
= 0;
3104 uint32_t exit_flags
= (uint32_t)flags
;
3109 * Allow access to the parent of the exiting
3110 * child or the parent debugger only.
3113 pid_t selfpid
= proc_selfpid();
3115 if (p
->p_ppid
== selfpid
)
3116 break; /* parent => ok */
3118 if ((p
->p_lflag
& P_LTRACED
) != 0 &&
3119 (p
->p_oppid
== selfpid
))
3120 break; /* parent-in-waiting => ok */
3126 if ((exit_flags
& NOTE_EXITSTATUS
) != 0) {
3127 /* The signal and exit status */
3128 exit_data
|= (p
->p_xstat
& NOTE_PDATAMASK
);
3131 if ((exit_flags
& NOTE_EXIT_DETAIL
) != 0) {
3132 /* The exit detail */
3133 if ((p
->p_lflag
& P_LTERM_DECRYPTFAIL
) != 0) {
3134 exit_data
|= NOTE_EXIT_DECRYPTFAIL
;
3137 if ((p
->p_lflag
& P_LTERM_JETSAM
) != 0) {
3138 exit_data
|= NOTE_EXIT_MEMORY
;
3140 switch (p
->p_lflag
& P_JETSAM_MASK
) {
3141 case P_JETSAM_VMPAGESHORTAGE
:
3142 exit_data
|= NOTE_EXIT_MEMORY_VMPAGESHORTAGE
;
3144 case P_JETSAM_VMTHRASHING
:
3145 exit_data
|= NOTE_EXIT_MEMORY_VMTHRASHING
;
3147 case P_JETSAM_FCTHRASHING
:
3148 exit_data
|= NOTE_EXIT_MEMORY_FCTHRASHING
;
3150 case P_JETSAM_VNODE
:
3151 exit_data
|= NOTE_EXIT_MEMORY_VNODE
;
3153 case P_JETSAM_HIWAT
:
3154 exit_data
|= NOTE_EXIT_MEMORY_HIWAT
;
3157 exit_data
|= NOTE_EXIT_MEMORY_PID
;
3159 case P_JETSAM_IDLEEXIT
:
3160 exit_data
|= NOTE_EXIT_MEMORY_IDLE
;
3165 if ((p
->p_csflags
& CS_KILLED
) != 0) {
3166 exit_data
|= NOTE_EXIT_CSERROR
;