2  * Copyright (c) 2005-2020 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> 
  70 #include <mach/vm_types.h> 
  72 #include <sys/mount_internal.h> 
  73 #include <sys/proc_info.h> 
  74 #include <sys/bsdtask_info.h> 
  75 #include <sys/kdebug.h> 
  76 #include <sys/sysproto.h> 
  77 #include <sys/msgbuf.h> 
  80 #include <sys/guarded.h> 
  82 #include <machine/machine_routines.h> 
  84 #include <kern/ipc_misc.h> 
  86 #include <vm/vm_protos.h> 
  88 /* Needed by proc_pidnoteexit(), proc_pidlistuptrs() */ 
  89 #include <sys/event.h> 
  90 #include <sys/codesign.h> 
  92 /* Needed by proc_listcoalitions() */ 
  93 #ifdef CONFIG_COALITIONS 
  94 #include <sys/coalition.h> 
  98 #include <security/mac_framework.h> 
 107 uint64_t get_dispatchqueue_offset_from_proc(void *); 
 108 uint64_t get_dispatchqueue_serialno_offset_from_proc(void *); 
 109 uint64_t get_dispatchqueue_label_offset_from_proc(void *p
); 
 110 uint64_t get_return_to_kernel_offset_from_proc(void *p
); 
 111 int proc_info_internal(int callnum
, int pid
, uint32_t flags
, uint64_t ext_id
, int flavor
, uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
); 
 114  * TODO: Replace the noinline attribute below.  Currently, it serves 
 115  * to avoid stack bloat caused by inlining multiple functions that 
 116  * have large stack footprints; when the functions are independent 
 117  * of each other (will not both be called in any given call to the 
 118  * caller), this only serves to bloat the stack, as we allocate 
 119  * space for both functions, despite the fact that we only need a 
 120  * fraction of that space. 
 122  * Long term, these functions should not be allocating everything on 
 123  * the stack, and should move large allocations (the huge structs 
 124  * that proc info deals in) to the heap, or eliminate them if 
 127  * The functions that most desperately need to improve stack usage 
 128  * (starting with the worst offenders): 
 129  *   proc_pidvnodepathinfo 
 131  *   proc_pidregionpathinfo 
 137  *   proc_pidoriginatorinfo 
 140 /* protos for proc_info calls */ 
 141 static int __attribute__ ((noinline
)) proc_listpids(uint32_t type
, uint32_t tyoneinfo
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
); 
 142 static int __attribute__ ((noinline
)) proc_pidinfo(int pid
, uint32_t flags
, uint64_t ext_id
, int flavor
, uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
); 
 143 static int __attribute__ ((noinline
)) proc_pidfdinfo(int pid
, int flavor
, int fd
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
); 
 144 static int __attribute__ ((noinline
)) proc_kernmsgbuf(user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
); 
 145 static int __attribute__ ((noinline
)) proc_setcontrol(int pid
, int flavor
, uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
); 
 146 static int __attribute__ ((noinline
)) proc_pidfileportinfo(int pid
, int flavor
, mach_port_name_t name
, user_addr_t buffer
, uint32_t buffersize
, int32_t *retval
); 
 147 static int __attribute__ ((noinline
)) proc_dirtycontrol(int pid
, int flavor
, uint64_t arg
, int32_t * retval
); 
 148 static int __attribute__ ((noinline
)) proc_terminate(int pid
, int32_t * retval
); 
 149 static int __attribute__ ((noinline
)) proc_pid_rusage(int pid
, int flavor
, user_addr_t buffer
, int32_t * retval
); 
 150 static int __attribute__ ((noinline
)) proc_pidoriginatorinfo(int pid
, int flavor
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
); 
 151 static int __attribute__ ((noinline
)) proc_listcoalitions(int flavor
, int coaltype
, user_addr_t buffer
, uint32_t buffersize
, int32_t *retval
); 
 152 static int __attribute__ ((noinline
)) proc_can_use_foreground_hw(int pid
, user_addr_t reason
, uint32_t resonsize
, int32_t *retval
); 
 154 /* protos for procpidinfo calls */ 
 155 static int __attribute__ ((noinline
)) proc_pidfdlist(proc_t p
, user_addr_t buffer
, uint32_t buffersize
, int32_t *retval
); 
 156 static int __attribute__ ((noinline
)) proc_pidbsdinfo(proc_t p
, struct proc_bsdinfo 
*pbsd
, int zombie
); 
 157 static int __attribute__ ((noinline
)) proc_pidshortbsdinfo(proc_t p
, struct proc_bsdshortinfo 
*pbsd_shortp
, int zombie
); 
 158 static int __attribute__ ((noinline
)) proc_pidtaskinfo(proc_t p
, struct proc_taskinfo 
*ptinfo
); 
 159 static int __attribute__ ((noinline
)) proc_pidthreadinfo(proc_t p
, uint64_t arg
, bool thuniqueid
, struct proc_threadinfo 
*pthinfo
); 
 160 static int __attribute__ ((noinline
)) proc_pidthreadpathinfo(proc_t p
, uint64_t arg
, struct proc_threadwithpathinfo 
*pinfo
); 
 161 static int __attribute__ ((noinline
)) proc_pidlistthreads(proc_t p
, bool thuniqueid
, user_addr_t buffer
, uint32_t buffersize
, int32_t *retval
); 
 162 static int __attribute__ ((noinline
)) proc_pidregioninfo(proc_t p
, uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, int32_t *retval
); 
 163 static int __attribute__ ((noinline
)) proc_pidregionpathinfo(proc_t p
, uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, int32_t *retval
); 
 164 static int __attribute__ ((noinline
)) proc_pidregionpathinfo2(proc_t p
, uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, int32_t *retval
); 
 165 static int __attribute__ ((noinline
)) proc_pidregionpathinfo3(proc_t p
, uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, int32_t *retval
); 
 166 static int __attribute__ ((noinline
)) proc_pidvnodepathinfo(proc_t p
, uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, int32_t *retval
); 
 167 static int __attribute__ ((noinline
)) proc_pidpathinfo(proc_t p
, uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, int32_t *retval
); 
 168 static int __attribute__ ((noinline
)) proc_pidworkqueueinfo(proc_t p
, struct proc_workqueueinfo 
*pwqinfo
); 
 169 static int __attribute__ ((noinline
)) proc_pidfileportlist(proc_t p
, user_addr_t buffer
, size_t buffersize
, int32_t *retval
); 
 170 extern void __attribute__ ((noinline
)) proc_piduniqidentifierinfo(proc_t p
, struct proc_uniqidentifierinfo 
*p_uniqidinfo
); 
 171 static void __attribute__ ((noinline
)) proc_archinfo(proc_t p
, struct proc_archinfo 
*pai
); 
 172 static void __attribute__ ((noinline
)) proc_pidcoalitioninfo(proc_t p
, struct proc_pidcoalitioninfo 
*pci
); 
 173 static int __attribute__ ((noinline
)) proc_pidnoteexit(proc_t p
, uint64_t arg
, uint32_t *data
); 
 174 static int __attribute__ ((noinline
)) proc_pidexitreasoninfo(proc_t p
, struct proc_exitreasoninfo 
*peri
, struct proc_exitreasonbasicinfo 
*pberi
); 
 175 static int __attribute__ ((noinline
)) proc_pidoriginatorpid_uuid(uuid_t uuid
, uint32_t buffersize
, pid_t 
*pid
); 
 176 static int __attribute__ ((noinline
)) proc_pidlistuptrs(proc_t p
, user_addr_t buffer
, uint32_t buffersize
, int32_t *retval
); 
 177 static int __attribute__ ((noinline
)) proc_piddynkqueueinfo(pid_t pid
, int flavor
, kqueue_id_t id
, user_addr_t buffer
, uint32_t buffersize
, int32_t *retval
); 
 178 static int __attribute__ ((noinline
)) proc_pidregionpath(proc_t p
, uint64_t arg
, user_addr_t buffer
, __unused 
uint32_t buffersize
, int32_t *retval
); 
 179 static int __attribute__ ((noinline
)) proc_pidipctableinfo(proc_t p
, struct proc_ipctableinfo 
*table_info
); 
 181 #if CONFIG_PROC_UDATA_STORAGE 
 182 int __attribute__ ((noinline
)) proc_udata_info(pid_t pid
, int flavor
, user_addr_t buffer
, uint32_t buffersize
, int32_t *retval
); 
 185 /* protos for proc_pidfdinfo calls */ 
 186 static int __attribute__ ((noinline
)) pid_vnodeinfo(vnode_t vp
, struct fileproc 
* fp
, proc_t proc
, int fd
, user_addr_t  buffer
, uint32_t buffersize
, int32_t * retval
); 
 187 static int __attribute__ ((noinline
)) pid_vnodeinfopath(vnode_t vp
, struct fileproc 
* fp
, proc_t proc
, int fd
, user_addr_t  buffer
, uint32_t buffersize
, int32_t * retval
); 
 188 static 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
); 
 189 static 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
); 
 190 static 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
); 
 191 static 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
); 
 192 static 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
); 
 195 /* protos for misc */ 
 197 static int fill_vnodeinfo(vnode_t vp
, struct vnode_info 
*vinfo
, boolean_t check_fsgetpath
); 
 198 static void fill_fileinfo(struct fileproc 
*fp
, proc_t proc
, int fd
, struct proc_fileinfo 
* finfo
); 
 199 static int proc_security_policy(proc_t targetp
, int callnum
, int flavor
, boolean_t check_same_user
); 
 200 static void munge_vinfo_stat(struct stat64 
*sbp
, struct vinfo_stat 
*vsbp
); 
 201 static int proc_piduuidinfo(pid_t pid
, uuid_t uuid_buf
, uint32_t buffersize
); 
 203 extern int proc_pidpathinfo_internal(proc_t p
, __unused 
uint64_t arg
, char *buf
, uint32_t buffersize
, __unused 
int32_t *retval
); 
 204 extern int cansignal(struct proc 
*, kauth_cred_t
, struct proc 
*, int); 
 205 extern int proc_get_rusage(proc_t proc
, int flavor
, user_addr_t buffer
, int is_zombie
); 
 207 #define CHECK_SAME_USER         TRUE 
 208 #define NO_CHECK_SAME_USER      FALSE 
 211 get_dispatchqueue_offset_from_proc(void *p
) 
 214                 proc_t pself 
= (proc_t
)p
; 
 215                 return pself
->p_dispatchqueue_offset
; 
 222 get_dispatchqueue_serialno_offset_from_proc(void *p
) 
 225                 proc_t pself 
= (proc_t
)p
; 
 226                 return pself
->p_dispatchqueue_serialno_offset
; 
 233 get_dispatchqueue_label_offset_from_proc(void *p
) 
 236                 proc_t pself 
= (proc_t
)p
; 
 237                 return pself
->p_dispatchqueue_label_offset
; 
 244 get_return_to_kernel_offset_from_proc(void *p
) 
 247                 proc_t pself 
= (proc_t
)p
; 
 248                 return pself
->p_return_to_kernel_offset
; 
 254 /***************************** proc_info ********************/ 
 257 proc_info(__unused 
struct proc 
*p
, struct proc_info_args 
* uap
, int32_t *retval
) 
 259         return proc_info_internal(uap
->callnum
, uap
->pid
, 0, 0, uap
->flavor
, uap
->arg
, uap
->buffer
, uap
->buffersize
, retval
); 
 263 proc_info_extended_id(__unused 
struct proc 
*p
, struct proc_info_extended_id_args 
*uap
, int32_t *retval
) 
 265         uint32_t flags 
= uap
->flags
; 
 267         if ((flags 
& (PIF_COMPARE_IDVERSION 
| PIF_COMPARE_UNIQUEID
)) == (PIF_COMPARE_IDVERSION 
| PIF_COMPARE_UNIQUEID
)) { 
 271         return proc_info_internal(uap
->callnum
, uap
->pid
, flags
, uap
->ext_id
, uap
->flavor
, uap
->arg
, uap
->buffer
, uap
->buffersize
, retval
); 
 275 proc_info_internal(int callnum
, int pid
, uint32_t flags
, uint64_t ext_id
, int flavor
, uint64_t arg
, user_addr_t buffer
, uint32_t  buffersize
, int32_t * retval
) 
 278         case PROC_INFO_CALL_LISTPIDS
: 
 279                 /* pid contains type and flavor contains typeinfo */ 
 280                 return proc_listpids(pid
, flavor
, buffer
, buffersize
, retval
); 
 281         case PROC_INFO_CALL_PIDINFO
: 
 282                 return proc_pidinfo(pid
, flags
, ext_id
, flavor
, arg
, buffer
, buffersize
, retval
); 
 283         case PROC_INFO_CALL_PIDFDINFO
: 
 284                 return proc_pidfdinfo(pid
, flavor
, (int)arg
, buffer
, buffersize
, retval
); 
 285         case PROC_INFO_CALL_KERNMSGBUF
: 
 286                 return proc_kernmsgbuf(buffer
, buffersize
, retval
); 
 287         case PROC_INFO_CALL_SETCONTROL
: 
 288                 return proc_setcontrol(pid
, flavor
, arg
, buffer
, buffersize
, retval
); 
 289         case PROC_INFO_CALL_PIDFILEPORTINFO
: 
 290                 return proc_pidfileportinfo(pid
, flavor
, (mach_port_name_t
)arg
, buffer
, buffersize
, retval
); 
 291         case PROC_INFO_CALL_TERMINATE
: 
 292                 return proc_terminate(pid
, retval
); 
 293         case PROC_INFO_CALL_DIRTYCONTROL
: 
 294                 return proc_dirtycontrol(pid
, flavor
, arg
, retval
); 
 295         case PROC_INFO_CALL_PIDRUSAGE
: 
 296                 return proc_pid_rusage(pid
, flavor
, buffer
, retval
); 
 297         case PROC_INFO_CALL_PIDORIGINATORINFO
: 
 298                 return proc_pidoriginatorinfo(pid
, flavor
, buffer
, buffersize
, retval
); 
 299         case PROC_INFO_CALL_LISTCOALITIONS
: 
 300                 return proc_listcoalitions(pid 
/* flavor */, flavor 
/* coaltype */, buffer
, 
 302         case PROC_INFO_CALL_CANUSEFGHW
: 
 303                 return proc_can_use_foreground_hw(pid
, buffer
, buffersize
, retval
); 
 304         case PROC_INFO_CALL_PIDDYNKQUEUEINFO
: 
 305                 return proc_piddynkqueueinfo(pid
, flavor
, (kqueue_id_t
)arg
, buffer
, buffersize
, retval
); 
 306 #if CONFIG_PROC_UDATA_STORAGE 
 307         case PROC_INFO_CALL_UDATA_INFO
: 
 308                 return proc_udata_info(pid
, flavor
, buffer
, buffersize
, retval
); 
 309 #endif /* CONFIG_PROC_UDATA_STORAGE */ 
 317 /******************* proc_listpids routine ****************/ 
 319 proc_listpids(uint32_t type
, uint32_t typeinfo
, user_addr_t buffer
, uint32_t  buffersize
, int32_t * retval
) 
 321         uint32_t numprocs 
= 0; 
 330         struct proclist 
*current_list
; 
 332         /* Do we have permission to look into this? */ 
 333         if ((error 
= proc_security_policy(PROC_NULL
, PROC_INFO_CALL_LISTPIDS
, type
, NO_CHECK_SAME_USER
))) { 
 337         /* if the buffer is null, return num of procs */ 
 338         if (buffer 
== (user_addr_t
)0) { 
 339                 *retval 
= ((nprocs 
+ 20) * sizeof(int)); 
 343         if (buffersize 
< sizeof(int)) { 
 346         wantpids 
= buffersize 
/ sizeof(int); 
 347         if ((nprocs 
+ 20) > 0) { 
 348                 numprocs 
= (uint32_t)(nprocs 
+ 20); 
 350         if (numprocs 
> wantpids
) { 
 354         kbuf 
= kheap_alloc(KHEAP_TEMP
, numprocs 
* sizeof(int), 
 364         current_list 
= &allproc
; 
 366         LIST_FOREACH(p
, current_list
, p_list
) { 
 370                         if (p
->p_pgrpid 
!= (pid_t
)typeinfo
) { 
 375                         if ((p
->p_ppid 
!= (pid_t
)typeinfo
) && (((p
->p_lflag 
& P_LTRACED
) == 0) || (p
->p_oppid 
!= (pid_t
)typeinfo
))) { 
 384                         /* racy but list lock is held */ 
 385                         if ((p
->p_flag 
& P_CONTROLT
) == 0 || 
 386                             (p
->p_pgrp 
== NULL
) || (p
->p_pgrp
->pg_session 
== NULL
) || 
 387                             (tp 
= SESSION_TP(p
->p_pgrp
->pg_session
)) == TTY_NULL 
|| 
 388                             tp
->t_dev 
!= (dev_t
)typeinfo
) { 
 393                         if (p
->p_ucred 
== NULL
) { 
 396                                 kauth_cred_t my_cred
; 
 399                                 my_cred 
= kauth_cred_proc_ref(p
); 
 400                                 uid 
= kauth_cred_getuid(my_cred
); 
 401                                 kauth_cred_unref(&my_cred
); 
 402                                 if (uid 
!= (uid_t
)typeinfo
) { 
 408                         if (p
->p_ucred 
== NULL
) { 
 411                                 kauth_cred_t my_cred
; 
 414                                 my_cred 
= kauth_cred_proc_ref(p
); 
 415                                 uid 
= kauth_cred_getruid(my_cred
); 
 416                                 kauth_cred_unref(&my_cred
); 
 417                                 if (uid 
!= (uid_t
)typeinfo
) { 
 423                         if (p
->p_kdebug 
== 0) { 
 442         if ((n 
< numprocs
) && (current_list 
== &allproc
)) { 
 443                 current_list 
= &zombproc
; 
 450         error 
= copyout((caddr_t
)ptr
, buffer
, n 
* sizeof(int)); 
 452                 *retval 
= (n 
* sizeof(int)); 
 454         kheap_free(KHEAP_TEMP
, kbuf
, numprocs 
* sizeof(int)); 
 460 /********************************** proc_pidfdlist routines ********************************/ 
 463 proc_fdlist_internal(proc_t p
, struct proc_fdinfo 
*pfd
, size_t numfds
) 
 471                 if (count 
>= numfds
) { 
 474                 file_type_t fdtype 
= FILEGLOB_DTYPE(fp
->fp_glob
); 
 475                 pfd
[count
].proc_fd 
= fdt_foreach_fd(); 
 476                 pfd
[count
].proc_fdtype 
= (fdtype 
!= DTYPE_ATALK
) ? 
 477                     fdtype 
: PROX_FDTYPE_ATALK
; 
 486 proc_pidfdlist(proc_t p
, user_addr_t buffer
, uint32_t  buffersize
, int32_t *retval
) 
 494         if (p
->p_fd
->fd_nfiles 
> 0) { 
 495                 numfds 
= (uint32_t)p
->p_fd
->fd_nfiles
; 
 498         if (buffer 
== (user_addr_t
) 0) { 
 500                 *retval 
= (numfds 
* sizeof(struct proc_fdinfo
)); 
 504         /* buffersize is big enough atleast for one struct */ 
 505         needfds 
= buffersize 
/ sizeof(struct proc_fdinfo
); 
 507         if (numfds 
> needfds
) { 
 511         kbuf 
= kheap_alloc(KHEAP_TEMP
, numfds 
* sizeof(struct proc_fdinfo
), 
 517         /* cannot overflow due to count <= numfds */ 
 518         count 
= (uint32_t)proc_fdlist_internal(p
, (struct proc_fdinfo 
*)kbuf
, (size_t)numfds
); 
 520         error 
= copyout(kbuf
, buffer
, count 
* sizeof(struct proc_fdinfo
)); 
 521         kheap_free(KHEAP_TEMP
, kbuf
, numfds 
* sizeof(struct proc_fdinfo
)); 
 523                 *retval 
= count 
* sizeof(struct proc_fdinfo
); 
 529  * KPI variant of proc_pidfdlist. 
 531  * Caller is responsible for adding margin to *count when calling this in 
 532  * circumstances where file descriptors can appear/disappear between the 
 533  * two calls to this function. 
 536 proc_fdlist(proc_t p
, struct proc_fdinfo 
*buf
, size_t *count
) 
 538         if (p 
== NULL 
|| count 
== NULL
) { 
 544                 *count 
= (size_t)max(min(p
->p_fd
->fd_lastfile 
+ 1, p
->p_fd
->fd_nfiles
), 0); 
 549         *count 
= proc_fdlist_internal(p
, buf
, *count
); 
 554  * Helper functions for proc_pidfileportlist. 
 557 proc_fileport_count(__unused mach_port_name_t name
, 
 558     __unused 
struct fileglob 
*fg
, void *arg
) 
 560         size_t *counter 
= arg
; 
 566 struct fileport_fdtype_args 
{ 
 567         struct proc_fileportinfo 
*ffa_pfi
; 
 568         struct proc_fileportinfo 
*ffa_pfi_end
; 
 572 proc_fileport_fdtype(mach_port_name_t name
, struct fileglob 
*fg
, void *arg
) 
 574         struct fileport_fdtype_args 
*ffa 
= arg
; 
 576         if (ffa
->ffa_pfi 
!= ffa
->ffa_pfi_end
) { 
 577                 file_type_t fdtype 
= FILEGLOB_DTYPE(fg
); 
 579                 ffa
->ffa_pfi
->proc_fdtype 
= (fdtype 
!= DTYPE_ATALK
) ? 
 580                     fdtype 
: PROX_FDTYPE_ATALK
; 
 581                 ffa
->ffa_pfi
->proc_fileport 
= name
; 
 583                 return 0;             /* keep walking */ 
 585                 return -1;            /* stop the walk! */ 
 590 proc_pidfileportlist(proc_t p
, 
 591     user_addr_t buffer
, size_t buffersize
, int32_t *retval
) 
 595         struct proc_fileportinfo 
*pfi
; 
 596         size_t needfileports
, numfileports
; 
 597         struct fileport_fdtype_args ffa
; 
 600         needfileports 
= buffersize 
/ sizeof(*pfi
); 
 601         if ((user_addr_t
)0 == buffer 
|| needfileports 
> (size_t)maxfilesperproc
) { 
 603                  * Either (i) the user is asking for a fileport count, 
 604                  * or (ii) the number of fileports they're asking for is 
 605                  * larger than the maximum number of open files (!); count 
 606                  * them to bound subsequent heap allocations. 
 609                 switch (fileport_walk(p
->task
, 
 610                     proc_fileport_count
, &numfileports
)) { 
 613                 case KERN_RESOURCE_SHORTAGE
: 
 615                 case KERN_INVALID_TASK
: 
 621                 if (numfileports 
== 0) { 
 622                         *retval 
= 0;            /* none at all, bail */ 
 625                 if ((user_addr_t
)0 == buffer
) { 
 626                         numfileports 
+= 20;     /* accelerate convergence */ 
 627                         *retval 
= (int32_t)MIN(numfileports 
* sizeof(*pfi
), INT32_MAX
); 
 630                 if (needfileports 
> numfileports
) { 
 631                         needfileports 
= numfileports
; 
 635         assert(buffersize 
>= PROC_PIDLISTFILEPORTS_SIZE
); 
 637         kbufsize 
= needfileports 
* sizeof(*pfi
); 
 638         pfi 
= kbuf 
= kheap_alloc(KHEAP_TEMP
, kbufsize
, Z_WAITOK 
| Z_ZERO
); 
 644         ffa
.ffa_pfi_end 
= pfi 
+ needfileports
; 
 646         switch (fileport_walk(p
->task
, proc_fileport_fdtype
, &ffa
)) { 
 650                 if ((numfileports 
= (size_t)(pfi 
- (typeof(pfi
))kbuf
)) == 0) { 
 653                 if (numfileports 
> needfileports
) { 
 654                         panic("more fileports returned than requested"); 
 656                 error 
= copyout(kbuf
, buffer
, numfileports 
* sizeof(*pfi
)); 
 658         case KERN_RESOURCE_SHORTAGE
: 
 661         case KERN_INVALID_TASK
: 
 668         kheap_free(KHEAP_TEMP
, kbuf
, kbufsize
); 
 670                 *retval 
= (int32_t)MIN(numfileports 
* sizeof(*pfi
), INT32_MAX
); 
 676 proc_pidbsdinfo(proc_t p
, struct proc_bsdinfo 
* pbsd
, int zombie
) 
 679         struct  session 
*sessionp 
= NULL
; 
 681         kauth_cred_t my_cred
; 
 684         sessionp 
= proc_session(p
); 
 686         my_cred 
= kauth_cred_proc_ref(p
); 
 687         bzero(pbsd
, sizeof(struct proc_bsdinfo
)); 
 688         pbsd
->pbi_status 
= p
->p_stat
; 
 689         pbsd
->pbi_xstatus 
= p
->p_xstat
; 
 690         pbsd
->pbi_pid 
= p
->p_pid
; 
 691         pbsd
->pbi_ppid 
= p
->p_ppid
; 
 692         pbsd
->pbi_uid 
= kauth_cred_getuid(my_cred
); 
 693         pbsd
->pbi_gid 
= kauth_cred_getgid(my_cred
); 
 694         pbsd
->pbi_ruid 
=  kauth_cred_getruid(my_cred
); 
 695         pbsd
->pbi_rgid 
= kauth_cred_getrgid(my_cred
); 
 696         pbsd
->pbi_svuid 
=  kauth_cred_getsvuid(my_cred
); 
 697         pbsd
->pbi_svgid 
= kauth_cred_getsvgid(my_cred
); 
 698         kauth_cred_unref(&my_cred
); 
 700         pbsd
->pbi_nice 
= p
->p_nice
; 
 701         pbsd
->pbi_start_tvsec 
= p
->p_start
.tv_sec
; 
 702         pbsd
->pbi_start_tvusec 
= p
->p_start
.tv_usec
; 
 703         bcopy(&p
->p_comm
, &pbsd
->pbi_comm
[0], MAXCOMLEN
); 
 704         pbsd
->pbi_comm
[MAXCOMLEN 
- 1] = '\0'; 
 705         bcopy(&p
->p_name
, &pbsd
->pbi_name
[0], 2 * MAXCOMLEN
); 
 706         pbsd
->pbi_name
[(2 * MAXCOMLEN
) - 1] = '\0'; 
 709         if ((p
->p_flag 
& P_SYSTEM
) == P_SYSTEM
) { 
 710                 pbsd
->pbi_flags 
|= PROC_FLAG_SYSTEM
; 
 712         if ((p
->p_lflag 
& P_LTRACED
) == P_LTRACED
) { 
 713                 pbsd
->pbi_flags 
|= PROC_FLAG_TRACED
; 
 715         if ((p
->p_lflag 
& P_LEXIT
) == P_LEXIT
) { 
 716                 pbsd
->pbi_flags 
|= PROC_FLAG_INEXIT
; 
 718         if ((p
->p_lflag 
& P_LPPWAIT
) == P_LPPWAIT
) { 
 719                 pbsd
->pbi_flags 
|= PROC_FLAG_PPWAIT
; 
 721         if ((p
->p_flag 
& P_LP64
) == P_LP64
) { 
 722                 pbsd
->pbi_flags 
|= PROC_FLAG_LP64
; 
 724         if ((p
->p_flag 
& P_CONTROLT
) == P_CONTROLT
) { 
 725                 pbsd
->pbi_flags 
|= PROC_FLAG_CONTROLT
; 
 727         if ((p
->p_flag 
& P_THCWD
) == P_THCWD
) { 
 728                 pbsd
->pbi_flags 
|= PROC_FLAG_THCWD
; 
 730         if ((p
->p_flag 
& P_SUGID
) == P_SUGID
) { 
 731                 pbsd
->pbi_flags 
|= PROC_FLAG_PSUGID
; 
 733         if ((p
->p_flag 
& P_EXEC
) == P_EXEC
) { 
 734                 pbsd
->pbi_flags 
|= PROC_FLAG_EXEC
; 
 737         if (sessionp 
!= SESSION_NULL
) { 
 738                 if (SESS_LEADER(p
, sessionp
)) { 
 739                         pbsd
->pbi_flags 
|= PROC_FLAG_SLEADER
; 
 741                 if (sessionp
->s_ttyvp
) { 
 742                         pbsd
->pbi_flags 
|= PROC_FLAG_CTTY
; 
 746 #if CONFIG_DELAY_IDLE_SLEEP 
 747         if ((p
->p_flag 
& P_DELAYIDLESLEEP
) == P_DELAYIDLESLEEP
) { 
 748                 pbsd
->pbi_flags 
|= PROC_FLAG_DELAYIDLESLEEP
; 
 750 #endif /* CONFIG_DELAY_IDLE_SLEEP */ 
 752         switch (PROC_CONTROL_STATE(p
)) { 
 754                 pbsd
->pbi_flags 
|= PROC_FLAG_PC_THROTTLE
; 
 757                 pbsd
->pbi_flags 
|= PROC_FLAG_PC_SUSP
; 
 760                 pbsd
->pbi_flags 
|= PROC_FLAG_PC_KILL
; 
 765         switch (PROC_ACTION_STATE(p
)) { 
 767                 pbsd
->pbi_flags 
|= PROC_FLAG_PA_THROTTLE
; 
 770                 pbsd
->pbi_flags 
|= PROC_FLAG_PA_SUSP
; 
 775         /* if process is a zombie skip bg state */ 
 776         if ((zombie 
== 0) && (p
->p_stat 
!= SZOMB
) && (p
->task 
!= TASK_NULL
)) { 
 777                 proc_get_darwinbgstate(p
->task
, &pbsd
->pbi_flags
); 
 781                 pbsd
->pbi_nfiles 
= p
->p_fd
->fd_nfiles
; 
 784         pbsd
->e_tdev 
= NODEV
; 
 785         if (pg 
!= PGRP_NULL
) { 
 786                 pbsd
->pbi_pgid 
= p
->p_pgrpid
; 
 787                 pbsd
->pbi_pjobc 
= pg
->pg_jobc
; 
 788                 if ((p
->p_flag 
& P_CONTROLT
) && (sessionp 
!= SESSION_NULL
) && (tp 
= SESSION_TP(sessionp
))) { 
 789                         pbsd
->e_tdev 
= tp
->t_dev
; 
 790                         pbsd
->e_tpgid 
= sessionp
->s_ttypgrpid
; 
 793         if (sessionp 
!= SESSION_NULL
) { 
 794                 session_rele(sessionp
); 
 796         if (pg 
!= PGRP_NULL
) { 
 805 proc_pidshortbsdinfo(proc_t p
, struct proc_bsdshortinfo 
* pbsd_shortp
, int zombie
) 
 807         bzero(pbsd_shortp
, sizeof(struct proc_bsdshortinfo
)); 
 808         pbsd_shortp
->pbsi_pid 
= p
->p_pid
; 
 809         pbsd_shortp
->pbsi_ppid 
= p
->p_ppid
; 
 810         pbsd_shortp
->pbsi_pgid 
= p
->p_pgrpid
; 
 811         pbsd_shortp
->pbsi_status 
= p
->p_stat
; 
 812         bcopy(&p
->p_comm
, &pbsd_shortp
->pbsi_comm
[0], MAXCOMLEN
); 
 813         pbsd_shortp
->pbsi_comm
[MAXCOMLEN 
- 1] = '\0'; 
 815         pbsd_shortp
->pbsi_flags 
= 0; 
 816         if ((p
->p_flag 
& P_SYSTEM
) == P_SYSTEM
) { 
 817                 pbsd_shortp
->pbsi_flags 
|= PROC_FLAG_SYSTEM
; 
 819         if ((p
->p_lflag 
& P_LTRACED
) == P_LTRACED
) { 
 820                 pbsd_shortp
->pbsi_flags 
|= PROC_FLAG_TRACED
; 
 822         if ((p
->p_lflag 
& P_LEXIT
) == P_LEXIT
) { 
 823                 pbsd_shortp
->pbsi_flags 
|= PROC_FLAG_INEXIT
; 
 825         if ((p
->p_lflag 
& P_LPPWAIT
) == P_LPPWAIT
) { 
 826                 pbsd_shortp
->pbsi_flags 
|= PROC_FLAG_PPWAIT
; 
 828         if ((p
->p_flag 
& P_LP64
) == P_LP64
) { 
 829                 pbsd_shortp
->pbsi_flags 
|= PROC_FLAG_LP64
; 
 831         if ((p
->p_flag 
& P_CONTROLT
) == P_CONTROLT
) { 
 832                 pbsd_shortp
->pbsi_flags 
|= PROC_FLAG_CONTROLT
; 
 834         if ((p
->p_flag 
& P_THCWD
) == P_THCWD
) { 
 835                 pbsd_shortp
->pbsi_flags 
|= PROC_FLAG_THCWD
; 
 837         if ((p
->p_flag 
& P_SUGID
) == P_SUGID
) { 
 838                 pbsd_shortp
->pbsi_flags 
|= PROC_FLAG_PSUGID
; 
 840         if ((p
->p_flag 
& P_EXEC
) == P_EXEC
) { 
 841                 pbsd_shortp
->pbsi_flags 
|= PROC_FLAG_EXEC
; 
 843 #if CONFIG_DELAY_IDLE_SLEEP 
 844         if ((p
->p_flag 
& P_DELAYIDLESLEEP
) == P_DELAYIDLESLEEP
) { 
 845                 pbsd_shortp
->pbsi_flags 
|= PROC_FLAG_DELAYIDLESLEEP
; 
 847 #endif /* CONFIG_DELAY_IDLE_SLEEP */ 
 849         switch (PROC_CONTROL_STATE(p
)) { 
 851                 pbsd_shortp
->pbsi_flags 
|= PROC_FLAG_PC_THROTTLE
; 
 854                 pbsd_shortp
->pbsi_flags 
|= PROC_FLAG_PC_SUSP
; 
 857                 pbsd_shortp
->pbsi_flags 
|= PROC_FLAG_PC_KILL
; 
 862         switch (PROC_ACTION_STATE(p
)) { 
 864                 pbsd_shortp
->pbsi_flags 
|= PROC_FLAG_PA_THROTTLE
; 
 867                 pbsd_shortp
->pbsi_flags 
|= PROC_FLAG_PA_SUSP
; 
 872         /* if process is a zombie skip bg state */ 
 873         if ((zombie 
== 0) && (p
->p_stat 
!= SZOMB
) && (p
->task 
!= TASK_NULL
)) { 
 874                 proc_get_darwinbgstate(p
->task
, &pbsd_shortp
->pbsi_flags
); 
 877         pbsd_shortp
->pbsi_uid 
= p
->p_uid
; 
 878         pbsd_shortp
->pbsi_gid 
= p
->p_gid
; 
 879         pbsd_shortp
->pbsi_ruid 
=  p
->p_ruid
; 
 880         pbsd_shortp
->pbsi_rgid 
= p
->p_rgid
; 
 881         pbsd_shortp
->pbsi_svuid 
=  p
->p_svuid
; 
 882         pbsd_shortp
->pbsi_svgid 
= p
->p_svgid
; 
 888 proc_pidtaskinfo(proc_t p
, struct proc_taskinfo 
* ptinfo
) 
 894         bzero(ptinfo
, sizeof(struct proc_taskinfo
)); 
 895         fill_taskprocinfo(task
, (struct proc_taskinfo_internal 
*)ptinfo
); 
 903 proc_pidthreadinfo(proc_t p
, uint64_t arg
, bool thuniqueid
, struct proc_threadinfo 
*pthinfo
) 
 906         uint64_t threadaddr 
= (uint64_t)arg
; 
 908         bzero(pthinfo
, sizeof(struct proc_threadinfo
)); 
 910         error 
= fill_taskthreadinfo(p
->task
, threadaddr
, thuniqueid
, (struct proc_threadinfo_internal 
*)pthinfo
, NULL
, NULL
); 
 919 bsd_hasthreadname(void *uth
) 
 921         struct uthread 
*ut 
= (struct uthread
*)uth
; 
 923         /* This doesn't check for the empty string; do we care? */ 
 932 bsd_getthreadname(void *uth
, char *buffer
) 
 934         struct uthread 
*ut 
= (struct uthread 
*)uth
; 
 936                 bcopy(ut
->pth_name
, buffer
, MAXTHREADNAMESIZE
); 
 943  * This is known to race with regards to the contents of the thread name; concurrent 
 944  * callers may result in a garbled name. 
 947 bsd_setthreadname(void *uth
, const char *name
) 
 949         struct uthread 
*ut 
= (struct uthread 
*)uth
; 
 950         char * name_buf 
= NULL
; 
 953                 /* If there is no existing thread name, allocate a buffer for one. */ 
 954                 name_buf 
= kalloc(MAXTHREADNAMESIZE
); 
 956                 bzero(name_buf
, MAXTHREADNAMESIZE
); 
 958                 /* Someone could conceivably have named the thread at the same time we did. */ 
 959                 if (!OSCompareAndSwapPtr(NULL
, name_buf
, &ut
->pth_name
)) { 
 960                         kfree(name_buf
, MAXTHREADNAMESIZE
); 
 963                 kernel_debug_string_simple(TRACE_STRING_THREADNAME_PREV
, ut
->pth_name
); 
 966         strncpy(ut
->pth_name
, name
, MAXTHREADNAMESIZE 
- 1); 
 967         kernel_debug_string_simple(TRACE_STRING_THREADNAME
, ut
->pth_name
); 
 971 bsd_copythreadname(void *dst_uth
, void *src_uth
) 
 973         struct uthread 
*dst_ut 
= (struct uthread 
*)dst_uth
; 
 974         struct uthread 
*src_ut 
= (struct uthread 
*)src_uth
; 
 976         if (src_ut
->pth_name 
== NULL
) { 
 980         if (dst_ut
->pth_name 
== NULL
) { 
 981                 dst_ut
->pth_name 
= (char *)kalloc(MAXTHREADNAMESIZE
); 
 982                 if (dst_ut
->pth_name 
== NULL
) { 
 987         bcopy(src_ut
->pth_name
, dst_ut
->pth_name
, MAXTHREADNAMESIZE
); 
 992 bsd_threadcdir(void * uth
, void *vptr
, int *vidp
) 
 994         struct uthread 
* ut 
= (struct uthread 
*)uth
; 
 996         vnode_t 
*vpp 
= (vnode_t 
*)vptr
; 
1011 proc_pidthreadpathinfo(proc_t p
, uint64_t arg
, struct proc_threadwithpathinfo 
*pinfo
) 
1013         vnode_t vp 
= NULLVP
; 
1016         uint64_t threadaddr 
= (uint64_t)arg
; 
1019         bzero(pinfo
, sizeof(struct proc_threadwithpathinfo
)); 
1021         error 
= fill_taskthreadinfo(p
->task
, threadaddr
, 0, (struct proc_threadinfo_internal 
*)&pinfo
->pt
, (void *)&vp
, &vid
); 
1026         if ((vp 
!= NULLVP
) && ((vnode_getwithvid(vp
, vid
)) == 0)) { 
1027                 error 
= fill_vnodeinfo(vp
, &pinfo
->pvip
.vip_vi
, FALSE
); 
1030                         vn_getpath(vp
, &pinfo
->pvip
.vip_path
[0], &count
); 
1031                         pinfo
->pvip
.vip_path
[MAXPATHLEN 
- 1] = 0; 
1041 proc_pidlistthreads(proc_t p
, bool thuniqueid
, user_addr_t buffer
, uint32_t  buffersize
, int32_t *retval
) 
1047         uint32_t numthreads 
= 0; 
1049         int num 
= get_numthreads(p
->task
) + 10; 
1051                 numthreads 
= (uint32_t)num
; 
1054         count 
= buffersize 
/ (sizeof(uint64_t)); 
1056         if (numthreads 
> count
) { 
1060         kbuf 
= kheap_alloc(KHEAP_TEMP
, 
1061             numthreads 
* sizeof(uint64_t), Z_WAITOK 
| Z_ZERO
); 
1066         ret 
= fill_taskthreadlist(p
->task
, kbuf
, numthreads
, thuniqueid
); 
1068         error 
= copyout(kbuf
, buffer
, ret
); 
1069         kheap_free(KHEAP_TEMP
, kbuf
, numthreads 
* sizeof(uint64_t)); 
1078 proc_pidregioninfo(proc_t p
, uint64_t arg
, user_addr_t buffer
, __unused 
uint32_t  buffersize
, int32_t *retval
) 
1080         struct proc_regioninfo preginfo
; 
1083         bzero(&preginfo
, sizeof(struct proc_regioninfo
)); 
1084         ret 
= fill_procregioninfo( p
->task
, arg
, (struct proc_regioninfo_internal 
*)&preginfo
, (uintptr_t *)0, (uint32_t *)0); 
1088         error 
= copyout(&preginfo
, buffer
, sizeof(struct proc_regioninfo
)); 
1090                 *retval 
= sizeof(struct proc_regioninfo
); 
1097 proc_pidregionpathinfo(proc_t p
, uint64_t arg
, user_addr_t buffer
, __unused 
uint32_t  buffersize
, int32_t *retval
) 
1099         struct proc_regionwithpathinfo preginfo
; 
1101         uintptr_t vnodeaddr 
= 0; 
1102         uint32_t vnodeid 
= 0; 
1106         bzero(&preginfo
, sizeof(struct proc_regionwithpathinfo
)); 
1108         ret 
= fill_procregioninfo( p
->task
, arg
, (struct proc_regioninfo_internal 
*)&preginfo
.prp_prinfo
, (uintptr_t *)&vnodeaddr
, (uint32_t *)&vnodeid
); 
1113                 vp 
= (vnode_t
)vnodeaddr
; 
1114                 if ((vnode_getwithvid(vp
, vnodeid
)) == 0) { 
1115                         /* FILL THE VNODEINFO */ 
1116                         error 
= fill_vnodeinfo(vp
, &preginfo
.prp_vip
.vip_vi
, FALSE
); 
1118                         vn_getpath(vp
, &preginfo
.prp_vip
.vip_path
[0], &count
); 
1119                         /* Always make sure it is null terminated */ 
1120                         preginfo
.prp_vip
.vip_path
[MAXPATHLEN 
- 1] = 0; 
1124         error 
= copyout(&preginfo
, buffer
, sizeof(struct proc_regionwithpathinfo
)); 
1126                 *retval 
= sizeof(struct proc_regionwithpathinfo
); 
1132 proc_pidregionpathinfo2(proc_t p
, uint64_t arg
, user_addr_t buffer
, __unused 
uint32_t buffersize
, int32_t *retval
) 
1134         struct proc_regionwithpathinfo preginfo
; 
1136         uintptr_t vnodeaddr 
= 0; 
1137         uint32_t vnodeid 
= 0; 
1141         bzero(&preginfo
, sizeof(struct proc_regionwithpathinfo
)); 
1143         ret 
= fill_procregioninfo_onlymappedvnodes( p
->task
, arg
, (struct proc_regioninfo_internal 
*)&preginfo
.prp_prinfo
, (uintptr_t *)&vnodeaddr
, (uint32_t *)&vnodeid
); 
1151         vp 
= (vnode_t
)vnodeaddr
; 
1152         if ((vnode_getwithvid(vp
, vnodeid
)) == 0) { 
1153                 /* FILL THE VNODEINFO */ 
1154                 error 
= fill_vnodeinfo(vp
, &preginfo
.prp_vip
.vip_vi
, FALSE
); 
1156                 vn_getpath(vp
, &preginfo
.prp_vip
.vip_path
[0], &count
); 
1157                 /* Always make sure it is null terminated */ 
1158                 preginfo
.prp_vip
.vip_path
[MAXPATHLEN 
- 1] = 0; 
1164         error 
= copyout(&preginfo
, buffer
, sizeof(struct proc_regionwithpathinfo
)); 
1166                 *retval 
= sizeof(struct proc_regionwithpathinfo
); 
1172 proc_pidregionpath(proc_t p
, uint64_t arg
, user_addr_t buffer
, __unused 
uint32_t buffersize
, int32_t *retval
) 
1174         struct proc_regionpath path 
= {}; 
1176         uintptr_t vnodeaddr 
= 0; 
1177         uint32_t vnodeid 
= 0; 
1180         ret 
= find_region_details(p
->task
, (vm_map_offset_t
) arg
, 
1181             (uintptr_t *)&vnodeaddr
, (uint32_t *)&vnodeid
, 
1182             &path
.prpo_addr
, &path
.prpo_regionlength
); 
1190         vp 
= (vnode_t
)vnodeaddr
; 
1191         if ((vnode_getwithvid(vp
, vnodeid
)) == 0) { 
1192                 int count 
= MAXPATHLEN
; 
1193                 vn_getpath(vp
, &path
.prpo_path
[0], &count
); 
1194                 /* Always make sure it is null terminated */ 
1195                 path
.prpo_path
[MAXPATHLEN 
- 1] = 0; 
1201         error 
= copyout(&path
, buffer
, sizeof(struct proc_regionpath
)); 
1203                 *retval 
= sizeof(struct proc_regionpath
); 
1209 proc_pidregionpathinfo3(proc_t p
, uint64_t arg
, user_addr_t buffer
, __unused 
uint32_t buffersize
, int32_t *retval
) 
1211         struct proc_regionwithpathinfo preginfo
; 
1213         uintptr_t vnodeaddr
; 
1219         /* Loop while looking for vnodes that match dev_t filter */ 
1221                 bzero(&preginfo
, sizeof(struct proc_regionwithpathinfo
)); 
1225                 ret 
= fill_procregioninfo_onlymappedvnodes( p
->task
, addr
, (struct proc_regioninfo_internal 
*)&preginfo
.prp_prinfo
, (uintptr_t *)&vnodeaddr
, (uint32_t *)&vnodeid
); 
1233                 vp 
= (vnode_t
)vnodeaddr
; 
1234                 if ((vnode_getwithvid(vp
, vnodeid
)) == 0) { 
1235                         /* Check if the vnode matches the filter, otherwise loop looking for the next memory region backed by a vnode */ 
1236                         struct vnode_attr va
; 
1238                         memset(&va
, 0, sizeof(va
)); 
1240                         VATTR_WANTED(&va
, va_fsid
); 
1241                         VATTR_WANTED(&va
, va_fsid64
); 
1243                         ret 
= vnode_getattr(vp
, &va
, vfs_context_current()); 
1249                         if (vnode_get_va_fsid(&va
) == arg
) { 
1250                                 /* FILL THE VNODEINFO */ 
1251                                 error 
= fill_vnodeinfo(vp
, &preginfo
.prp_vip
.vip_vi
, FALSE
); 
1253                                 vn_getpath(vp
, &preginfo
.prp_vip
.vip_path
[0], &count
); 
1254                                 /* Always make sure it is null terminated */ 
1255                                 preginfo
.prp_vip
.vip_path
[MAXPATHLEN 
- 1] = 0; 
1264                 addr 
= preginfo
.prp_prinfo
.pri_address 
+ preginfo
.prp_prinfo
.pri_size
; 
1267         error 
= copyout(&preginfo
, buffer
, sizeof(struct proc_regionwithpathinfo
)); 
1269                 *retval 
= sizeof(struct proc_regionwithpathinfo
); 
1275  * Path is relative to current process directory; may different from current 
1279 proc_pidvnodepathinfo(proc_t p
, __unused 
uint64_t arg
, user_addr_t buffer
, __unused 
uint32_t  buffersize
, int32_t *retval
) 
1281         struct proc_vnodepathinfo pvninfo
; 
1283         vnode_t vncdirvp 
= NULLVP
; 
1284         uint32_t vncdirid 
= 0; 
1285         vnode_t vnrdirvp 
= NULLVP
; 
1286         uint32_t vnrdirid 
= 0; 
1289         bzero(&pvninfo
, sizeof(struct proc_vnodepathinfo
)); 
1292         if (p
->p_fd
->fd_cdir
) { 
1293                 vncdirvp 
= p
->p_fd
->fd_cdir
; 
1294                 vncdirid 
= p
->p_fd
->fd_cdir
->v_id
; 
1296         if (p
->p_fd
->fd_rdir
) { 
1297                 vnrdirvp 
= p
->p_fd
->fd_rdir
; 
1298                 vnrdirid 
= p
->p_fd
->fd_rdir
->v_id
; 
1302         if (vncdirvp 
!= NULLVP
) { 
1303                 if ((error 
= vnode_getwithvid(vncdirvp
, vncdirid
)) == 0) { 
1304                         /* FILL THE VNODEINFO */ 
1305                         error 
= fill_vnodeinfo(vncdirvp
, &pvninfo
.pvi_cdir
.vip_vi
, TRUE
); 
1308                                 vn_getpath(vncdirvp
, &pvninfo
.pvi_cdir
.vip_path
[0], &count
); 
1309                                 pvninfo
.pvi_cdir
.vip_path
[MAXPATHLEN 
- 1] = 0; 
1311                         vnode_put(vncdirvp
); 
1317         if ((error 
== 0) && (vnrdirvp 
!= NULLVP
)) { 
1318                 if ((error 
= vnode_getwithvid(vnrdirvp
, vnrdirid
)) == 0) { 
1319                         /* FILL THE VNODEINFO */ 
1320                         error 
= fill_vnodeinfo(vnrdirvp
, &pvninfo
.pvi_rdir
.vip_vi
, TRUE
); 
1323                                 vn_getpath(vnrdirvp
, &pvninfo
.pvi_rdir
.vip_path
[0], &count
); 
1324                                 pvninfo
.pvi_rdir
.vip_path
[MAXPATHLEN 
- 1] = 0; 
1326                         vnode_put(vnrdirvp
); 
1332                 error 
= copyout(&pvninfo
, buffer
, sizeof(struct proc_vnodepathinfo
)); 
1334                         *retval 
= sizeof(struct proc_vnodepathinfo
); 
1342 proc_pidpathinfo(proc_t p
, __unused 
uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, __unused 
int32_t *retval
) 
1346         int len 
= buffersize
; 
1351         if (tvp 
== NULLVP
) { 
1355         buf 
= kheap_alloc(KHEAP_TEMP
, buffersize
, Z_WAITOK 
| Z_ZERO
); 
1360         error 
= proc_pidpathinfo_internal(p
, arg
, buf
, buffersize
, retval
); 
1362                 error 
= copyout(buf
, buffer
, len
); 
1364         kheap_free(KHEAP_TEMP
, buf
, buffersize
); 
1369 proc_pidpathinfo_internal(proc_t p
, __unused 
uint64_t arg
, char *buf
, uint32_t buffersize
, __unused 
int32_t *retval
) 
1373         vnode_t nvp 
= NULLVP
; 
1374         int len 
= buffersize
; 
1378         if (tvp 
== NULLVP
) { 
1382         vid 
= vnode_vid(tvp
); 
1383         error 
= vnode_getwithvid(tvp
, vid
); 
1385                 error 
= vn_getpath_fsenter(tvp
, buf
, &len
); 
1388                         error 
= vnode_lookup(buf
, 0, &nvp
, vfs_context_current()); 
1389                         if ((error 
== 0) && (nvp 
!= NULLVP
)) { 
1399 proc_pidworkqueueinfo(proc_t p
, struct proc_workqueueinfo 
*pwqinfo
) 
1403         bzero(pwqinfo
, sizeof(struct proc_workqueueinfo
)); 
1405         error 
= fill_procworkqueue(p
, pwqinfo
); 
1415 proc_piduniqidentifierinfo(proc_t p
, struct proc_uniqidentifierinfo 
*p_uniqidinfo
) 
1417         p_uniqidinfo
->p_uniqueid 
= proc_uniqueid(p
); 
1418         proc_getexecutableuuid(p
, (unsigned char *)&p_uniqidinfo
->p_uuid
, sizeof(p_uniqidinfo
->p_uuid
)); 
1419         p_uniqidinfo
->p_puniqueid 
= proc_puniqueid(p
); 
1420         p_uniqidinfo
->p_idversion 
= proc_pidversion(p
); 
1421         p_uniqidinfo
->p_reserve2 
= 0; 
1422         p_uniqidinfo
->p_reserve3 
= 0; 
1423         p_uniqidinfo
->p_reserve4 
= 0; 
1428 proc_piduuidinfo(pid_t pid
, uuid_t uuid_buf
, uint32_t buffersize
) 
1430         struct proc 
* p 
= PROC_NULL
; 
1433         if (buffersize 
< sizeof(uuid_t
)) { 
1437         if ((p 
= proc_find(pid
)) == PROC_NULL
) { 
1438                 p 
= proc_find_zombref(pid
); 
1441         if (p 
== PROC_NULL
) { 
1445         proc_getexecutableuuid(p
, (unsigned char *)uuid_buf
, buffersize
); 
1448                 proc_drop_zombref(p
); 
1457  * Function to get the uuid and pid of the originator of the voucher. 
1460 proc_pidoriginatorpid_uuid(uuid_t uuid
, uint32_t buffersize
, pid_t 
*pid
) 
1462         pid_t originator_pid
; 
1467          * Get the current voucher origin pid. The pid returned here 
1468          * might not be valid or may have been recycled. 
1470         kr 
= thread_get_current_voucher_origin_pid(&originator_pid
); 
1471         /* If errors, convert errors to appropriate format */ 
1473                 if (kr 
== KERN_INVALID_TASK
) { 
1475                 } else if (kr 
== KERN_INVALID_VALUE
) { 
1483         *pid 
= originator_pid
; 
1484         error 
= proc_piduuidinfo(originator_pid
, uuid
, buffersize
); 
1489  * Function to get the uuid of the originator of the voucher. 
1492 proc_pidoriginatoruuid(uuid_t uuid
, uint32_t buffersize
) 
1494         pid_t originator_pid
; 
1495         return proc_pidoriginatorpid_uuid(uuid
, buffersize
, &originator_pid
); 
1499  * Function to get the task ipc table size. 
1502 proc_pidipctableinfo(proc_t p
, struct proc_ipctableinfo 
*table_info
) 
1509         bzero(table_info
, sizeof(struct proc_ipctableinfo
)); 
1510         error 
= fill_taskipctableinfo(task
, &(table_info
->table_size
), &(table_info
->table_free
)); 
1519 /***************************** proc_pidoriginatorinfo ***************************/ 
1522 proc_pidoriginatorinfo(int pid
, int flavor
, user_addr_t buffer
, uint32_t  buffersize
, int32_t * retval
) 
1524         int error 
= ENOTSUP
; 
1528         case PROC_PIDORIGINATOR_UUID
: 
1529                 size 
= PROC_PIDORIGINATOR_UUID_SIZE
; 
1531         case PROC_PIDORIGINATOR_BGSTATE
: 
1532                 size 
= PROC_PIDORIGINATOR_BGSTATE_SIZE
; 
1534         case PROC_PIDORIGINATOR_PID_UUID
: 
1535                 size 
= PROC_PIDORIGINATOR_PID_UUID_SIZE
; 
1541         if (buffersize 
< size
) { 
1545         if (pid 
!= 0 && pid 
!= proc_selfpid()) { 
1550         case PROC_PIDORIGINATOR_UUID
: { 
1553                 error 
= proc_pidoriginatoruuid(uuid
, sizeof(uuid
)); 
1558                 error 
= copyout(uuid
, buffer
, size
); 
1565         case PROC_PIDORIGINATOR_PID_UUID
: { 
1566                 struct proc_originatorinfo originator_info
; 
1567                 bzero(&originator_info
, sizeof(originator_info
)); 
1569                 error 
= proc_pidoriginatorpid_uuid(originator_info
.originator_uuid
, 
1570                     sizeof(uuid_t
), &originator_info
.originator_pid
); 
1575                 error 
= copyout(&originator_info
, buffer
, size
); 
1582         case PROC_PIDORIGINATOR_BGSTATE
: { 
1583                 uint32_t is_backgrounded 
= 0; 
1584                 error 
= proc_get_originatorbgstate(&is_backgrounded
); 
1589                 error 
= copyout(&is_backgrounded
, buffer
, size
); 
1603 /***************************** proc_listcoalitions ***************************/ 
1605 proc_listcoalitions(int flavor
, int type
, user_addr_t buffer
, 
1606     uint32_t buffersize
, int32_t *retval
) 
1608 #if CONFIG_COALITIONS 
1609         int error 
= ENOTSUP
; 
1612         void *coalinfo 
= NULL
; 
1613         uint32_t k_buffersize 
= 0, copyout_sz 
= 0; 
1614         int ncoals 
= 0, ncoals_ 
= 0; 
1616         /* struct procinfo_coalinfo; */ 
1619         case LISTCOALITIONS_ALL_COALS
: 
1620                 elem_size 
= LISTCOALITIONS_ALL_COALS_SIZE
; 
1623         case LISTCOALITIONS_SINGLE_TYPE
: 
1624                 elem_size 
= LISTCOALITIONS_SINGLE_TYPE_SIZE
; 
1631         /* find the total number of coalitions */ 
1632         ncoals 
= coalitions_get_list(coal_type
, NULL
, 0); 
1634         if (ncoals 
== 0 || buffer 
== 0 || buffersize 
== 0) { 
1636                  * user just wants buffer size 
1637                  * or there are no coalitions 
1640                 *retval 
= (int)(ncoals 
* elem_size
); 
1644         k_buffersize 
= ncoals 
* elem_size
; 
1645         coalinfo 
= kheap_alloc(KHEAP_TEMP
, k_buffersize
, Z_WAITOK 
| Z_ZERO
); 
1652         case LISTCOALITIONS_ALL_COALS
: 
1653         case LISTCOALITIONS_SINGLE_TYPE
: 
1654                 ncoals_ 
= coalitions_get_list(coal_type
, coalinfo
, ncoals
); 
1657                 panic("memory corruption?!"); 
1661                 /* all the coalitions disappeared... weird but valid */ 
1668          * Some coalitions may have disappeared between our initial check, 
1669          * and the the actual list acquisition. 
1670          * Only copy out what we really need. 
1672         copyout_sz 
= k_buffersize
; 
1673         if (ncoals_ 
< ncoals
) { 
1674                 copyout_sz 
= ncoals_ 
* elem_size
; 
1678          * copy the list up to user space 
1679          * (we're guaranteed to have a non-null pointer/size here) 
1681         error 
= copyout(coalinfo
, buffer
, 
1682             copyout_sz 
< buffersize 
? copyout_sz 
: buffersize
); 
1685                 *retval 
= (int)copyout_sz
; 
1690                 kheap_free(KHEAP_TEMP
, coalinfo
, k_buffersize
); 
1695         /* no coalition support */ 
1706 /*************************** proc_can_use_forgeound_hw **************************/ 
1708 proc_can_use_foreground_hw(int pid
, user_addr_t u_reason
, uint32_t reasonsize
, int32_t *retval
) 
1710         proc_t p 
= PROC_NULL
; 
1712         uint32_t reason 
= PROC_FGHW_ERROR
; 
1714         task_t task 
= TASK_NULL
; 
1715 #if CONFIG_COALITIONS 
1716         coalition_t coal 
= COALITION_NULL
; 
1723                 reason 
= PROC_FGHW_ERROR
; 
1728         if (p 
== PROC_NULL
) { 
1730                 reason 
= PROC_FGHW_ERROR
; 
1734 #if CONFIG_COALITIONS 
1735         if (p 
!= current_proc() && 
1736             !kauth_cred_issuser(kauth_cred_get())) { 
1738                 reason 
= PROC_FGHW_ERROR
; 
1743         if (coalition_is_leader(task
, task_get_coalition(task
, COALITION_TYPE_JETSAM
))) { 
1744                 task_reference(task
); 
1746                 /* current task is not a coalition leader: find the leader */ 
1747                 task 
= coalition_get_leader(coal
); 
1750         if (task 
!= TASK_NULL
) { 
1752                  * If task is non-null, then it is the coalition leader of the 
1753                  * current process' coalition. This could be the same task as 
1754                  * the current_task, and that's OK. 
1759                 proc_get_darwinbgstate(task
, &flags
); 
1760                 if ((flags 
& PROC_FLAG_APPLICATION
) != PROC_FLAG_APPLICATION
) { 
1762                          * Coalition leader is not an application, continue 
1763                          * searching for other ways this task could gain 
1766                         reason 
= PROC_FGHW_DAEMON_LEADER
; 
1770                 if (proc_get_effective_task_policy(task
, TASK_POLICY_DARWIN_BG
)) { 
1772                          * If the leader of the current process' coalition has 
1773                          * been marked as DARWIN_BG, then it definitely should 
1774                          * not be using foreground hardware resources. 
1776                         reason 
= PROC_FGHW_LEADER_BACKGROUND
; 
1780                 role 
= proc_get_effective_task_policy(task
, TASK_POLICY_ROLE
); 
1782                 case TASK_FOREGROUND_APPLICATION
: /* DARWIN_ROLE_UI_FOCAL */ 
1783                 case TASK_BACKGROUND_APPLICATION
: /* DARWIN_ROLE_UI */ 
1785                          * The leader of this coalition is a focal, UI app: 
1787                          * TODO: should extensions/plugins be allowed to use 
1791                         reason 
= PROC_FGHW_OK
; 
1793                 case TASK_DEFAULT_APPLICATION
: /* DARWIN_ROLE_UI_NON_FOCAL */ 
1794                 case TASK_NONUI_APPLICATION
: /* DARWIN_ROLE_NON_UI */ 
1795                 case TASK_THROTTLE_APPLICATION
: 
1796                 case TASK_UNSPECIFIED
: 
1798                         /* non-focal, non-ui apps don't get access */ 
1799                         reason 
= PROC_FGHW_LEADER_NONUI
; 
1805         if (task 
!= TASK_NULL
) { 
1806                 task_deallocate(task
); 
1809 #endif /* CONFIG_COALITIONS */ 
1812          * There is no reasonable semantic to investigate the currently 
1813          * adopted voucher of an arbitrary thread in a non-current process. 
1816         if (p 
!= current_proc()) { 
1822          * In the absence of coalitions, fall back to a voucher-based lookup 
1823          * where a daemon can used foreground HW if it's operating on behalf 
1824          * of a foreground application. 
1825          * NOTE: this is equivalent to a call to 
1826          *       proc_pidoriginatorinfo(PROC_PIDORIGINATOR_BGSTATE, &isBG, sizeof(isBG)) 
1829         error 
= proc_get_originatorbgstate(&isBG
); 
1834                 reason 
= PROC_FGHW_NO_ORIGINATOR
; 
1838                 reason 
= PROC_FGHW_NO_VOUCHER_ATTR
; 
1842                 reason 
= PROC_FGHW_DAEMON_NO_VOUCHER
; 
1846                 /* some other error occurred: report that to the caller */ 
1847                 reason 
= PROC_FGHW_VOUCHER_ERROR
; 
1852                 reason 
= PROC_FGHW_ORIGINATOR_BACKGROUND
; 
1856                  * The process itself is either a foreground app, or has 
1857                  * adopted a voucher originating from an app that's still in 
1860                 reason 
= PROC_FGHW_DAEMON_OK
; 
1865         if (task 
!= TASK_NULL
) { 
1866                 task_deallocate(task
); 
1868         if (p 
!= PROC_NULL
) { 
1871         if (reasonsize 
>= sizeof(reason
) && u_reason 
!= (user_addr_t
)0) { 
1872                 (void)copyout(&reason
, u_reason
, sizeof(reason
)); 
1878 /********************************** proc_pidinfo ********************************/ 
1882 proc_pidinfo(int pid
, uint32_t flags
, uint64_t ext_id
, int flavor
, uint64_t arg
, user_addr_t buffer
, uint32_t  buffersize
, int32_t * retval
) 
1884         struct proc 
* p 
= PROC_NULL
; 
1885         int error 
= ENOTSUP
; 
1888         int shortversion 
= 0; 
1891         bool thuniqueid 
= false; 
1892         int uniqidversion 
= 0; 
1893         bool check_same_user
; 
1896         case PROC_PIDLISTFDS
: 
1897                 size 
= PROC_PIDLISTFD_SIZE
; 
1898                 if (buffer 
== USER_ADDR_NULL
) { 
1902         case PROC_PIDTBSDINFO
: 
1903                 size 
= PROC_PIDTBSDINFO_SIZE
; 
1905         case PROC_PIDTASKINFO
: 
1906                 size 
= PROC_PIDTASKINFO_SIZE
; 
1908         case PROC_PIDTASKALLINFO
: 
1909                 size 
= PROC_PIDTASKALLINFO_SIZE
; 
1911         case PROC_PIDTHREADINFO
: 
1912                 size 
= PROC_PIDTHREADINFO_SIZE
; 
1914         case PROC_PIDLISTTHREADIDS
: 
1915                 size 
= PROC_PIDLISTTHREADIDS_SIZE
; 
1917         case PROC_PIDLISTTHREADS
: 
1918                 size 
= PROC_PIDLISTTHREADS_SIZE
; 
1920         case PROC_PIDREGIONINFO
: 
1921                 size 
= PROC_PIDREGIONINFO_SIZE
; 
1923         case PROC_PIDREGIONPATHINFO
: 
1924                 size 
= PROC_PIDREGIONPATHINFO_SIZE
; 
1926         case PROC_PIDVNODEPATHINFO
: 
1927                 size 
= PROC_PIDVNODEPATHINFO_SIZE
; 
1929         case PROC_PIDTHREADPATHINFO
: 
1930                 size 
= PROC_PIDTHREADPATHINFO_SIZE
; 
1932         case PROC_PIDPATHINFO
: 
1935         case PROC_PIDWORKQUEUEINFO
: 
1936                 /* kernel does not have workq info */ 
1940                         size 
= PROC_PIDWORKQUEUEINFO_SIZE
; 
1943         case PROC_PIDT_SHORTBSDINFO
: 
1944                 size 
= PROC_PIDT_SHORTBSDINFO_SIZE
; 
1946         case PROC_PIDLISTFILEPORTS
: 
1947                 size 
= PROC_PIDLISTFILEPORTS_SIZE
; 
1948                 if (buffer 
== (user_addr_t
)0) { 
1952         case PROC_PIDTHREADID64INFO
: 
1953                 size 
= PROC_PIDTHREADID64INFO_SIZE
; 
1955         case PROC_PIDUNIQIDENTIFIERINFO
: 
1956                 size 
= PROC_PIDUNIQIDENTIFIERINFO_SIZE
; 
1958         case PROC_PIDT_BSDINFOWITHUNIQID
: 
1959                 size 
= PROC_PIDT_BSDINFOWITHUNIQID_SIZE
; 
1961         case PROC_PIDARCHINFO
: 
1962                 size 
= PROC_PIDARCHINFO_SIZE
; 
1964         case PROC_PIDCOALITIONINFO
: 
1965                 size 
= PROC_PIDCOALITIONINFO_SIZE
; 
1967         case PROC_PIDNOTEEXIT
: 
1969                  * Set findzomb explicitly because arg passed 
1970                  * in is used as note exit status bits. 
1972                 size 
= PROC_PIDNOTEEXIT_SIZE
; 
1975         case PROC_PIDEXITREASONINFO
: 
1976                 size 
= PROC_PIDEXITREASONINFO_SIZE
; 
1979         case PROC_PIDEXITREASONBASICINFO
: 
1980                 size 
= PROC_PIDEXITREASONBASICINFOSIZE
; 
1983         case PROC_PIDREGIONPATHINFO2
: 
1984                 size 
= PROC_PIDREGIONPATHINFO2_SIZE
; 
1986         case PROC_PIDREGIONPATHINFO3
: 
1987                 size 
= PROC_PIDREGIONPATHINFO3_SIZE
; 
1989         case PROC_PIDLISTUPTRS
: 
1990                 size 
= PROC_PIDLISTUPTRS_SIZE
; 
1991                 if (buffer 
== USER_ADDR_NULL
) { 
1995         case PROC_PIDLISTDYNKQUEUES
: 
1996                 size 
= PROC_PIDLISTDYNKQUEUES_SIZE
; 
1997                 if (buffer 
== USER_ADDR_NULL
) { 
2001         case PROC_PIDVMRTFAULTINFO
: 
2002                 size 
= sizeof(vm_rtfault_record_t
); 
2003                 if (buffer 
== USER_ADDR_NULL
) { 
2007         case PROC_PIDPLATFORMINFO
: 
2008                 size 
= PROC_PIDPLATFORMINFO_SIZE
; 
2011         case PROC_PIDREGIONPATH
: 
2012                 size 
= PROC_PIDREGIONPATH_SIZE
; 
2014         case PROC_PIDIPCTABLEINFO
: 
2015                 size 
= PROC_PIDIPCTABLEINFO_SIZE
; 
2021         if (buffersize 
< size
) { 
2025         if ((flavor 
== PROC_PIDPATHINFO
) && (buffersize 
> PROC_PIDPATHINFO_MAXSIZE
)) { 
2029         /* Check if we need to look for zombies */ 
2030         if ((flavor 
== PROC_PIDTBSDINFO
) || (flavor 
== PROC_PIDT_SHORTBSDINFO
) || (flavor 
== PROC_PIDT_BSDINFOWITHUNIQID
) 
2031             || (flavor 
== PROC_PIDUNIQIDENTIFIERINFO
)) { 
2037         if ((p 
= proc_find(pid
)) == PROC_NULL
) { 
2039                         p 
= proc_find_zombref(pid
); 
2041                 if (p 
== PROC_NULL
) { 
2050         if ((flags 
& PIF_COMPARE_IDVERSION
) && (ext_id 
!= p
->p_idversion
)) { 
2054         if ((flags 
& PIF_COMPARE_UNIQUEID
) && (ext_id 
!= p
->p_uniqueid
)) { 
2059         /* Certain operations don't require privileges */ 
2061         case PROC_PIDT_SHORTBSDINFO
: 
2062         case PROC_PIDUNIQIDENTIFIERINFO
: 
2063         case PROC_PIDPATHINFO
: 
2064         case PROC_PIDCOALITIONINFO
: 
2065         case PROC_PIDPLATFORMINFO
: 
2066                 check_same_user 
= NO_CHECK_SAME_USER
; 
2069                 check_same_user 
= CHECK_SAME_USER
; 
2073         /* Do we have permission to look into this? */ 
2074         if ((error 
= proc_security_policy(p
, PROC_INFO_CALL_PIDINFO
, flavor
, check_same_user
))) { 
2079         case PROC_PIDLISTFDS
: { 
2080                 error 
= proc_pidfdlist(p
, buffer
, buffersize
, retval
); 
2084         case PROC_PIDUNIQIDENTIFIERINFO
: { 
2085                 struct proc_uniqidentifierinfo p_uniqidinfo
; 
2086                 bzero(&p_uniqidinfo
, sizeof(p_uniqidinfo
)); 
2087                 proc_piduniqidentifierinfo(p
, &p_uniqidinfo
); 
2088                 error 
= copyout(&p_uniqidinfo
, buffer
, sizeof(struct proc_uniqidentifierinfo
)); 
2090                         *retval 
= sizeof(struct proc_uniqidentifierinfo
); 
2095         case PROC_PIDT_SHORTBSDINFO
: 
2098         case PROC_PIDT_BSDINFOWITHUNIQID
: 
2099         case PROC_PIDTBSDINFO
: { 
2100                 struct proc_bsdinfo pbsd
; 
2101                 struct proc_bsdshortinfo pbsd_short
; 
2102                 struct proc_bsdinfowithuniqid pbsd_uniqid
; 
2104                 if (flavor 
== PROC_PIDT_BSDINFOWITHUNIQID
) { 
2108                 if (shortversion 
!= 0) { 
2109                         error 
= proc_pidshortbsdinfo(p
, &pbsd_short
, zombie
); 
2111                         error 
= proc_pidbsdinfo(p
, &pbsd
, zombie
); 
2112                         if (uniqidversion 
!= 0) { 
2113                                 bzero(&pbsd_uniqid
, sizeof(pbsd_uniqid
)); 
2114                                 proc_piduniqidentifierinfo(p
, &pbsd_uniqid
.p_uniqidentifier
); 
2115                                 pbsd_uniqid
.pbsd 
= pbsd
; 
2120                         if (shortversion 
!= 0) { 
2121                                 error 
= copyout(&pbsd_short
, buffer
, sizeof(struct proc_bsdshortinfo
)); 
2123                                         *retval 
= sizeof(struct proc_bsdshortinfo
); 
2125                         } else if (uniqidversion 
!= 0) { 
2126                                 error 
= copyout(&pbsd_uniqid
, buffer
, sizeof(struct proc_bsdinfowithuniqid
)); 
2128                                         *retval 
= sizeof(struct proc_bsdinfowithuniqid
); 
2131                                 error 
= copyout(&pbsd
, buffer
, sizeof(struct proc_bsdinfo
)); 
2133                                         *retval 
= sizeof(struct proc_bsdinfo
); 
2140         case PROC_PIDTASKINFO
: { 
2141                 struct proc_taskinfo ptinfo
; 
2143                 error 
=  proc_pidtaskinfo(p
, &ptinfo
); 
2145                         error 
= copyout(&ptinfo
, buffer
, sizeof(struct proc_taskinfo
)); 
2147                                 *retval 
= sizeof(struct proc_taskinfo
); 
2153         case PROC_PIDTASKALLINFO
: { 
2154                 struct proc_taskallinfo pall
; 
2155                 bzero(&pall
, sizeof(pall
)); 
2156                 error 
= proc_pidbsdinfo(p
, &pall
.pbsd
, 0); 
2157                 error 
=  proc_pidtaskinfo(p
, &pall
.ptinfo
); 
2159                         error 
= copyout(&pall
, buffer
, sizeof(struct proc_taskallinfo
)); 
2161                                 *retval 
= sizeof(struct proc_taskallinfo
); 
2167         case PROC_PIDTHREADID64INFO
: 
2170         case PROC_PIDTHREADINFO
:{ 
2171                 struct proc_threadinfo pthinfo
; 
2173                 error  
= proc_pidthreadinfo(p
, arg
, thuniqueid
, &pthinfo
); 
2175                         error 
= copyout(&pthinfo
, buffer
, sizeof(struct proc_threadinfo
)); 
2177                                 *retval 
= sizeof(struct proc_threadinfo
); 
2183         case PROC_PIDLISTTHREADIDS
: 
2186         case PROC_PIDLISTTHREADS
:{ 
2187                 error 
=  proc_pidlistthreads(p
, thuniqueid
, buffer
, buffersize
, retval
); 
2191         case PROC_PIDREGIONINFO
:{ 
2192                 error 
=  proc_pidregioninfo(p
, arg
, buffer
, buffersize
, retval
); 
2197         case PROC_PIDREGIONPATHINFO
:{ 
2198                 error 
=  proc_pidregionpathinfo(p
, arg
, buffer
, buffersize
, retval
); 
2202         case PROC_PIDREGIONPATHINFO2
:{ 
2203                 error 
=  proc_pidregionpathinfo2(p
, arg
, buffer
, buffersize
, retval
); 
2207         case PROC_PIDREGIONPATHINFO3
:{ 
2208                 error 
=  proc_pidregionpathinfo3(p
, arg
, buffer
, buffersize
, retval
); 
2212         case PROC_PIDVNODEPATHINFO
:{ 
2213                 error 
=  proc_pidvnodepathinfo(p
, arg
, buffer
, buffersize
, retval
); 
2218         case PROC_PIDTHREADPATHINFO
:{ 
2219                 struct proc_threadwithpathinfo pinfo
; 
2221                 error  
= proc_pidthreadpathinfo(p
, arg
, &pinfo
); 
2223                         error 
= copyout((caddr_t
)&pinfo
, buffer
, sizeof(struct proc_threadwithpathinfo
)); 
2225                                 *retval 
= sizeof(struct proc_threadwithpathinfo
); 
2231         case PROC_PIDPATHINFO
: { 
2232                 error 
=  proc_pidpathinfo(p
, arg
, buffer
, buffersize
, retval
); 
2237         case PROC_PIDWORKQUEUEINFO
:{ 
2238                 struct proc_workqueueinfo pwqinfo
; 
2240                 error  
= proc_pidworkqueueinfo(p
, &pwqinfo
); 
2242                         error 
= copyout(&pwqinfo
, buffer
, sizeof(struct proc_workqueueinfo
)); 
2244                                 *retval 
= sizeof(struct proc_workqueueinfo
); 
2250         case PROC_PIDLISTFILEPORTS
: { 
2251                 error 
= proc_pidfileportlist(p
, buffer
, buffersize
, retval
); 
2255         case PROC_PIDARCHINFO
: { 
2256                 struct proc_archinfo pai
; 
2257                 bzero(&pai
, sizeof(pai
)); 
2258                 proc_archinfo(p
, &pai
); 
2259                 error 
= copyout(&pai
, buffer
, sizeof(struct proc_archinfo
)); 
2261                         *retval 
= sizeof(struct proc_archinfo
); 
2266         case PROC_PIDCOALITIONINFO
: { 
2267                 struct proc_pidcoalitioninfo pci
; 
2268                 proc_pidcoalitioninfo(p
, &pci
); 
2269                 error 
= copyout(&pci
, buffer
, sizeof(struct proc_pidcoalitioninfo
)); 
2271                         *retval 
= sizeof(struct proc_pidcoalitioninfo
); 
2276         case PROC_PIDNOTEEXIT
: { 
2278                 error 
= proc_pidnoteexit(p
, arg
, &data
); 
2280                         error 
= copyout(&data
, buffer
, sizeof(data
)); 
2282                                 *retval 
= sizeof(data
); 
2288         case PROC_PIDEXITREASONINFO
: { 
2289                 struct proc_exitreasoninfo eri
; 
2291                 error 
= copyin(buffer
, &eri
, sizeof(eri
)); 
2296                 error 
= proc_pidexitreasoninfo(p
, &eri
, NULL
); 
2298                         error 
= copyout(&eri
, buffer
, sizeof(eri
)); 
2300                                 *retval 
=  sizeof(eri
); 
2306         case PROC_PIDEXITREASONBASICINFO
: { 
2307                 struct proc_exitreasonbasicinfo beri
; 
2309                 bzero(&beri
, sizeof(struct proc_exitreasonbasicinfo
)); 
2311                 error 
= proc_pidexitreasoninfo(p
, NULL
, &beri
); 
2313                         error 
= copyout(&beri
, buffer
, sizeof(beri
)); 
2315                                 *retval 
=  sizeof(beri
); 
2321         case PROC_PIDLISTUPTRS
: 
2322                 error 
= proc_pidlistuptrs(p
, buffer
, buffersize
, retval
); 
2325         case PROC_PIDLISTDYNKQUEUES
: 
2326                 error 
= kevent_copyout_proc_dynkqids(p
, buffer
, buffersize
, retval
); 
2328         case PROC_PIDVMRTFAULTINFO
: { 
2329                 /* This interface can only be employed on the current 
2330                  * process. We will eventually enforce an entitlement. 
2334                 if (p 
!= current_proc()) { 
2339                 size_t kbufsz 
= MIN(buffersize
, vmrtfaultinfo_bufsz()); 
2340                 void *vmrtfbuf 
= kheap_alloc(KHEAP_TEMP
, kbufsz
, Z_WAITOK 
| Z_ZERO
); 
2342                 if (vmrtfbuf 
== NULL
) { 
2347                 uint64_t effpid 
= get_current_unique_pid(); 
2348                 /* The VM may choose to provide more comprehensive records 
2349                  * for root-privileged users on internal configurations. 
2351                 boolean_t isroot 
= (suser(kauth_cred_get(), (u_short 
*)0) == 0); 
2352                 size_t num_extracted 
= 0; 
2353                 int vmf_residue 
= vmrtf_extract(effpid
, isroot
, kbufsz
, vmrtfbuf
, &num_extracted
); 
2354                 size_t vmfsz 
= num_extracted 
* sizeof(vm_rtfault_record_t
); 
2356                 *retval 
= (int32_t)MIN(num_extracted
, INT32_MAX
); 
2360                         error 
= copyout(vmrtfbuf
, buffer
, vmfsz
); 
2368                 kheap_free(KHEAP_TEMP
, vmrtfbuf
, kbufsz
); 
2371         case PROC_PIDPLATFORMINFO
: { 
2373                 uint32_t platform 
= p
->p_platform
; 
2375                 error 
= copyout(&platform
, buffer
, sizeof(uint32_t)); 
2377                         *retval 
= sizeof(uint32_t); 
2380         case PROC_PIDREGIONPATH
: { 
2381                 error 
= proc_pidregionpath(p
, arg
, buffer
, buffersize
, retval
); 
2384         case PROC_PIDIPCTABLEINFO
: { 
2385                 struct proc_ipctableinfo table_info
; 
2387                 error 
= proc_pidipctableinfo(p
, &table_info
); 
2389                         error 
= copyout(&table_info
, buffer
, sizeof(struct proc_ipctableinfo
)); 
2391                                 *retval 
= sizeof(struct proc_ipctableinfo
); 
2404         } else if (zombie
) { 
2405                 proc_drop_zombref(p
); 
2412 pid_vnodeinfo(vnode_t vp
, struct fileproc 
* fp
, proc_t proc
, int fd
, user_addr_t  buffer
, __unused 
uint32_t buffersize
, int32_t * retval
) 
2414         struct vnode_fdinfo vfi
; 
2415         uint32_t vid 
= vnode_vid(vp
); 
2418         if ((error 
= vnode_getwithvid(vp
, vid
)) != 0) { 
2421         bzero(&vfi
, sizeof(struct vnode_fdinfo
)); 
2422         fill_fileinfo(fp
, proc
, fd
, &vfi
.pfi
); 
2423         error 
= fill_vnodeinfo(vp
, &vfi
.pvi
, FALSE
); 
2426                 error 
= copyout((caddr_t
)&vfi
, buffer
, sizeof(struct vnode_fdinfo
)); 
2428                         *retval 
= sizeof(struct vnode_fdinfo
); 
2435 pid_vnodeinfopath(vnode_t vp
, struct fileproc 
* fp
, proc_t proc
, int fd
, user_addr_t  buffer
, __unused 
uint32_t buffersize
, int32_t * retval
) 
2437         struct vnode_fdinfowithpath vfip
; 
2438         uint32_t vid 
= vnode_vid(vp
); 
2439         int count
, error 
= 0; 
2441         if ((error 
= vnode_getwithvid(vp
, vid
)) != 0) { 
2444         bzero(&vfip
, sizeof(struct vnode_fdinfowithpath
)); 
2445         fill_fileinfo(fp
, proc
, fd
, &vfip
.pfi
); 
2446         error 
= fill_vnodeinfo(vp
, &vfip
.pvip
.vip_vi
, TRUE
); 
2449                 vn_getpath(vp
, &vfip
.pvip
.vip_path
[0], &count
); 
2450                 vfip
.pvip
.vip_path
[MAXPATHLEN 
- 1] = 0; 
2452                 error 
= copyout((caddr_t
)&vfip
, buffer
, sizeof(struct vnode_fdinfowithpath
)); 
2454                         *retval 
= sizeof(struct vnode_fdinfowithpath
); 
2463 fill_fileinfo(struct fileproc 
* fp
, proc_t proc
, int fd
, struct proc_fileinfo 
* fproc
) 
2465         fproc
->fi_openflags 
= fp
->fp_glob
->fg_flag
; 
2466         fproc
->fi_status 
= 0; 
2467         fproc
->fi_offset 
= fp
->fp_glob
->fg_offset
; 
2468         fproc
->fi_type 
= FILEGLOB_DTYPE(fp
->fp_glob
); 
2469         if (os_ref_get_count_raw(&fp
->fp_glob
->fg_count
) > 1) { 
2470                 fproc
->fi_status 
|= PROC_FP_SHARED
; 
2472         if (proc 
!= PROC_NULL
) { 
2473                 if ((FDFLAGS_GET(proc
, fd
) & UF_EXCLOSE
) != 0) { 
2474                         fproc
->fi_status 
|= PROC_FP_CLEXEC
; 
2476                 if ((FDFLAGS_GET(proc
, fd
) & UF_FORKCLOSE
) != 0) { 
2477                         fproc
->fi_status 
|= PROC_FP_CLFORK
; 
2480         if (FILEPROC_TYPE(fp
) == FTYPE_GUARDED
) { 
2481                 fproc
->fi_status 
|= PROC_FP_GUARDED
; 
2482                 fproc
->fi_guardflags 
= 0; 
2483                 if (fp_isguarded(fp
, GUARD_CLOSE
)) { 
2484                         fproc
->fi_guardflags 
|= PROC_FI_GUARD_CLOSE
; 
2486                 if (fp_isguarded(fp
, GUARD_DUP
)) { 
2487                         fproc
->fi_guardflags 
|= PROC_FI_GUARD_DUP
; 
2489                 if (fp_isguarded(fp
, GUARD_SOCKET_IPC
)) { 
2490                         fproc
->fi_guardflags 
|= PROC_FI_GUARD_SOCKET_IPC
; 
2492                 if (fp_isguarded(fp
, GUARD_FILEPORT
)) { 
2493                         fproc
->fi_guardflags 
|= PROC_FI_GUARD_FILEPORT
; 
2501 fill_vnodeinfo(vnode_t vp
, struct vnode_info 
*vinfo
, __unused boolean_t check_fsgetpath
) 
2503         vfs_context_t context
; 
2507         bzero(&sb
, sizeof(struct stat64
)); 
2508         context 
= vfs_context_create((vfs_context_t
)0); 
2510         /* Called when vnode info is used by the caller to get vnode's path */ 
2511         if (check_fsgetpath
) { 
2512                 error 
= mac_vnode_check_fsgetpath(context
, vp
); 
2516                 error 
= vn_stat(vp
, &sb
, NULL
, 1, 0, context
); 
2517                 munge_vinfo_stat(&sb
, &vinfo
->vi_stat
); 
2519         (void)vfs_context_rele(context
); 
2524         if (vp
->v_mount 
!= dead_mountp
) { 
2525                 vinfo
->vi_fsid 
= vp
->v_mount
->mnt_vfsstat
.f_fsid
; 
2527                 vinfo
->vi_fsid
.val
[0] = 0; 
2528                 vinfo
->vi_fsid
.val
[1] = 0; 
2530         vinfo
->vi_type 
= vp
->v_type
; 
2536 pid_socketinfo(socket_t so
, struct fileproc 
*fp
, proc_t proc
, int fd
, user_addr_t  buffer
, __unused 
uint32_t buffersize
, int32_t * retval
) 
2539         struct socket_fdinfo s
; 
2542         bzero(&s
, sizeof(struct socket_fdinfo
)); 
2543         fill_fileinfo(fp
, proc
, fd
, &s
.pfi
); 
2544         if ((error 
= fill_socketinfo(so
, &s
.psi
)) == 0) { 
2545                 if ((error 
= copyout(&s
, buffer
, sizeof(struct socket_fdinfo
))) == 0) { 
2546                         *retval 
= sizeof(struct socket_fdinfo
); 
2551 #pragma unused(so, fp, proc, fd, buffer) 
2558 pid_pseminfo(struct psemnode 
*psem
, struct fileproc 
*fp
, proc_t proc
, int fd
, user_addr_t  buffer
, __unused 
uint32_t buffersize
, int32_t * retval
) 
2560         struct psem_fdinfo pseminfo
; 
2563         bzero(&pseminfo
, sizeof(struct psem_fdinfo
)); 
2564         fill_fileinfo(fp
, proc
, fd
, &pseminfo
.pfi
); 
2566         if ((error 
= fill_pseminfo(psem
, &pseminfo
.pseminfo
)) == 0) { 
2567                 if ((error 
= copyout(&pseminfo
, buffer
, sizeof(struct psem_fdinfo
))) == 0) { 
2568                         *retval 
= sizeof(struct psem_fdinfo
); 
2576 pid_pshminfo(struct pshmnode 
*pshm
, struct fileproc 
*fp
, proc_t proc
, int fd
, user_addr_t  buffer
, __unused 
uint32_t buffersize
, int32_t * retval
) 
2578         struct pshm_fdinfo pshminfo
; 
2581         bzero(&pshminfo
, sizeof(struct pshm_fdinfo
)); 
2582         fill_fileinfo(fp
, proc
, fd
, &pshminfo
.pfi
); 
2584         if ((error 
= fill_pshminfo(pshm
, &pshminfo
.pshminfo
)) == 0) { 
2585                 if ((error 
= copyout(&pshminfo
, buffer
, sizeof(struct pshm_fdinfo
))) == 0) { 
2586                         *retval 
= sizeof(struct pshm_fdinfo
); 
2594 pid_pipeinfo(struct pipe 
*  p
, struct fileproc 
*fp
, proc_t proc
, int fd
, user_addr_t  buffer
, __unused 
uint32_t buffersize
, int32_t * retval
) 
2596         struct pipe_fdinfo pipeinfo
; 
2599         bzero(&pipeinfo
, sizeof(struct pipe_fdinfo
)); 
2600         fill_fileinfo(fp
, proc
, fd
, &pipeinfo
.pfi
); 
2601         if ((error 
= fill_pipeinfo(p
, &pipeinfo
.pipeinfo
)) == 0) { 
2602                 if ((error 
= copyout(&pipeinfo
, buffer
, sizeof(struct pipe_fdinfo
))) == 0) { 
2603                         *retval 
= sizeof(struct pipe_fdinfo
); 
2611 pid_kqueueinfo(struct kqueue 
* kq
, struct fileproc 
*fp
, proc_t proc
, int fd
, user_addr_t  buffer
, __unused 
uint32_t buffersize
, int32_t * retval
) 
2613         struct kqueue_fdinfo kqinfo
; 
2616         bzero(&kqinfo
, sizeof(struct kqueue_fdinfo
)); 
2618         /* not all kq's are associated with a file (e.g. workqkq) */ 
2621                 fill_fileinfo(fp
, proc
, fd
, &kqinfo
.pfi
); 
2624         if ((error 
= fill_kqueueinfo(kq
, &kqinfo
.kqueueinfo
)) == 0) { 
2625                 if ((error 
= copyout(&kqinfo
, buffer
, sizeof(struct kqueue_fdinfo
))) == 0) { 
2626                         *retval 
= sizeof(struct kqueue_fdinfo
); 
2634 /************************** proc_pidfdinfo routine ***************************/ 
2636 proc_pidfdinfo(int pid
, int flavor
, int fd
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
) 
2639         int error 
= ENOTSUP
; 
2640         struct fileproc 
*fp 
= NULL
; 
2644         case PROC_PIDFDVNODEINFO
: 
2645                 size 
= PROC_PIDFDVNODEINFO_SIZE
; 
2647         case PROC_PIDFDVNODEPATHINFO
: 
2648                 size 
= PROC_PIDFDVNODEPATHINFO_SIZE
; 
2650         case PROC_PIDFDSOCKETINFO
: 
2651                 size 
= PROC_PIDFDSOCKETINFO_SIZE
; 
2653         case PROC_PIDFDPSEMINFO
: 
2654                 size 
= PROC_PIDFDPSEMINFO_SIZE
; 
2656         case PROC_PIDFDPSHMINFO
: 
2657                 size 
= PROC_PIDFDPSHMINFO_SIZE
; 
2659         case PROC_PIDFDPIPEINFO
: 
2660                 size 
= PROC_PIDFDPIPEINFO_SIZE
; 
2662         case PROC_PIDFDKQUEUEINFO
: 
2663                 size 
= PROC_PIDFDKQUEUEINFO_SIZE
; 
2665         case PROC_PIDFDKQUEUE_EXTINFO
: 
2666                 size 
= PROC_PIDFDKQUEUE_EXTINFO_SIZE
; 
2667                 if (buffer 
== (user_addr_t
)0) { 
2671         case PROC_PIDFDATALKINFO
: 
2672                 size 
= PROC_PIDFDATALKINFO_SIZE
; 
2679         if (buffersize 
< size
) { 
2683         if ((p 
= proc_find(pid
)) == PROC_NULL
) { 
2688         /* Do we have permission to look into this? */ 
2689         if ((error 
= proc_security_policy(p
, PROC_INFO_CALL_PIDFDINFO
, flavor
, CHECK_SAME_USER
))) { 
2694         case PROC_PIDFDVNODEINFO
: { 
2695                 if ((error 
= fp_get_ftype(p
, fd
, DTYPE_VNODE
, EBADF
, &fp
)) != 0) { 
2698                 error 
= pid_vnodeinfo(fp
->fp_glob
->fg_data
, fp
, p
, fd
, buffer
, buffersize
, retval
); 
2702         case PROC_PIDFDVNODEPATHINFO
: { 
2703                 if ((error 
= fp_get_ftype(p
, fd
, DTYPE_VNODE
, EBADF
, &fp
)) != 0) { 
2706                 error 
= pid_vnodeinfopath(fp
->fp_glob
->fg_data
, fp
, p
, fd
, buffer
, buffersize
, retval
); 
2710         case PROC_PIDFDSOCKETINFO
: { 
2711                 if ((error 
= fp_get_ftype(p
, fd
, DTYPE_SOCKET
, ENOTSOCK
, &fp
)) != 0) { 
2714                 error 
= pid_socketinfo(fp
->fp_glob
->fg_data
, fp
, p
, fd
, buffer
, buffersize
, retval
); 
2718         case PROC_PIDFDPSEMINFO
: { 
2719                 if ((error 
= fp_get_ftype(p
, fd
, DTYPE_PSXSEM
, EBADF
, &fp
)) != 0) { 
2722                 error 
= pid_pseminfo(fp
->fp_glob
->fg_data
, fp
, p
, fd
, buffer
, buffersize
, retval
); 
2726         case PROC_PIDFDPSHMINFO
: { 
2727                 if ((error 
= fp_get_ftype(p
, fd
, DTYPE_PSXSHM
, EBADF
, &fp
)) != 0) { 
2730                 error 
= pid_pshminfo(fp
->fp_glob
->fg_data
, fp
, p
, fd
, buffer
, buffersize
, retval
); 
2734         case PROC_PIDFDPIPEINFO
: { 
2735                 if ((error 
= fp_get_ftype(p
, fd
, DTYPE_PIPE
, EBADF
, &fp
)) != 0) { 
2738                 error 
= pid_pipeinfo(fp
->fp_glob
->fg_data
, fp
, p
, fd
, buffer
, buffersize
, retval
); 
2742         case PROC_PIDFDKQUEUEINFO
: { 
2746                         if ((kqu
.kqwq 
= p
->p_fd
->fd_wqkqueue
) == NULL
) { 
2747                                 /* wqkqueue is initialized on-demand */ 
2751                 } else if ((error 
= fp_get_ftype(p
, fd
, DTYPE_KQUEUE
, EBADF
, &fp
)) != 0) { 
2754                         kqu
.kq 
= fp
->fp_glob
->fg_data
; 
2757                 error 
= pid_kqueueinfo(kqu
.kq
, fp
, p
, fd
, buffer
, buffersize
, retval
); 
2761         case PROC_PIDFDKQUEUE_EXTINFO
: { 
2765                         if ((kqu
.kqwq 
= p
->p_fd
->fd_wqkqueue
) == NULL
) { 
2766                                 /* wqkqueue is initialized on-demand */ 
2770                 } else if ((error 
= fp_get_ftype(p
, fd
, DTYPE_KQUEUE
, EBADF
, &fp
)) != 0) { 
2773                         kqu
.kq 
= fp
->fp_glob
->fg_data
; 
2775                 error 
= pid_kqueue_extinfo(p
, kqu
.kq
, buffer
, buffersize
, retval
); 
2786                 fp_drop(p
, fd
, fp
, 0); 
2794 #define MAX_UPTRS 16392 
2797 proc_pidlistuptrs(proc_t p
, user_addr_t buffer
, uint32_t buffersize
, int32_t *retval
) 
2804         if (buffer 
== USER_ADDR_NULL 
|| buffersize 
< sizeof(uint64_t)) { 
2807                 count 
= MIN(buffersize 
/ sizeof(uint64_t), MAX_UPTRS
); 
2808                 buffersize 
= count 
* sizeof(uint64_t); 
2809                 kbuf 
= kheap_alloc(KHEAP_TEMP
, buffersize
, Z_WAITOK
); 
2812         nuptrs 
= kevent_proc_copy_uptrs(p
, kbuf
, buffersize
); 
2816                 if (os_mul_overflow(nuptrs
, sizeof(uint64_t), ©size
)) { 
2820                 if (copysize 
> buffersize
) { 
2821                         copysize 
= buffersize
; 
2823                 error 
= copyout(kbuf
, buffer
, copysize
); 
2830                 kheap_free(KHEAP_TEMP
, kbuf
, buffersize
); 
2838  * Helper function for proc_pidfileportinfo 
2841 struct fileport_info_args 
{ 
2843         user_addr_t     fia_buffer
; 
2844         uint32_t        fia_buffersize
; 
2845         int32_t         *fia_retval
; 
2848 static kern_return_t
 
2849 proc_fileport_info(__unused mach_port_name_t name
, 
2850     struct fileglob 
*fg
, void *arg
) 
2852         struct fileport_info_args 
*fia 
= arg
; 
2853         struct fileproc __fileproc
, *fp 
= &__fileproc
; 
2856         bzero(fp
, sizeof(*fp
)); 
2859         switch (fia
->fia_flavor
) { 
2860         case PROC_PIDFILEPORTVNODEPATHINFO
: { 
2863                 if (FILEGLOB_DTYPE(fg
) != DTYPE_VNODE
) { 
2867                 vp 
= (struct vnode 
*)fg
->fg_data
; 
2868                 error 
= pid_vnodeinfopath(vp
, fp
, PROC_NULL
, 0, 
2869                     fia
->fia_buffer
, fia
->fia_buffersize
, fia
->fia_retval
); 
2872         case PROC_PIDFILEPORTSOCKETINFO
: { 
2875                 if (FILEGLOB_DTYPE(fg
) != DTYPE_SOCKET
) { 
2879                 so 
= (socket_t
)fg
->fg_data
; 
2880                 error 
= pid_socketinfo(so
, fp
, PROC_NULL
, 0, 
2881                     fia
->fia_buffer
, fia
->fia_buffersize
, fia
->fia_retval
); 
2884         case PROC_PIDFILEPORTPSHMINFO
: { 
2885                 struct pshmnode 
*pshm
; 
2887                 if (FILEGLOB_DTYPE(fg
) != DTYPE_PSXSHM
) { 
2888                         error 
= EBADF
;          /* ick - mirror fp_getfpshm */ 
2891                 pshm 
= (struct pshmnode 
*)fg
->fg_data
; 
2892                 error 
= pid_pshminfo(pshm
, fp
, PROC_NULL
, 0, 
2893                     fia
->fia_buffer
, fia
->fia_buffersize
, fia
->fia_retval
); 
2896         case PROC_PIDFILEPORTPIPEINFO
: { 
2899                 if (FILEGLOB_DTYPE(fg
) != DTYPE_PIPE
) { 
2900                         error 
= EBADF
;          /* ick - mirror fp_getfpipe */ 
2903                 cpipe 
= (struct pipe 
*)fg
->fg_data
; 
2904                 error 
= pid_pipeinfo(cpipe
, fp
, PROC_NULL
, 0, 
2905                     fia
->fia_buffer
, fia
->fia_buffersize
, fia
->fia_retval
); 
2916 /************************* proc_pidfileportinfo routine *********************/ 
2918 proc_pidfileportinfo(int pid
, int flavor
, mach_port_name_t name
, 
2919     user_addr_t buffer
, uint32_t buffersize
, int32_t *retval
) 
2922         int error 
= ENOTSUP
; 
2924         struct fileport_info_args fia
; 
2926         /* fileport types are restricted by file_issendable() */ 
2929         case PROC_PIDFILEPORTVNODEPATHINFO
: 
2930                 size 
= PROC_PIDFILEPORTVNODEPATHINFO_SIZE
; 
2932         case PROC_PIDFILEPORTSOCKETINFO
: 
2933                 size 
= PROC_PIDFILEPORTSOCKETINFO_SIZE
; 
2935         case PROC_PIDFILEPORTPSHMINFO
: 
2936                 size 
= PROC_PIDFILEPORTPSHMINFO_SIZE
; 
2938         case PROC_PIDFILEPORTPIPEINFO
: 
2939                 size 
= PROC_PIDFILEPORTPIPEINFO_SIZE
; 
2945         if (buffersize 
< size
) { 
2948         if ((p 
= proc_find(pid
)) == PROC_NULL
) { 
2953         /* Do we have permission to look into this? */ 
2954         if ((error 
= proc_security_policy(p
, PROC_INFO_CALL_PIDFILEPORTINFO
, flavor
, CHECK_SAME_USER
))) { 
2958         fia
.fia_flavor 
= flavor
; 
2959         fia
.fia_buffer 
= buffer
; 
2960         fia
.fia_buffersize 
= buffersize
; 
2961         fia
.fia_retval 
= retval
; 
2963         if (fileport_invoke(p
->task
, name
, 
2964             proc_fileport_info
, &fia
, &error
) != KERN_SUCCESS
) { 
2974 proc_security_policy(proc_t targetp
, __unused 
int callnum
, __unused 
int flavor
, boolean_t check_same_user
) 
2979         if ((error 
= mac_proc_check_proc_info(current_proc(), targetp
, callnum
, flavor
))) { 
2984         /* The 'listpids' call doesn't have a target proc */ 
2985         if (targetp 
== PROC_NULL
) { 
2986                 assert(callnum 
== PROC_INFO_CALL_LISTPIDS 
&& check_same_user 
== NO_CHECK_SAME_USER
); 
2991          * Check for 'get information for processes owned by other users' privilege 
2992          * root has this privilege by default 
2994         if (priv_check_cred(kauth_cred_get(), PRIV_GLOBAL_PROC_INFO
, 0) == 0) { 
2995                 check_same_user 
= FALSE
; 
2998         if (check_same_user
) { 
2999                 kauth_cred_t target_cred
; 
3002                 target_cred 
= kauth_cred_proc_ref(targetp
); 
3003                 target_uid  
= kauth_cred_getuid(target_cred
); 
3004                 kauth_cred_unref(&target_cred
); 
3006                 if (kauth_getuid() != target_uid
) { 
3015 proc_kernmsgbuf(user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
) 
3020         if ((error 
= mac_system_check_info(kauth_cred_get(), "kern.msgbuf"))) { 
3025         if (suser(kauth_cred_get(), (u_short 
*)0) == 0) { 
3026                 return log_dmesg(buffer
, buffersize
, retval
); 
3032 /* ********* process control sets on self only */ 
3034 proc_setcontrol(int pid
, int flavor
, uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, __unused 
int32_t * retval
) 
3036         struct proc 
* pself 
= PROC_NULL
; 
3038         uint32_t pcontrol 
= (uint32_t)arg
; 
3039         struct uthread 
*ut 
= NULL
; 
3040         char name_buf
[MAXTHREADNAMESIZE
]; 
3042         pself 
= current_proc(); 
3043         if (pid 
!= pself
->p_pid
) { 
3047         /* Do we have permission to look into this? */ 
3048         if ((error 
= proc_security_policy(pself
, PROC_INFO_CALL_SETCONTROL
, flavor
, NO_CHECK_SAME_USER
))) { 
3053         case PROC_SELFSET_PCONTROL
: { 
3054                 if (pcontrol 
> P_PCMAX
) { 
3058                 /* reset existing control setting while retaining action state */ 
3059                 pself
->p_pcaction 
&= PROC_ACTION_MASK
; 
3060                 /* set new control state */ 
3061                 pself
->p_pcaction 
|= pcontrol
; 
3066         case PROC_SELFSET_THREADNAME
: { 
3068                  * This is a bit ugly, as it copies the name into the kernel, and then 
3069                  * invokes bsd_setthreadname again to copy it into the uthread name 
3070                  * buffer.  Hopefully this isn't such a hot codepath that an additional 
3071                  * MAXTHREADNAMESIZE copy is a big issue. 
3073                 if (buffersize 
> (MAXTHREADNAMESIZE 
- 1)) { 
3074                         return ENAMETOOLONG
; 
3077                 ut 
= current_uthread(); 
3079                 bzero(name_buf
, MAXTHREADNAMESIZE
); 
3080                 error 
= copyin(buffer
, name_buf
, buffersize
); 
3083                         bsd_setthreadname(ut
, name_buf
); 
3088         case PROC_SELFSET_VMRSRCOWNER
: { 
3089                 /* need to to be superuser */ 
3090                 if (suser(kauth_cred_get(), (u_short 
*)0) != 0) { 
3096                 /* reset existing control setting while retaining action state */ 
3097                 pself
->p_lflag 
|= P_LVMRSRCOWNER
; 
3102         case PROC_SELFSET_DELAYIDLESLEEP
: { 
3103 #if CONFIG_DELAY_IDLE_SLEEP 
3104                 /* mark or clear the process property to delay idle sleep disk IO */ 
3105                 if (pcontrol 
!= 0) { 
3106                         OSBitOrAtomic(P_DELAYIDLESLEEP
, &pself
->p_flag
); 
3108                         OSBitAndAtomic(~((uint32_t)P_DELAYIDLESLEEP
), &pself
->p_flag
); 
3126 #if CONFIG_MEMORYSTATUS 
3129 proc_dirtycontrol(int pid
, int flavor
, uint64_t arg
, int32_t *retval
) 
3131         struct proc 
*target_p
; 
3133         uint32_t pcontrol 
= (uint32_t)arg
; 
3134         kauth_cred_t my_cred
, target_cred
; 
3135         boolean_t self 
= FALSE
; 
3136         boolean_t child 
= FALSE
; 
3137         boolean_t zombref 
= FALSE
; 
3140         target_p 
= proc_find(pid
); 
3142         if (target_p 
== PROC_NULL
) { 
3143                 if (flavor 
== PROC_DIRTYCONTROL_GET
) { 
3144                         target_p 
= proc_find_zombref(pid
); 
3148                 if (target_p 
== PROC_NULL
) { 
3153         my_cred 
= kauth_cred_get(); 
3154         target_cred 
= kauth_cred_proc_ref(target_p
); 
3156         /* Do we have permission to look into this? */ 
3157         if ((error 
= proc_security_policy(target_p
, PROC_INFO_CALL_DIRTYCONTROL
, flavor
, NO_CHECK_SAME_USER
))) { 
3161         selfpid 
= proc_selfpid(); 
3162         if (pid 
== selfpid
) { 
3164         } else if (target_p
->p_ppid 
== selfpid
) { 
3169         case PROC_DIRTYCONTROL_TRACK
: { 
3170                 /* Only allow the process itself, its parent, or root */ 
3171                 if ((self 
== FALSE
) && (child 
== FALSE
) && kauth_cred_issuser(kauth_cred_get()) != TRUE
) { 
3176                 error 
= memorystatus_dirty_track(target_p
, pcontrol
); 
3180         case PROC_DIRTYCONTROL_SET
: { 
3181                 /* Check privileges; use cansignal() here since the process could be terminated */ 
3182                 if (!cansignal(current_proc(), my_cred
, target_p
, SIGKILL
)) { 
3187                 error 
= memorystatus_dirty_set(target_p
, self
, pcontrol
); 
3191         case PROC_DIRTYCONTROL_GET
: { 
3192                 /* No permissions check - dirty state is freely available */ 
3194                         *retval 
= memorystatus_dirty_get(target_p
, FALSE
); 
3201         case PROC_DIRTYCONTROL_CLEAR
: { 
3202                 /* Check privileges; use cansignal() here since the process could be terminated */ 
3203                 if (!cansignal(current_proc(), my_cred
, target_p
, SIGKILL
)) { 
3208                 error 
= memorystatus_dirty_clear(target_p
, pcontrol
); 
3215                 proc_drop_zombref(target_p
); 
3217                 proc_rele(target_p
); 
3220         kauth_cred_unref(&target_cred
); 
3227 proc_dirtycontrol(__unused 
int pid
, __unused 
int flavor
, __unused 
uint64_t arg
, __unused 
int32_t *retval
) 
3232 #endif /* CONFIG_MEMORYSTATUS */ 
3235  * proc_terminate() provides support for sudden termination. 
3236  * SIGKILL is issued to tracked, clean processes; otherwise, 
3241 proc_terminate(int pid
, int32_t *retval
) 
3245         kauth_cred_t uc 
= kauth_cred_get(); 
3249         /* XXX: Check if these are necessary */ 
3250         AUDIT_ARG(pid
, pid
); 
3251         AUDIT_ARG(signum
, sig
); 
3254         if (pid 
<= 0 || retval 
== NULL
) { 
3258         if ((p 
= proc_find(pid
)) == NULL
) { 
3263         /* XXX: Check if these are necessary */ 
3264         AUDIT_ARG(process
, p
); 
3267         /* Check privileges; if SIGKILL can be issued, then SIGTERM is also OK */ 
3268         if (!cansignal(current_proc(), uc
, p
, SIGKILL
)) { 
3273         /* Not allowed to sudden terminate yourself */ 
3274         if (p 
== current_proc()) { 
3279 #if CONFIG_MEMORYSTATUS 
3280         /* Determine requisite signal to issue */ 
3281         sig 
= memorystatus_on_terminate(p
); 
3286         proc_set_task_policy(p
->task
, TASK_POLICY_ATTRIBUTE
, 
3287             TASK_POLICY_TERMINATED
, TASK_POLICY_ENABLE
); 
3299  * copy stat64 structure into vinfo_stat structure. 
3302 munge_vinfo_stat(struct stat64 
*sbp
, struct vinfo_stat 
*vsbp
) 
3304         bzero(vsbp
, sizeof(struct vinfo_stat
)); 
3306         vsbp
->vst_dev 
= sbp
->st_dev
; 
3307         vsbp
->vst_mode 
= sbp
->st_mode
; 
3308         vsbp
->vst_nlink 
= sbp
->st_nlink
; 
3309         vsbp
->vst_ino 
= sbp
->st_ino
; 
3310         vsbp
->vst_uid 
= sbp
->st_uid
; 
3311         vsbp
->vst_gid 
= sbp
->st_gid
; 
3312         vsbp
->vst_atime 
= sbp
->st_atimespec
.tv_sec
; 
3313         vsbp
->vst_atimensec 
= sbp
->st_atimespec
.tv_nsec
; 
3314         vsbp
->vst_mtime 
= sbp
->st_mtimespec
.tv_sec
; 
3315         vsbp
->vst_mtimensec 
= sbp
->st_mtimespec
.tv_nsec
; 
3316         vsbp
->vst_ctime 
= sbp
->st_ctimespec
.tv_sec
; 
3317         vsbp
->vst_ctimensec 
= sbp
->st_ctimespec
.tv_nsec
; 
3318         vsbp
->vst_birthtime 
= sbp
->st_birthtimespec
.tv_sec
; 
3319         vsbp
->vst_birthtimensec 
= sbp
->st_birthtimespec
.tv_nsec
; 
3320         vsbp
->vst_size 
= sbp
->st_size
; 
3321         vsbp
->vst_blocks 
= sbp
->st_blocks
; 
3322         vsbp
->vst_blksize 
= sbp
->st_blksize
; 
3323         vsbp
->vst_flags 
= sbp
->st_flags
; 
3324         vsbp
->vst_gen 
= sbp
->st_gen
; 
3325         vsbp
->vst_rdev 
= sbp
->st_rdev
; 
3326         vsbp
->vst_qspare
[0] = sbp
->st_qspare
[0]; 
3327         vsbp
->vst_qspare
[1] = sbp
->st_qspare
[1]; 
3331 proc_pid_rusage(int pid
, int flavor
, user_addr_t buffer
, __unused 
int32_t *retval
) 
3337         if ((p 
= proc_find(pid
)) == PROC_NULL
) { 
3338                 if ((p 
= proc_find_zombref(pid
)) == PROC_NULL
) { 
3344         /* Do we have permission to look into this? */ 
3345         if ((error 
= proc_security_policy(p
, PROC_INFO_CALL_PIDRUSAGE
, flavor
, CHECK_SAME_USER
))) { 
3349         error 
= proc_get_rusage(p
, flavor
, buffer
, zombie
); 
3353                 proc_drop_zombref(p
); 
3362 proc_archinfo(proc_t p
, struct proc_archinfo 
*pai
) 
3366                 pai
->p_cputype 
= p
->p_cputype
; 
3367                 pai
->p_cpusubtype 
= p
->p_cpusubtype
; 
3373 proc_pidcoalitioninfo(proc_t p
, struct proc_pidcoalitioninfo 
*ppci
) 
3375         bzero(ppci
, sizeof(*ppci
)); 
3376         proc_coalitionids(p
, ppci
->coalition_id
); 
3380 proc_pidexitreasoninfo(proc_t p
, struct proc_exitreasoninfo 
*peri
, struct proc_exitreasonbasicinfo 
*pberi
) 
3382         uint32_t reason_data_size 
= 0; 
3384         pid_t selfpid 
= proc_selfpid(); 
3389          * One (and only one) of peri and pberi must be non-NULL. 
3391         assert((peri 
!= NULL
) || (pberi 
!= NULL
)); 
3392         assert((peri 
== NULL
) || (pberi 
== NULL
)); 
3395          * Allow access to the parent of the exiting 
3396          * child or the parent debugger only. 
3399                 if (p
->p_ppid 
== selfpid
) { 
3400                         break;  /* parent => ok */ 
3402                 if ((p
->p_lflag 
& P_LTRACED
) != 0 && 
3403                     (p
->p_oppid 
== selfpid
)) { 
3404                         break;  /* parent-in-waiting => ok */ 
3410         if (p
->p_exit_reason 
== OS_REASON_NULL
) { 
3415         if (p
->p_exit_reason
->osr_kcd_buf 
!= NULL
) { 
3416                 reason_data_size 
= (uint32_t)kcdata_memory_get_used_bytes(&p
->p_exit_reason
->osr_kcd_descriptor
); 
3420                 peri
->eri_namespace 
= p
->p_exit_reason
->osr_namespace
; 
3421                 peri
->eri_code 
= p
->p_exit_reason
->osr_code
; 
3422                 peri
->eri_flags 
= p
->p_exit_reason
->osr_flags
; 
3424                 if ((peri
->eri_kcd_buf 
== 0) || (peri
->eri_reason_buf_size 
< reason_data_size
)) { 
3429                 peri
->eri_reason_buf_size 
= reason_data_size
; 
3430                 if (reason_data_size 
!= 0) { 
3431                         error 
= copyout(p
->p_exit_reason
->osr_kcd_buf
, (user_addr_t
)peri
->eri_kcd_buf
, reason_data_size
); 
3434                 pberi
->beri_namespace 
=  p
->p_exit_reason
->osr_namespace
; 
3435                 pberi
->beri_code 
= p
->p_exit_reason
->osr_code
; 
3436                 pberi
->beri_flags 
= p
->p_exit_reason
->osr_flags
; 
3437                 pberi
->beri_reason_buf_size 
= reason_data_size
; 
3446  * Wrapper to provide NOTE_EXIT_DETAIL and NOTE_EXITSTATUS 
3447  * It mimics the data that is typically captured by the 
3448  * EVFILT_PROC, NOTE_EXIT event mechanism. 
3449  * See filt_proc() in kern_event.c. 
3452 proc_pidnoteexit(proc_t p
, uint64_t flags
, uint32_t *data
) 
3454         uint32_t exit_data 
= 0; 
3455         uint32_t exit_flags 
= (uint32_t)flags
; 
3460          * Allow access to the parent of the exiting 
3461          * child or the parent debugger only. 
3464                 pid_t selfpid 
= proc_selfpid(); 
3466                 if (p
->p_ppid 
== selfpid
) { 
3467                         break;  /* parent => ok */ 
3469                 if ((p
->p_lflag 
& P_LTRACED
) != 0 && 
3470                     (p
->p_oppid 
== selfpid
)) { 
3471                         break;  /* parent-in-waiting => ok */ 
3477         if ((exit_flags 
& NOTE_EXITSTATUS
) != 0) { 
3478                 /* The signal and exit status */ 
3479                 exit_data 
|= (p
->p_xstat 
& NOTE_PDATAMASK
); 
3482         if ((exit_flags 
& NOTE_EXIT_DETAIL
) != 0) { 
3483                 /* The exit detail */ 
3484                 if ((p
->p_lflag 
& P_LTERM_DECRYPTFAIL
) != 0) { 
3485                         exit_data 
|= NOTE_EXIT_DECRYPTFAIL
; 
3488                 if ((p
->p_lflag 
& P_LTERM_JETSAM
) != 0) { 
3489                         exit_data 
|= NOTE_EXIT_MEMORY
; 
3491                         switch (p
->p_lflag 
& P_JETSAM_MASK
) { 
3492                         case P_JETSAM_VMPAGESHORTAGE
: 
3493                                 exit_data 
|= NOTE_EXIT_MEMORY_VMPAGESHORTAGE
; 
3495                         case P_JETSAM_VMTHRASHING
: 
3496                                 exit_data 
|= NOTE_EXIT_MEMORY_VMTHRASHING
; 
3498                         case P_JETSAM_FCTHRASHING
: 
3499                                 exit_data 
|= NOTE_EXIT_MEMORY_FCTHRASHING
; 
3501                         case P_JETSAM_VNODE
: 
3502                                 exit_data 
|= NOTE_EXIT_MEMORY_VNODE
; 
3504                         case P_JETSAM_HIWAT
: 
3505                                 exit_data 
|= NOTE_EXIT_MEMORY_HIWAT
; 
3508                                 exit_data 
|= NOTE_EXIT_MEMORY_PID
; 
3510                         case P_JETSAM_IDLEEXIT
: 
3511                                 exit_data 
|= NOTE_EXIT_MEMORY_IDLE
; 
3516                 if ((p
->p_csflags 
& CS_KILLED
) != 0) { 
3517                         exit_data 
|= NOTE_EXIT_CSERROR
; 
3529 proc_piddynkqueueinfo(int pid
, int flavor
, kqueue_id_t kq_id
, 
3530     user_addr_t ubuf
, uint32_t bufsize
, int32_t *retval
) 
3535         if (ubuf 
== USER_ADDR_NULL
) { 
3540         if (p 
== PROC_NULL
) { 
3544         err 
= proc_security_policy(p
, PROC_INFO_CALL_PIDDYNKQUEUEINFO
, 0, CHECK_SAME_USER
); 
3550         case PROC_PIDDYNKQUEUE_INFO
: 
3551                 err 
= kevent_copyout_dynkqinfo(p
, kq_id
, ubuf
, bufsize
, retval
); 
3553         case PROC_PIDDYNKQUEUE_EXTINFO
: 
3554                 err 
= kevent_copyout_dynkqextinfo(p
, kq_id
, ubuf
, bufsize
, retval
); 
3567 #if CONFIG_PROC_UDATA_STORAGE 
3569 proc_udata_info(int pid
, int flavor
, user_addr_t buffer
, uint32_t bufsize
, int32_t *retval
) 
3575         if (p 
== PROC_NULL
) { 
3580          * Only support calls against oneself for the moment. 
3582         if (p
->p_pid 
!= proc_selfpid()) { 
3587         if (bufsize 
!= sizeof(p
->p_user_data
)) { 
3593         case PROC_UDATA_INFO_SET
: 
3594                 err 
= copyin(buffer
, &p
->p_user_data
, sizeof(p
->p_user_data
)); 
3596         case PROC_UDATA_INFO_GET
: 
3597                 err 
= copyout(&p
->p_user_data
, buffer
, sizeof(p
->p_user_data
)); 
3613 #endif /* CONFIG_PROC_UDATA_STORAGE */