2 * Copyright (c) 2005-2013 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/kernel.h>
36 #include <sys/malloc.h>
37 #include <sys/proc_internal.h>
38 #include <sys/kauth.h>
39 #include <sys/file_internal.h>
40 #include <sys/vnode_internal.h>
41 #include <sys/unistd.h>
43 #include <sys/ioctl.h>
44 #include <sys/namei.h>
46 #include <sys/disklabel.h>
48 #include <sys/sysctl.h>
50 #include <sys/aio_kern.h>
51 #include <sys/kern_memorystatus.h>
53 #include <security/audit/audit.h>
55 #include <mach/machine.h>
56 #include <mach/mach_types.h>
57 #include <mach/vm_param.h>
58 #include <kern/task.h>
59 #include <kern/lock.h>
60 #include <kern/kalloc.h>
61 #include <kern/assert.h>
62 #include <vm/vm_kern.h>
63 #include <vm/vm_map.h>
64 #include <mach/host_info.h>
65 #include <mach/task_info.h>
66 #include <mach/thread_info.h>
67 #include <mach/vm_region.h>
69 #include <sys/mount_internal.h>
70 #include <sys/proc_info.h>
71 #include <sys/bsdtask_info.h>
72 #include <sys/kdebug.h>
73 #include <sys/sysproto.h>
74 #include <sys/msgbuf.h>
77 #include <sys/guarded.h>
79 #include <machine/machine_routines.h>
81 #include <kern/ipc_misc.h>
83 #include <vm/vm_protos.h>
91 uint64_t get_dispatchqueue_offset_from_proc(void *);
92 uint64_t get_dispatchqueue_serialno_offset_from_proc(void *);
93 int proc_info_internal(int callnum
, int pid
, int flavor
, uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
);
95 /* protos for proc_info calls */
96 int proc_listpids(uint32_t type
, uint32_t tyoneinfo
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
);
97 int proc_pidinfo(int pid
, int flavor
, uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
);
98 int proc_pidfdinfo(int pid
, int flavor
,int fd
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
);
99 int proc_kernmsgbuf(user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
);
100 int proc_setcontrol(int pid
, int flavor
, uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
);
101 int proc_pidfileportinfo(int pid
, int flavor
, mach_port_name_t name
, user_addr_t buffer
, uint32_t buffersize
, int32_t *retval
);
102 int proc_dirtycontrol(int pid
, int flavor
, uint64_t arg
, int32_t * retval
);
103 int proc_terminate(int pid
, int32_t * retval
);
104 int proc_pid_rusage(int pid
, int flavor
, user_addr_t buffer
, int32_t * retval
);
106 /* protos for procpidinfo calls */
107 int proc_pidfdlist(proc_t p
, user_addr_t buffer
, uint32_t buffersize
, int32_t *retval
);
108 int proc_pidbsdinfo(proc_t p
, struct proc_bsdinfo
*pbsd
, int zombie
);
109 int proc_pidshortbsdinfo(proc_t p
, struct proc_bsdshortinfo
*pbsd_shortp
, int zombie
);
110 int proc_pidtaskinfo(proc_t p
, struct proc_taskinfo
*ptinfo
);
111 int proc_pidallinfo(proc_t p
, int flavor
, uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, int32_t *retval
);
112 int proc_pidthreadinfo(proc_t p
, uint64_t arg
, int thuniqueid
, struct proc_threadinfo
*pthinfo
);
113 int proc_pidthreadpathinfo(proc_t p
, uint64_t arg
, struct proc_threadwithpathinfo
*pinfo
);
114 int proc_pidlistthreads(proc_t p
, user_addr_t buffer
, uint32_t buffersize
, int32_t *retval
);
115 int proc_pidregioninfo(proc_t p
, uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, int32_t *retval
);
116 int proc_pidregionpathinfo(proc_t p
, uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, int32_t *retval
);
117 int proc_pidvnodepathinfo(proc_t p
, uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, int32_t *retval
);
118 int proc_pidpathinfo(proc_t p
, uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, int32_t *retval
);
119 int proc_pidworkqueueinfo(proc_t p
, struct proc_workqueueinfo
*pwqinfo
);
120 int proc_pidfileportlist(proc_t p
, user_addr_t buffer
, uint32_t buffersize
, int32_t *retval
);
121 void proc_piduniqidentifierinfo(proc_t p
, struct proc_uniqidentifierinfo
*p_uniqidinfo
);
124 /* protos for proc_pidfdinfo calls */
125 int pid_vnodeinfo(vnode_t vp
, uint32_t vid
, struct fileproc
* fp
, int closeonexec
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
);
126 int pid_vnodeinfopath(vnode_t vp
, uint32_t vid
, struct fileproc
* fp
, int closeonexec
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
);
127 int pid_socketinfo(socket_t so
, struct fileproc
*fp
, int closeonexec
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
);
128 int pid_pseminfo(struct psemnode
* psem
, struct fileproc
* fp
, int closeonexec
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
);
129 int pid_pshminfo(struct pshmnode
* pshm
, struct fileproc
* fp
, int closeonexec
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
);
130 int pid_pipeinfo(struct pipe
* p
, struct fileproc
* fp
, int closeonexec
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
);
131 int pid_kqueueinfo(struct kqueue
* kq
, struct fileproc
* fp
, int closeonexec
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
);
132 int pid_atalkinfo(struct atalk
* at
, struct fileproc
* fp
, int closeonexec
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
);
135 /* protos for misc */
137 int fill_vnodeinfo(vnode_t vp
, struct vnode_info
*vinfo
);
138 void fill_fileinfo(struct fileproc
* fp
, int closeonexec
, struct proc_fileinfo
* finfo
);
139 int proc_security_policy(proc_t targetp
, int callnum
, int flavor
, boolean_t check_same_user
);
140 static void munge_vinfo_stat(struct stat64
*sbp
, struct vinfo_stat
*vsbp
);
142 extern int cansignal(struct proc
*, kauth_cred_t
, struct proc
*, int, int);
143 extern int proc_get_rusage(proc_t proc
, int flavor
, user_addr_t buffer
, int is_zombie
);
145 #define CHECK_SAME_USER TRUE
146 #define NO_CHECK_SAME_USER FALSE
148 uint64_t get_dispatchqueue_offset_from_proc(void *p
)
151 proc_t pself
= (proc_t
)p
;
152 return (pself
->p_dispatchqueue_offset
);
158 uint64_t get_dispatchqueue_serialno_offset_from_proc(void *p
)
161 proc_t pself
= (proc_t
)p
;
162 return (pself
->p_dispatchqueue_serialno_offset
);
168 /***************************** proc_info ********************/
171 proc_info(__unused
struct proc
*p
, struct proc_info_args
* uap
, int32_t *retval
)
173 return(proc_info_internal(uap
->callnum
, uap
->pid
, uap
->flavor
, uap
->arg
, uap
->buffer
, uap
->buffersize
, retval
));
178 proc_info_internal(int callnum
, int pid
, int flavor
, uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
)
182 case PROC_INFO_CALL_LISTPIDS
:
183 /* pid contains type and flavor contains typeinfo */
184 return(proc_listpids(pid
, flavor
, buffer
, buffersize
, retval
));
185 case PROC_INFO_CALL_PIDINFO
:
186 return(proc_pidinfo(pid
, flavor
, arg
, buffer
, buffersize
, retval
));
187 case PROC_INFO_CALL_PIDFDINFO
:
188 return(proc_pidfdinfo(pid
, flavor
, (int)arg
, buffer
, buffersize
, retval
));
189 case PROC_INFO_CALL_KERNMSGBUF
:
190 return(proc_kernmsgbuf(buffer
, buffersize
, retval
));
191 case PROC_INFO_CALL_SETCONTROL
:
192 return(proc_setcontrol(pid
, flavor
, arg
, buffer
, buffersize
, retval
));
193 case PROC_INFO_CALL_PIDFILEPORTINFO
:
194 return(proc_pidfileportinfo(pid
, flavor
, (mach_port_name_t
)arg
, buffer
, buffersize
, retval
));
195 case PROC_INFO_CALL_TERMINATE
:
196 return(proc_terminate(pid
, retval
));
197 case PROC_INFO_CALL_DIRTYCONTROL
:
198 return(proc_dirtycontrol(pid
, flavor
, arg
, retval
));
199 case PROC_INFO_CALL_PIDRUSAGE
:
200 return (proc_pid_rusage(pid
, flavor
, buffer
, retval
));
208 /******************* proc_listpids routine ****************/
210 proc_listpids(uint32_t type
, uint32_t typeinfo
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
)
212 int numprocs
, wantpids
;
219 struct proclist
*current_list
;
221 /* Do we have permission to look into this? */
222 if ((error
= proc_security_policy(PROC_NULL
, PROC_INFO_CALL_LISTPIDS
, type
, NO_CHECK_SAME_USER
)))
225 /* if the buffer is null, return num of procs */
226 if (buffer
== (user_addr_t
)0) {
227 *retval
= ((nprocs
+20) * sizeof(int));
231 if (buffersize
< sizeof(int)) {
234 wantpids
= buffersize
/sizeof(int);
235 numprocs
= nprocs
+20;
236 if (numprocs
> wantpids
)
239 kbuf
= (char *)kalloc((vm_size_t
)(numprocs
* sizeof(int)));
242 bzero(kbuf
, sizeof(int));
249 current_list
= &allproc
;
251 LIST_FOREACH(p
, current_list
, p_list
) {
255 if (p
->p_pgrpid
!= (pid_t
)typeinfo
)
259 if ((p
->p_ppid
!= (pid_t
)typeinfo
) && (((p
->p_lflag
& P_LTRACED
) == 0) || (p
->p_oppid
!= (pid_t
)typeinfo
)))
267 /* racy but list lock is held */
268 if ((p
->p_flag
& P_CONTROLT
) == 0 ||
269 (p
->p_pgrp
== NULL
) || (p
->p_pgrp
->pg_session
== NULL
) ||
270 (tp
= SESSION_TP(p
->p_pgrp
->pg_session
)) == TTY_NULL
||
271 tp
->t_dev
!= (dev_t
)typeinfo
)
275 if (p
->p_ucred
== NULL
)
278 kauth_cred_t my_cred
;
281 my_cred
= kauth_cred_proc_ref(p
);
282 uid
= kauth_cred_getuid(my_cred
);
283 kauth_cred_unref(&my_cred
);
284 if (uid
!= (uid_t
)typeinfo
)
289 if (p
->p_ucred
== NULL
)
292 kauth_cred_t my_cred
;
295 my_cred
= kauth_cred_proc_ref(p
);
296 uid
= kauth_cred_getruid(my_cred
);
297 kauth_cred_unref(&my_cred
);
298 if (uid
!= (uid_t
)typeinfo
)
315 if ((n
< numprocs
) && (current_list
== &allproc
)) {
316 current_list
= &zombproc
;
323 error
= copyout((caddr_t
)ptr
, buffer
, n
* sizeof(int));
325 *retval
= (n
* sizeof(int));
326 kfree((void *)kbuf
, (vm_size_t
)(numprocs
* sizeof(int)));
332 /********************************** proc_pidinfo routines ********************************/
335 proc_pidfdlist(proc_t p
, user_addr_t buffer
, uint32_t buffersize
, int32_t *retval
)
339 struct proc_fdinfo
* pfd
;
340 struct fileproc
* fp
;
345 numfds
= p
->p_fd
->fd_nfiles
;
347 if (buffer
== (user_addr_t
) 0) {
349 *retval
= (numfds
* sizeof(struct proc_fdinfo
));
353 /* buffersize is big enough atleast for one struct */
354 needfds
= buffersize
/sizeof(struct proc_fdinfo
);
356 if (numfds
> needfds
)
359 kbuf
= (char *)kalloc((vm_size_t
)(numfds
* sizeof(struct proc_fdinfo
)));
362 bzero(kbuf
, numfds
* sizeof(struct proc_fdinfo
));
366 pfd
= (struct proc_fdinfo
*)kbuf
;
368 for (n
= 0; ((n
< numfds
) && (n
< p
->p_fd
->fd_nfiles
)); n
++) {
369 if (((fp
= p
->p_fd
->fd_ofiles
[n
]) != 0)
370 && ((p
->p_fd
->fd_ofileflags
[n
] & UF_RESERVED
) == 0)) {
371 file_type_t fdtype
= FILEGLOB_DTYPE(fp
->f_fglob
);
373 pfd
->proc_fdtype
= (fdtype
!= DTYPE_ATALK
) ?
374 fdtype
: PROX_FDTYPE_ATALK
;
381 error
= copyout(kbuf
, buffer
, count
* sizeof(struct proc_fdinfo
));
382 kfree((void *)kbuf
, (vm_size_t
)(numfds
* sizeof(struct proc_fdinfo
)));
384 *retval
= (count
* sizeof(struct proc_fdinfo
));
389 * Helper functions for proc_pidfileportlist.
392 proc_fileport_count(__unused mach_port_name_t name
,
393 __unused
struct fileglob
*fg
, void *arg
)
395 uint32_t *counter
= arg
;
401 struct fileport_fdtype_args
{
402 struct proc_fileportinfo
*ffa_pfi
;
403 struct proc_fileportinfo
*ffa_pfi_end
;
407 proc_fileport_fdtype(mach_port_name_t name
, struct fileglob
*fg
, void *arg
)
409 struct fileport_fdtype_args
*ffa
= arg
;
411 if (ffa
->ffa_pfi
!= ffa
->ffa_pfi_end
) {
412 file_type_t fdtype
= FILEGLOB_DTYPE(fg
);
414 ffa
->ffa_pfi
->proc_fdtype
= (fdtype
!= DTYPE_ATALK
) ?
415 fdtype
: PROX_FDTYPE_ATALK
;
416 ffa
->ffa_pfi
->proc_fileport
= name
;
418 return (0); /* keep walking */
420 return (-1); /* stop the walk! */
424 proc_pidfileportlist(proc_t p
,
425 user_addr_t buffer
, uint32_t buffersize
, int32_t *retval
)
429 struct proc_fileportinfo
*pfi
;
430 uint32_t needfileports
, numfileports
;
431 struct fileport_fdtype_args ffa
;
434 needfileports
= buffersize
/ sizeof (*pfi
);
435 if ((user_addr_t
)0 == buffer
|| needfileports
> (uint32_t)maxfiles
) {
437 * Either (i) the user is asking for a fileport count,
438 * or (ii) the number of fileports they're asking for is
439 * larger than the maximum number of open files (!); count
440 * them to bound subsequent heap allocations.
443 switch (fileport_walk(p
->task
,
444 proc_fileport_count
, &numfileports
)) {
447 case KERN_RESOURCE_SHORTAGE
:
449 case KERN_INVALID_TASK
:
455 if (numfileports
== 0) {
456 *retval
= 0; /* none at all, bail */
459 if ((user_addr_t
)0 == buffer
) {
460 numfileports
+= 20; /* accelerate convergence */
461 *retval
= numfileports
* sizeof (*pfi
);
464 if (needfileports
> numfileports
)
465 needfileports
= numfileports
;
468 assert(buffersize
>= PROC_PIDLISTFILEPORTS_SIZE
);
470 kbufsize
= (vm_size_t
)needfileports
* sizeof (*pfi
);
471 pfi
= kbuf
= kalloc(kbufsize
);
474 bzero(kbuf
, kbufsize
);
477 ffa
.ffa_pfi_end
= pfi
+ needfileports
;
479 switch (fileport_walk(p
->task
, proc_fileport_fdtype
, &ffa
)) {
483 if ((numfileports
= pfi
- (typeof(pfi
))kbuf
) == 0)
485 if (numfileports
> needfileports
)
486 panic("more fileports returned than requested");
487 error
= copyout(kbuf
, buffer
, numfileports
* sizeof (*pfi
));
489 case KERN_RESOURCE_SHORTAGE
:
492 case KERN_INVALID_TASK
:
499 kfree(kbuf
, kbufsize
);
501 *retval
= numfileports
* sizeof (*pfi
);
506 proc_pidbsdinfo(proc_t p
, struct proc_bsdinfo
* pbsd
, int zombie
)
508 register struct tty
*tp
;
509 struct session
*sessionp
= NULL
;
511 kauth_cred_t my_cred
;
514 sessionp
= proc_session(p
);
516 my_cred
= kauth_cred_proc_ref(p
);
517 bzero(pbsd
, sizeof(struct proc_bsdinfo
));
518 pbsd
->pbi_status
= p
->p_stat
;
519 pbsd
->pbi_xstatus
= p
->p_xstat
;
520 pbsd
->pbi_pid
= p
->p_pid
;
521 pbsd
->pbi_ppid
= p
->p_ppid
;
522 pbsd
->pbi_uid
= kauth_cred_getuid(my_cred
);
523 pbsd
->pbi_gid
= kauth_cred_getgid(my_cred
);
524 pbsd
->pbi_ruid
= kauth_cred_getruid(my_cred
);
525 pbsd
->pbi_rgid
= kauth_cred_getrgid(my_cred
);
526 pbsd
->pbi_svuid
= kauth_cred_getsvuid(my_cred
);
527 pbsd
->pbi_svgid
= kauth_cred_getsvgid(my_cred
);
528 kauth_cred_unref(&my_cred
);
530 pbsd
->pbi_nice
= p
->p_nice
;
531 pbsd
->pbi_start_tvsec
= p
->p_start
.tv_sec
;
532 pbsd
->pbi_start_tvusec
= p
->p_start
.tv_usec
;
533 bcopy(&p
->p_comm
, &pbsd
->pbi_comm
[0], MAXCOMLEN
);
534 pbsd
->pbi_comm
[MAXCOMLEN
- 1] = '\0';
535 bcopy(&p
->p_name
, &pbsd
->pbi_name
[0], 2*MAXCOMLEN
);
536 pbsd
->pbi_name
[(2*MAXCOMLEN
) - 1] = '\0';
539 if ((p
->p_flag
& P_SYSTEM
) == P_SYSTEM
)
540 pbsd
->pbi_flags
|= PROC_FLAG_SYSTEM
;
541 if ((p
->p_lflag
& P_LTRACED
) == P_LTRACED
)
542 pbsd
->pbi_flags
|= PROC_FLAG_TRACED
;
543 if ((p
->p_lflag
& P_LEXIT
) == P_LEXIT
)
544 pbsd
->pbi_flags
|= PROC_FLAG_INEXIT
;
545 if ((p
->p_lflag
& P_LPPWAIT
) == P_LPPWAIT
)
546 pbsd
->pbi_flags
|= PROC_FLAG_PPWAIT
;
547 if ((p
->p_flag
& P_LP64
) == P_LP64
)
548 pbsd
->pbi_flags
|= PROC_FLAG_LP64
;
549 if ((p
->p_flag
& P_CONTROLT
) == P_CONTROLT
)
550 pbsd
->pbi_flags
|= PROC_FLAG_CONTROLT
;
551 if ((p
->p_flag
& P_THCWD
) == P_THCWD
)
552 pbsd
->pbi_flags
|= PROC_FLAG_THCWD
;
553 if ((p
->p_flag
& P_SUGID
) == P_SUGID
)
554 pbsd
->pbi_flags
|= PROC_FLAG_PSUGID
;
555 if ((p
->p_flag
& P_EXEC
) == P_EXEC
)
556 pbsd
->pbi_flags
|= PROC_FLAG_EXEC
;
558 if (sessionp
!= SESSION_NULL
) {
559 if (SESS_LEADER(p
, sessionp
))
560 pbsd
->pbi_flags
|= PROC_FLAG_SLEADER
;
561 if (sessionp
->s_ttyvp
)
562 pbsd
->pbi_flags
|= PROC_FLAG_CTTY
;
565 if ((p
->p_flag
& P_DELAYIDLESLEEP
) == P_DELAYIDLESLEEP
)
566 pbsd
->pbi_flags
|= PROC_FLAG_DELAYIDLESLEEP
;
568 switch(PROC_CONTROL_STATE(p
)) {
570 pbsd
->pbi_flags
|= PROC_FLAG_PC_THROTTLE
;
573 pbsd
->pbi_flags
|= PROC_FLAG_PC_SUSP
;
576 pbsd
->pbi_flags
|= PROC_FLAG_PC_KILL
;
580 switch(PROC_ACTION_STATE(p
)) {
582 pbsd
->pbi_flags
|= PROC_FLAG_PA_THROTTLE
;
585 pbsd
->pbi_flags
|= PROC_FLAG_PA_SUSP
;
589 /* if process is a zombie skip bg state */
590 if ((zombie
== 0) && (p
->p_stat
!= SZOMB
) && (p
->task
!= TASK_NULL
))
591 proc_get_darwinbgstate(p
->task
, &pbsd
->pbi_flags
);
594 pbsd
->pbi_nfiles
= p
->p_fd
->fd_nfiles
;
596 pbsd
->e_tdev
= NODEV
;
597 if (pg
!= PGRP_NULL
) {
598 pbsd
->pbi_pgid
= p
->p_pgrpid
;
599 pbsd
->pbi_pjobc
= pg
->pg_jobc
;
600 if ((p
->p_flag
& P_CONTROLT
) && (sessionp
!= SESSION_NULL
) && (tp
= SESSION_TP(sessionp
))) {
601 pbsd
->e_tdev
= tp
->t_dev
;
602 pbsd
->e_tpgid
= sessionp
->s_ttypgrpid
;
605 if (sessionp
!= SESSION_NULL
)
606 session_rele(sessionp
);
615 proc_pidshortbsdinfo(proc_t p
, struct proc_bsdshortinfo
* pbsd_shortp
, int zombie
)
617 bzero(pbsd_shortp
, sizeof(struct proc_bsdshortinfo
));
618 pbsd_shortp
->pbsi_pid
= p
->p_pid
;
619 pbsd_shortp
->pbsi_ppid
= p
->p_ppid
;
620 pbsd_shortp
->pbsi_pgid
= p
->p_pgrpid
;
621 pbsd_shortp
->pbsi_status
= p
->p_stat
;
622 bcopy(&p
->p_comm
, &pbsd_shortp
->pbsi_comm
[0], MAXCOMLEN
);
623 pbsd_shortp
->pbsi_comm
[MAXCOMLEN
- 1] = '\0';
625 pbsd_shortp
->pbsi_flags
= 0;
626 if ((p
->p_flag
& P_SYSTEM
) == P_SYSTEM
)
627 pbsd_shortp
->pbsi_flags
|= PROC_FLAG_SYSTEM
;
628 if ((p
->p_lflag
& P_LTRACED
) == P_LTRACED
)
629 pbsd_shortp
->pbsi_flags
|= PROC_FLAG_TRACED
;
630 if ((p
->p_lflag
& P_LEXIT
) == P_LEXIT
)
631 pbsd_shortp
->pbsi_flags
|= PROC_FLAG_INEXIT
;
632 if ((p
->p_lflag
& P_LPPWAIT
) == P_LPPWAIT
)
633 pbsd_shortp
->pbsi_flags
|= PROC_FLAG_PPWAIT
;
634 if ((p
->p_flag
& P_LP64
) == P_LP64
)
635 pbsd_shortp
->pbsi_flags
|= PROC_FLAG_LP64
;
636 if ((p
->p_flag
& P_CONTROLT
) == P_CONTROLT
)
637 pbsd_shortp
->pbsi_flags
|= PROC_FLAG_CONTROLT
;
638 if ((p
->p_flag
& P_THCWD
) == P_THCWD
)
639 pbsd_shortp
->pbsi_flags
|= PROC_FLAG_THCWD
;
640 if ((p
->p_flag
& P_SUGID
) == P_SUGID
)
641 pbsd_shortp
->pbsi_flags
|= PROC_FLAG_PSUGID
;
642 if ((p
->p_flag
& P_EXEC
) == P_EXEC
)
643 pbsd_shortp
->pbsi_flags
|= PROC_FLAG_EXEC
;
644 if ((p
->p_flag
& P_DELAYIDLESLEEP
) == P_DELAYIDLESLEEP
)
645 pbsd_shortp
->pbsi_flags
|= PROC_FLAG_DELAYIDLESLEEP
;
647 switch(PROC_CONTROL_STATE(p
)) {
649 pbsd_shortp
->pbsi_flags
|= PROC_FLAG_PC_THROTTLE
;
652 pbsd_shortp
->pbsi_flags
|= PROC_FLAG_PC_SUSP
;
655 pbsd_shortp
->pbsi_flags
|= PROC_FLAG_PC_KILL
;
659 switch(PROC_ACTION_STATE(p
)) {
661 pbsd_shortp
->pbsi_flags
|= PROC_FLAG_PA_THROTTLE
;
664 pbsd_shortp
->pbsi_flags
|= PROC_FLAG_PA_SUSP
;
668 /* if process is a zombie skip bg state */
669 if ((zombie
== 0) && (p
->p_stat
!= SZOMB
) && (p
->task
!= TASK_NULL
))
670 proc_get_darwinbgstate(p
->task
, &pbsd_shortp
->pbsi_flags
);
672 pbsd_shortp
->pbsi_uid
= p
->p_uid
;
673 pbsd_shortp
->pbsi_gid
= p
->p_gid
;
674 pbsd_shortp
->pbsi_ruid
= p
->p_ruid
;
675 pbsd_shortp
->pbsi_rgid
= p
->p_rgid
;
676 pbsd_shortp
->pbsi_svuid
= p
->p_svuid
;
677 pbsd_shortp
->pbsi_svgid
= p
->p_svgid
;
683 proc_pidtaskinfo(proc_t p
, struct proc_taskinfo
* ptinfo
)
689 bzero(ptinfo
, sizeof(struct proc_taskinfo
));
690 fill_taskprocinfo(task
, (struct proc_taskinfo_internal
*)ptinfo
);
698 proc_pidthreadinfo(proc_t p
, uint64_t arg
, int thuniqueid
, struct proc_threadinfo
*pthinfo
)
701 uint64_t threadaddr
= (uint64_t)arg
;
703 bzero(pthinfo
, sizeof(struct proc_threadinfo
));
705 error
= fill_taskthreadinfo(p
->task
, threadaddr
, thuniqueid
, (struct proc_threadinfo_internal
*)pthinfo
, NULL
, NULL
);
714 bsd_getthreadname(void *uth
, char *buffer
)
716 struct uthread
*ut
= (struct uthread
*)uth
;
718 bcopy(ut
->pth_name
,buffer
,MAXTHREADNAMESIZE
);
722 bsd_threadcdir(void * uth
, void *vptr
, int *vidp
)
724 struct uthread
* ut
= (struct uthread
*)uth
;
726 vnode_t
*vpp
= (vnode_t
*)vptr
;
740 proc_pidthreadpathinfo(proc_t p
, uint64_t arg
, struct proc_threadwithpathinfo
*pinfo
)
745 uint64_t threadaddr
= (uint64_t)arg
;
748 bzero(pinfo
, sizeof(struct proc_threadwithpathinfo
));
750 error
= fill_taskthreadinfo(p
->task
, threadaddr
, 0, (struct proc_threadinfo_internal
*)&pinfo
->pt
, (void *)&vp
, &vid
);
754 if ((vp
!= NULLVP
) && ((vnode_getwithvid(vp
, vid
)) == 0)) {
755 error
= fill_vnodeinfo(vp
, &pinfo
->pvip
.vip_vi
) ;
758 vn_getpath(vp
, &pinfo
->pvip
.vip_path
[0], &count
);
759 pinfo
->pvip
.vip_path
[MAXPATHLEN
-1] = 0;
769 proc_pidlistthreads(proc_t p
, user_addr_t buffer
, uint32_t buffersize
, int32_t *retval
)
778 count
= buffersize
/(sizeof(uint64_t));
779 numthreads
= get_numthreads(p
->task
);
783 if (numthreads
> count
)
786 kbuf
= (void *)kalloc(numthreads
* sizeof(uint64_t));
789 bzero(kbuf
, numthreads
* sizeof(uint64_t));
791 ret
= fill_taskthreadlist(p
->task
, kbuf
, numthreads
);
793 error
= copyout(kbuf
, buffer
, ret
);
794 kfree(kbuf
, numthreads
* sizeof(uint64_t));
803 proc_pidregioninfo(proc_t p
, uint64_t arg
, user_addr_t buffer
, __unused
uint32_t buffersize
, int32_t *retval
)
805 struct proc_regioninfo preginfo
;
808 bzero(&preginfo
, sizeof(struct proc_regioninfo
));
809 ret
= fill_procregioninfo( p
->task
, arg
, (struct proc_regioninfo_internal
*)&preginfo
, (uintptr_t *)0, (uint32_t *)0);
812 error
= copyout(&preginfo
, buffer
, sizeof(struct proc_regioninfo
));
814 *retval
= sizeof(struct proc_regioninfo
);
820 proc_pidregionpathinfo(proc_t p
, uint64_t arg
, user_addr_t buffer
, __unused
uint32_t buffersize
, int32_t *retval
)
822 struct proc_regionwithpathinfo preginfo
;
824 uintptr_t vnodeaddr
= 0;
829 bzero(&preginfo
, sizeof(struct proc_regionwithpathinfo
));
831 ret
= fill_procregioninfo( p
->task
, arg
, (struct proc_regioninfo_internal
*)&preginfo
.prp_prinfo
, (uintptr_t *)&vnodeaddr
, (uint32_t *)&vnodeid
);
835 vp
= (vnode_t
)vnodeaddr
;
836 if ((vnode_getwithvid(vp
, vnodeid
)) == 0) {
837 /* FILL THE VNODEINFO */
838 error
= fill_vnodeinfo(vp
, &preginfo
.prp_vip
.vip_vi
);
840 vn_getpath(vp
, &preginfo
.prp_vip
.vip_path
[0], &count
);
841 /* Always make sure it is null terminated */
842 preginfo
.prp_vip
.vip_path
[MAXPATHLEN
-1] = 0;
846 error
= copyout(&preginfo
, buffer
, sizeof(struct proc_regionwithpathinfo
));
848 *retval
= sizeof(struct proc_regionwithpathinfo
);
853 * Path is relative to current process directory; may different from current
857 proc_pidvnodepathinfo(proc_t p
, __unused
uint64_t arg
, user_addr_t buffer
, __unused
uint32_t buffersize
, int32_t *retval
)
859 struct proc_vnodepathinfo pvninfo
;
861 vnode_t vncdirvp
= NULLVP
;
863 vnode_t vnrdirvp
= NULLVP
;
867 bzero(&pvninfo
, sizeof(struct proc_vnodepathinfo
));
870 if (p
->p_fd
->fd_cdir
) {
871 vncdirvp
= p
->p_fd
->fd_cdir
;
872 vncdirid
= p
->p_fd
->fd_cdir
->v_id
;
874 if (p
->p_fd
->fd_rdir
) {
875 vnrdirvp
= p
->p_fd
->fd_rdir
;
876 vnrdirid
= p
->p_fd
->fd_rdir
->v_id
;
880 if (vncdirvp
!= NULLVP
) {
881 if ((error
= vnode_getwithvid(vncdirvp
, vncdirid
)) == 0) {
882 /* FILL THE VNODEINFO */
883 error
= fill_vnodeinfo(vncdirvp
, &pvninfo
.pvi_cdir
.vip_vi
);
886 vn_getpath(vncdirvp
, &pvninfo
.pvi_cdir
.vip_path
[0], &count
);
887 pvninfo
.pvi_cdir
.vip_path
[MAXPATHLEN
-1] = 0;
895 if ((error
== 0) && (vnrdirvp
!= NULLVP
)) {
896 if ((error
= vnode_getwithvid(vnrdirvp
, vnrdirid
)) == 0) {
897 /* FILL THE VNODEINFO */
898 error
= fill_vnodeinfo(vnrdirvp
, &pvninfo
.pvi_rdir
.vip_vi
);
901 vn_getpath(vnrdirvp
, &pvninfo
.pvi_rdir
.vip_path
[0], &count
);
902 pvninfo
.pvi_rdir
.vip_path
[MAXPATHLEN
-1] = 0;
910 error
= copyout(&pvninfo
, buffer
, sizeof(struct proc_vnodepathinfo
));
912 *retval
= sizeof(struct proc_vnodepathinfo
);
919 proc_pidpathinfo(proc_t p
, __unused
uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, __unused
int32_t *retval
)
923 vnode_t nvp
= NULLVP
;
924 int len
= buffersize
;
932 buf
= (char *)kalloc(buffersize
);
937 vid
= vnode_vid(tvp
);
938 error
= vnode_getwithvid(tvp
, vid
);
940 error
= vn_getpath_fsenter(tvp
, buf
, &len
);
943 error
= vnode_lookup(buf
, 0, &nvp
, vfs_context_current());
944 if ((error
== 0) && ( nvp
!= NULLVP
))
947 error
= copyout(buf
, buffer
, len
);
951 kfree(buf
, buffersize
);
957 proc_pidworkqueueinfo(proc_t p
, struct proc_workqueueinfo
*pwqinfo
)
961 bzero(pwqinfo
, sizeof(struct proc_workqueueinfo
));
963 error
= fill_procworkqueue(p
, pwqinfo
);
973 proc_piduniqidentifierinfo(proc_t p
, struct proc_uniqidentifierinfo
*p_uniqidinfo
)
975 p_uniqidinfo
->p_uniqueid
= proc_uniqueid(p
);
976 proc_getexecutableuuid(p
, (unsigned char *)&p_uniqidinfo
->p_uuid
, sizeof(p_uniqidinfo
->p_uuid
));
977 p_uniqidinfo
->p_puniqueid
= proc_puniqueid(p
);
978 p_uniqidinfo
->p_reserve2
= 0;
979 p_uniqidinfo
->p_reserve3
= 0;
980 p_uniqidinfo
->p_reserve4
= 0;
983 /********************************** proc_pidinfo ********************************/
987 proc_pidinfo(int pid
, int flavor
, uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
)
989 struct proc
* p
= PROC_NULL
;
993 int shortversion
= 0;
997 int uniqidversion
= 0;
998 boolean_t check_same_user
;
1001 case PROC_PIDLISTFDS
:
1002 size
= PROC_PIDLISTFD_SIZE
;
1003 if (buffer
== (user_addr_t
)0)
1006 case PROC_PIDTBSDINFO
:
1007 size
= PROC_PIDTBSDINFO_SIZE
;
1009 case PROC_PIDTASKINFO
:
1010 size
= PROC_PIDTASKINFO_SIZE
;
1012 case PROC_PIDTASKALLINFO
:
1013 size
= PROC_PIDTASKALLINFO_SIZE
;
1015 case PROC_PIDTHREADINFO
:
1016 size
= PROC_PIDTHREADINFO_SIZE
;
1018 case PROC_PIDLISTTHREADS
:
1019 size
= PROC_PIDLISTTHREADS_SIZE
;
1021 case PROC_PIDREGIONINFO
:
1022 size
= PROC_PIDREGIONINFO_SIZE
;
1024 case PROC_PIDREGIONPATHINFO
:
1025 size
= PROC_PIDREGIONPATHINFO_SIZE
;
1027 case PROC_PIDVNODEPATHINFO
:
1028 size
= PROC_PIDVNODEPATHINFO_SIZE
;
1030 case PROC_PIDTHREADPATHINFO
:
1031 size
= PROC_PIDTHREADPATHINFO_SIZE
;
1033 case PROC_PIDPATHINFO
:
1036 case PROC_PIDWORKQUEUEINFO
:
1037 /* kernel does not have workq info */
1041 size
= PROC_PIDWORKQUEUEINFO_SIZE
;
1043 case PROC_PIDT_SHORTBSDINFO
:
1044 size
= PROC_PIDT_SHORTBSDINFO_SIZE
;
1046 case PROC_PIDLISTFILEPORTS
:
1047 size
= PROC_PIDLISTFILEPORTS_SIZE
;
1048 if (buffer
== (user_addr_t
)0)
1051 case PROC_PIDTHREADID64INFO
:
1052 size
= PROC_PIDTHREADID64INFO_SIZE
;
1054 case PROC_PIDUNIQIDENTIFIERINFO
:
1055 size
= PROC_PIDUNIQIDENTIFIERINFO_SIZE
;
1057 case PROC_PIDT_BSDINFOWITHUNIQID
:
1058 size
= PROC_PIDT_BSDINFOWITHUNIQID_SIZE
;
1064 if (buffersize
< size
)
1067 if ((flavor
== PROC_PIDPATHINFO
) && (buffersize
> PROC_PIDPATHINFO_MAXSIZE
)) {
1071 /* Check if we need to look for zombies */
1072 if ((flavor
== PROC_PIDTBSDINFO
) || (flavor
== PROC_PIDT_SHORTBSDINFO
) || (flavor
== PROC_PIDT_BSDINFOWITHUNIQID
)
1073 || (flavor
== PROC_PIDUNIQIDENTIFIERINFO
)) {
1078 if ((p
= proc_find(pid
)) == PROC_NULL
) {
1080 p
= proc_find_zombref(pid
);
1081 if (p
== PROC_NULL
) {
1090 /* Certain operations don't require privileges */
1092 case PROC_PIDT_SHORTBSDINFO
:
1093 case PROC_PIDUNIQIDENTIFIERINFO
:
1094 case PROC_PIDPATHINFO
:
1095 check_same_user
= NO_CHECK_SAME_USER
;
1098 check_same_user
= CHECK_SAME_USER
;
1102 /* Do we have permission to look into this? */
1103 if ((error
= proc_security_policy(p
, PROC_INFO_CALL_PIDINFO
, flavor
, check_same_user
)))
1107 case PROC_PIDLISTFDS
: {
1108 error
= proc_pidfdlist(p
, buffer
, buffersize
, retval
);
1112 case PROC_PIDUNIQIDENTIFIERINFO
: {
1113 struct proc_uniqidentifierinfo p_uniqidinfo
;
1115 proc_piduniqidentifierinfo(p
, &p_uniqidinfo
);
1116 error
= copyout(&p_uniqidinfo
, buffer
, sizeof(struct proc_uniqidentifierinfo
));
1118 *retval
= sizeof(struct proc_uniqidentifierinfo
);
1122 case PROC_PIDT_SHORTBSDINFO
:
1124 case PROC_PIDT_BSDINFOWITHUNIQID
:
1125 case PROC_PIDTBSDINFO
: {
1126 struct proc_bsdinfo pbsd
;
1127 struct proc_bsdshortinfo pbsd_short
;
1128 struct proc_bsdinfowithuniqid pbsd_uniqid
;
1130 if (flavor
== PROC_PIDT_BSDINFOWITHUNIQID
)
1133 if (shortversion
!= 0) {
1134 error
= proc_pidshortbsdinfo(p
, &pbsd_short
, zombie
);
1136 error
= proc_pidbsdinfo(p
, &pbsd
, zombie
);
1137 if (uniqidversion
!= 0) {
1138 proc_piduniqidentifierinfo(p
, &pbsd_uniqid
.p_uniqidentifier
);
1139 pbsd_uniqid
.pbsd
= pbsd
;
1144 if (shortversion
!= 0) {
1145 error
= copyout(&pbsd_short
, buffer
, sizeof(struct proc_bsdshortinfo
));
1147 *retval
= sizeof(struct proc_bsdshortinfo
);
1148 } else if (uniqidversion
!= 0) {
1149 error
= copyout(&pbsd_uniqid
, buffer
, sizeof(struct proc_bsdinfowithuniqid
));
1151 *retval
= sizeof(struct proc_bsdinfowithuniqid
);
1153 error
= copyout(&pbsd
, buffer
, sizeof(struct proc_bsdinfo
));
1155 *retval
= sizeof(struct proc_bsdinfo
);
1161 case PROC_PIDTASKINFO
: {
1162 struct proc_taskinfo ptinfo
;
1164 error
= proc_pidtaskinfo(p
, &ptinfo
);
1166 error
= copyout(&ptinfo
, buffer
, sizeof(struct proc_taskinfo
));
1168 *retval
= sizeof(struct proc_taskinfo
);
1173 case PROC_PIDTASKALLINFO
: {
1174 struct proc_taskallinfo pall
;
1176 error
= proc_pidbsdinfo(p
, &pall
.pbsd
, 0);
1177 error
= proc_pidtaskinfo(p
, &pall
.ptinfo
);
1179 error
= copyout(&pall
, buffer
, sizeof(struct proc_taskallinfo
));
1181 *retval
= sizeof(struct proc_taskallinfo
);
1186 case PROC_PIDTHREADID64INFO
:
1188 case PROC_PIDTHREADINFO
:{
1189 struct proc_threadinfo pthinfo
;
1191 error
= proc_pidthreadinfo(p
, arg
, thuniqueid
, &pthinfo
);
1193 error
= copyout(&pthinfo
, buffer
, sizeof(struct proc_threadinfo
));
1195 *retval
= sizeof(struct proc_threadinfo
);
1200 case PROC_PIDLISTTHREADS
:{
1201 error
= proc_pidlistthreads(p
, buffer
, buffersize
, retval
);
1205 case PROC_PIDREGIONINFO
:{
1206 error
= proc_pidregioninfo(p
, arg
, buffer
, buffersize
, retval
);
1211 case PROC_PIDREGIONPATHINFO
:{
1212 error
= proc_pidregionpathinfo(p
, arg
, buffer
, buffersize
, retval
);
1216 case PROC_PIDVNODEPATHINFO
:{
1217 error
= proc_pidvnodepathinfo(p
, arg
, buffer
, buffersize
, retval
);
1222 case PROC_PIDTHREADPATHINFO
:{
1223 struct proc_threadwithpathinfo pinfo
;
1225 error
= proc_pidthreadpathinfo(p
, arg
, &pinfo
);
1227 error
= copyout((caddr_t
)&pinfo
, buffer
, sizeof(struct proc_threadwithpathinfo
));
1229 *retval
= sizeof(struct proc_threadwithpathinfo
);
1234 case PROC_PIDPATHINFO
: {
1235 error
= proc_pidpathinfo(p
, arg
, buffer
, buffersize
, retval
);
1240 case PROC_PIDWORKQUEUEINFO
:{
1241 struct proc_workqueueinfo pwqinfo
;
1243 error
= proc_pidworkqueueinfo(p
, &pwqinfo
);
1245 error
= copyout(&pwqinfo
, buffer
, sizeof(struct proc_workqueueinfo
));
1247 *retval
= sizeof(struct proc_workqueueinfo
);
1252 case PROC_PIDLISTFILEPORTS
: {
1253 error
= proc_pidfileportlist(p
, buffer
, buffersize
,
1266 proc_drop_zombref(p
);
1272 pid_vnodeinfo(vnode_t vp
, uint32_t vid
, struct fileproc
* fp
, int closeonexec
, user_addr_t buffer
, __unused
uint32_t buffersize
, int32_t * retval
)
1274 struct vnode_fdinfo vfi
;
1277 if ((error
= vnode_getwithvid(vp
, vid
)) != 0) {
1280 bzero(&vfi
, sizeof(struct vnode_fdinfo
));
1281 fill_fileinfo(fp
, closeonexec
, &vfi
.pfi
);
1282 error
= fill_vnodeinfo(vp
, &vfi
.pvi
);
1285 error
= copyout((caddr_t
)&vfi
, buffer
, sizeof(struct vnode_fdinfo
));
1287 *retval
= sizeof(struct vnode_fdinfo
);
1293 pid_vnodeinfopath(vnode_t vp
, uint32_t vid
, struct fileproc
* fp
, int closeonexec
, user_addr_t buffer
, __unused
uint32_t buffersize
, int32_t * retval
)
1295 struct vnode_fdinfowithpath vfip
;
1296 int count
, error
= 0;
1298 if ((error
= vnode_getwithvid(vp
, vid
)) != 0) {
1301 bzero(&vfip
, sizeof(struct vnode_fdinfowithpath
));
1302 fill_fileinfo(fp
, closeonexec
, &vfip
.pfi
);
1303 error
= fill_vnodeinfo(vp
, &vfip
.pvip
.vip_vi
) ;
1306 vn_getpath(vp
, &vfip
.pvip
.vip_path
[0], &count
);
1307 vfip
.pvip
.vip_path
[MAXPATHLEN
-1] = 0;
1309 error
= copyout((caddr_t
)&vfip
, buffer
, sizeof(struct vnode_fdinfowithpath
));
1311 *retval
= sizeof(struct vnode_fdinfowithpath
);
1318 fill_fileinfo(struct fileproc
* fp
, int closeonexec
, struct proc_fileinfo
* fproc
)
1320 fproc
->fi_openflags
= fp
->f_fglob
->fg_flag
;
1321 fproc
->fi_status
= 0;
1322 fproc
->fi_offset
= fp
->f_fglob
->fg_offset
;
1323 fproc
->fi_type
= FILEGLOB_DTYPE(fp
->f_fglob
);
1324 if (fp
->f_fglob
->fg_count
> 1)
1325 fproc
->fi_status
|= PROC_FP_SHARED
;
1326 if (closeonexec
!= 0)
1327 fproc
->fi_status
|= PROC_FP_CLEXEC
;
1329 if (FILEPROC_TYPE(fp
) == FTYPE_GUARDED
) {
1330 fproc
->fi_status
|= PROC_FP_GUARDED
;
1331 fproc
->fi_guardflags
= 0;
1332 if (fp_isguarded(fp
, GUARD_CLOSE
))
1333 fproc
->fi_guardflags
|= PROC_FI_GUARD_CLOSE
;
1334 if (fp_isguarded(fp
, GUARD_DUP
))
1335 fproc
->fi_guardflags
|= PROC_FI_GUARD_DUP
;
1336 if (fp_isguarded(fp
, GUARD_SOCKET_IPC
))
1337 fproc
->fi_guardflags
|= PROC_FI_GUARD_SOCKET_IPC
;
1338 if (fp_isguarded(fp
, GUARD_FILEPORT
))
1339 fproc
->fi_guardflags
|= PROC_FI_GUARD_FILEPORT
;
1346 fill_vnodeinfo(vnode_t vp
, struct vnode_info
*vinfo
)
1348 vfs_context_t context
;
1352 context
= vfs_context_create((vfs_context_t
)0);
1353 error
= vn_stat(vp
, &sb
, NULL
, 1, context
);
1354 (void)vfs_context_rele(context
);
1356 munge_vinfo_stat(&sb
, &vinfo
->vi_stat
);
1361 if (vp
->v_mount
!= dead_mountp
) {
1362 vinfo
->vi_fsid
= vp
->v_mount
->mnt_vfsstat
.f_fsid
;
1364 vinfo
->vi_fsid
.val
[0] = 0;
1365 vinfo
->vi_fsid
.val
[1] = 0;
1367 vinfo
->vi_type
= vp
->v_type
;
1373 pid_socketinfo(socket_t so
, struct fileproc
*fp
, int closeonexec
, user_addr_t buffer
, __unused
uint32_t buffersize
, int32_t * retval
)
1376 struct socket_fdinfo s
;
1379 bzero(&s
, sizeof(struct socket_fdinfo
));
1380 fill_fileinfo(fp
, closeonexec
, &s
.pfi
);
1381 if ((error
= fill_socketinfo(so
, &s
.psi
)) == 0) {
1382 if ((error
= copyout(&s
, buffer
, sizeof(struct socket_fdinfo
))) == 0)
1383 *retval
= sizeof(struct socket_fdinfo
);
1387 #pragma unused(so, fp, closeonexec, buffer)
1394 pid_pseminfo(struct psemnode
*psem
, struct fileproc
*fp
, int closeonexec
, user_addr_t buffer
, __unused
uint32_t buffersize
, int32_t * retval
)
1396 struct psem_fdinfo pseminfo
;
1399 bzero(&pseminfo
, sizeof(struct psem_fdinfo
));
1400 fill_fileinfo(fp
, closeonexec
, &pseminfo
.pfi
);
1402 if ((error
= fill_pseminfo(psem
, &pseminfo
.pseminfo
)) == 0) {
1403 if ((error
= copyout(&pseminfo
, buffer
, sizeof(struct psem_fdinfo
))) == 0)
1404 *retval
= sizeof(struct psem_fdinfo
);
1411 pid_pshminfo(struct pshmnode
*pshm
, struct fileproc
*fp
, int closeonexec
, user_addr_t buffer
, __unused
uint32_t buffersize
, int32_t * retval
)
1413 struct pshm_fdinfo pshminfo
;
1416 bzero(&pshminfo
, sizeof(struct pshm_fdinfo
));
1417 fill_fileinfo(fp
, closeonexec
, &pshminfo
.pfi
);
1419 if ((error
= fill_pshminfo(pshm
, &pshminfo
.pshminfo
)) == 0) {
1420 if ((error
= copyout(&pshminfo
, buffer
, sizeof(struct pshm_fdinfo
))) == 0)
1421 *retval
= sizeof(struct pshm_fdinfo
);
1428 pid_pipeinfo(struct pipe
* p
, struct fileproc
*fp
, int closeonexec
, user_addr_t buffer
, __unused
uint32_t buffersize
, int32_t * retval
)
1430 struct pipe_fdinfo pipeinfo
;
1433 bzero(&pipeinfo
, sizeof(struct pipe_fdinfo
));
1434 fill_fileinfo(fp
, closeonexec
, &pipeinfo
.pfi
);
1435 if ((error
= fill_pipeinfo(p
, &pipeinfo
.pipeinfo
)) == 0) {
1436 if ((error
= copyout(&pipeinfo
, buffer
, sizeof(struct pipe_fdinfo
))) == 0)
1437 *retval
= sizeof(struct pipe_fdinfo
);
1444 pid_kqueueinfo(struct kqueue
* kq
, struct fileproc
*fp
, int closeonexec
, user_addr_t buffer
, __unused
uint32_t buffersize
, int32_t * retval
)
1446 struct kqueue_fdinfo kqinfo
;
1449 bzero(&kqinfo
, sizeof(struct kqueue_fdinfo
));
1451 fill_fileinfo(fp
, closeonexec
, &kqinfo
.pfi
);
1453 if ((error
= fill_kqueueinfo(kq
, &kqinfo
.kqueueinfo
)) == 0) {
1454 if ((error
= copyout(&kqinfo
, buffer
, sizeof(struct kqueue_fdinfo
))) == 0)
1455 *retval
= sizeof(struct kqueue_fdinfo
);
1462 pid_atalkinfo(__unused
struct atalk
* at
, __unused
struct fileproc
*fp
, __unused
int closeonexec
, __unused user_addr_t buffer
, __unused
uint32_t buffersize
, __unused
int32_t * retval
)
1469 /************************** proc_pidfdinfo routine ***************************/
1471 proc_pidfdinfo(int pid
, int flavor
, int fd
, user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
)
1474 int error
= ENOTSUP
;
1475 struct fileproc
* fp
;
1477 int closeonexec
= 0;
1480 case PROC_PIDFDVNODEINFO
:
1481 size
= PROC_PIDFDVNODEINFO_SIZE
;
1483 case PROC_PIDFDVNODEPATHINFO
:
1484 size
= PROC_PIDFDVNODEPATHINFO_SIZE
;
1486 case PROC_PIDFDSOCKETINFO
:
1487 size
= PROC_PIDFDSOCKETINFO_SIZE
;
1489 case PROC_PIDFDPSEMINFO
:
1490 size
= PROC_PIDFDPSEMINFO_SIZE
;
1492 case PROC_PIDFDPSHMINFO
:
1493 size
= PROC_PIDFDPSHMINFO_SIZE
;
1495 case PROC_PIDFDPIPEINFO
:
1496 size
= PROC_PIDFDPIPEINFO_SIZE
;
1498 case PROC_PIDFDKQUEUEINFO
:
1499 size
= PROC_PIDFDKQUEUEINFO_SIZE
;
1501 case PROC_PIDFDATALKINFO
:
1502 size
= PROC_PIDFDATALKINFO_SIZE
;
1510 if (buffersize
< size
)
1513 if ((p
= proc_find(pid
)) == PROC_NULL
) {
1518 /* Do we have permission to look into this? */
1519 if ((error
= proc_security_policy(p
, PROC_INFO_CALL_PIDFDINFO
, flavor
, CHECK_SAME_USER
)))
1523 case PROC_PIDFDVNODEINFO
: {
1527 if ((error
= fp_getfvpandvid(p
, fd
, &fp
, &vp
, &vid
)) !=0) {
1530 /* no need to be under the fdlock */
1531 closeonexec
= p
->p_fd
->fd_ofileflags
[fd
] & UF_EXCLOSE
;
1532 error
= pid_vnodeinfo(vp
, vid
, fp
, closeonexec
, buffer
, buffersize
, retval
);
1536 case PROC_PIDFDVNODEPATHINFO
: {
1540 if ((error
= fp_getfvpandvid(p
, fd
, &fp
, &vp
, &vid
)) !=0) {
1544 /* no need to be under the fdlock */
1545 closeonexec
= p
->p_fd
->fd_ofileflags
[fd
] & UF_EXCLOSE
;
1546 error
= pid_vnodeinfopath(vp
, vid
, fp
, closeonexec
, buffer
, buffersize
, retval
);
1550 case PROC_PIDFDSOCKETINFO
: {
1553 if ((error
= fp_getfsock(p
, fd
, &fp
, &so
)) !=0) {
1556 /* no need to be under the fdlock */
1557 closeonexec
= p
->p_fd
->fd_ofileflags
[fd
] & UF_EXCLOSE
;
1558 error
= pid_socketinfo(so
, fp
, closeonexec
, buffer
, buffersize
, retval
);
1562 case PROC_PIDFDPSEMINFO
: {
1563 struct psemnode
* psem
;
1565 if ((error
= fp_getfpsem(p
, fd
, &fp
, &psem
)) !=0) {
1568 /* no need to be under the fdlock */
1569 closeonexec
= p
->p_fd
->fd_ofileflags
[fd
] & UF_EXCLOSE
;
1570 error
= pid_pseminfo(psem
, fp
, closeonexec
, buffer
, buffersize
, retval
);
1574 case PROC_PIDFDPSHMINFO
: {
1575 struct pshmnode
* pshm
;
1577 if ((error
= fp_getfpshm(p
, fd
, &fp
, &pshm
)) !=0) {
1580 /* no need to be under the fdlock */
1581 closeonexec
= p
->p_fd
->fd_ofileflags
[fd
] & UF_EXCLOSE
;
1582 error
= pid_pshminfo(pshm
, fp
, closeonexec
, buffer
, buffersize
, retval
);
1586 case PROC_PIDFDPIPEINFO
: {
1587 struct pipe
* cpipe
;
1589 if ((error
= fp_getfpipe(p
, fd
, &fp
, &cpipe
)) !=0) {
1592 /* no need to be under the fdlock */
1593 closeonexec
= p
->p_fd
->fd_ofileflags
[fd
] & UF_EXCLOSE
;
1594 error
= pid_pipeinfo(cpipe
, fp
, closeonexec
, buffer
, buffersize
, retval
);
1598 case PROC_PIDFDKQUEUEINFO
: {
1601 if ((error
= fp_getfkq(p
, fd
, &fp
, &kq
)) !=0) {
1604 /* no need to be under the fdlock */
1605 closeonexec
= p
->p_fd
->fd_ofileflags
[fd
] & UF_EXCLOSE
;
1606 error
= pid_kqueueinfo(kq
, fp
, closeonexec
, buffer
, buffersize
, retval
);
1616 fp_drop(p
, fd
, fp
, 0);
1624 * Helper function for proc_pidfileportinfo
1627 struct fileport_info_args
{
1629 user_addr_t fia_buffer
;
1630 uint32_t fia_buffersize
;
1631 int32_t *fia_retval
;
1634 static kern_return_t
1635 proc_fileport_info(__unused mach_port_name_t name
,
1636 struct fileglob
*fg
, void *arg
)
1638 struct fileport_info_args
*fia
= arg
;
1639 struct fileproc __fileproc
, *fp
= &__fileproc
;
1642 bzero(fp
, sizeof (*fp
));
1645 switch (fia
->fia_flavor
) {
1646 case PROC_PIDFILEPORTVNODEPATHINFO
: {
1649 if (FILEGLOB_DTYPE(fg
) != DTYPE_VNODE
) {
1653 vp
= (struct vnode
*)fg
->fg_data
;
1654 error
= pid_vnodeinfopath(vp
, vnode_vid(vp
), fp
, 0,
1655 fia
->fia_buffer
, fia
->fia_buffersize
, fia
->fia_retval
);
1658 case PROC_PIDFILEPORTSOCKETINFO
: {
1661 if (FILEGLOB_DTYPE(fg
) != DTYPE_SOCKET
) {
1665 so
= (socket_t
)fg
->fg_data
;
1666 error
= pid_socketinfo(so
, fp
, 0,
1667 fia
->fia_buffer
, fia
->fia_buffersize
, fia
->fia_retval
);
1670 case PROC_PIDFILEPORTPSHMINFO
: {
1671 struct pshmnode
*pshm
;
1673 if (FILEGLOB_DTYPE(fg
) != DTYPE_PSXSHM
) {
1674 error
= EBADF
; /* ick - mirror fp_getfpshm */
1677 pshm
= (struct pshmnode
*)fg
->fg_data
;
1678 error
= pid_pshminfo(pshm
, fp
, 0,
1679 fia
->fia_buffer
, fia
->fia_buffersize
, fia
->fia_retval
);
1682 case PROC_PIDFILEPORTPIPEINFO
: {
1685 if (FILEGLOB_DTYPE(fg
) != DTYPE_PIPE
) {
1686 error
= EBADF
; /* ick - mirror fp_getfpipe */
1689 cpipe
= (struct pipe
*)fg
->fg_data
;
1690 error
= pid_pipeinfo(cpipe
, fp
, 0,
1691 fia
->fia_buffer
, fia
->fia_buffersize
, fia
->fia_retval
);
1702 /************************* proc_pidfileportinfo routine *********************/
1704 proc_pidfileportinfo(int pid
, int flavor
, mach_port_name_t name
,
1705 user_addr_t buffer
, uint32_t buffersize
, int32_t *retval
)
1708 int error
= ENOTSUP
;
1710 struct fileport_info_args fia
;
1712 /* fileport types are restricted by filetype_issendable() */
1715 case PROC_PIDFILEPORTVNODEPATHINFO
:
1716 size
= PROC_PIDFILEPORTVNODEPATHINFO_SIZE
;
1718 case PROC_PIDFILEPORTSOCKETINFO
:
1719 size
= PROC_PIDFILEPORTSOCKETINFO_SIZE
;
1721 case PROC_PIDFILEPORTPSHMINFO
:
1722 size
= PROC_PIDFILEPORTPSHMINFO_SIZE
;
1724 case PROC_PIDFILEPORTPIPEINFO
:
1725 size
= PROC_PIDFILEPORTPIPEINFO_SIZE
;
1731 if (buffersize
< size
)
1733 if ((p
= proc_find(pid
)) == PROC_NULL
) {
1738 /* Do we have permission to look into this? */
1739 if ((error
= proc_security_policy(p
, PROC_INFO_CALL_PIDFILEPORTINFO
, flavor
, CHECK_SAME_USER
)))
1742 fia
.fia_flavor
= flavor
;
1743 fia
.fia_buffer
= buffer
;
1744 fia
.fia_buffersize
= buffersize
;
1745 fia
.fia_retval
= retval
;
1747 if (fileport_invoke(p
->task
, name
,
1748 proc_fileport_info
, &fia
, &error
) != KERN_SUCCESS
)
1757 proc_security_policy(proc_t targetp
, __unused
int callnum
, __unused
int flavor
, boolean_t check_same_user
)
1762 if ((error
= mac_proc_check_proc_info(current_proc(), targetp
, callnum
, flavor
)))
1766 /* The 'listpids' call doesn't have a target proc */
1767 if (targetp
== PROC_NULL
) {
1768 assert(callnum
== PROC_INFO_CALL_LISTPIDS
&& check_same_user
== NO_CHECK_SAME_USER
);
1773 * Check for 'get information for processes owned by other users' privilege
1774 * root has this privilege by default
1776 if (priv_check_cred(kauth_cred_get(), PRIV_GLOBAL_PROC_INFO
, 0) == 0)
1777 check_same_user
= FALSE
;
1779 if (check_same_user
) {
1780 kauth_cred_t target_cred
;
1783 target_cred
= kauth_cred_proc_ref(targetp
);
1784 target_uid
= kauth_cred_getuid(target_cred
);
1785 kauth_cred_unref(&target_cred
);
1787 if (kauth_getuid() != target_uid
)
1795 proc_kernmsgbuf(user_addr_t buffer
, uint32_t buffersize
, int32_t * retval
)
1797 if (suser(kauth_cred_get(), (u_short
*)0) == 0) {
1798 return(log_dmesg(buffer
, buffersize
, retval
));
1803 /* ********* process control sets on self only */
1805 proc_setcontrol(int pid
, int flavor
, uint64_t arg
, user_addr_t buffer
, uint32_t buffersize
, __unused
int32_t * retval
)
1807 struct proc
* pself
= PROC_NULL
;
1809 uint32_t pcontrol
= (uint32_t)arg
;
1810 struct uthread
*ut
= NULL
;
1813 pself
= current_proc();
1814 if (pid
!= pself
->p_pid
)
1817 /* Do we have permission to look into this? */
1818 if ((error
= proc_security_policy(pself
, PROC_INFO_CALL_SETCONTROL
, flavor
, NO_CHECK_SAME_USER
)))
1822 case PROC_SELFSET_PCONTROL
: {
1823 if (pcontrol
> P_PCMAX
)
1826 /* reset existing control setting while retaining action state */
1827 pself
->p_pcaction
&= PROC_ACTION_MASK
;
1828 /* set new control state */
1829 pself
->p_pcaction
|= pcontrol
;
1834 case PROC_SELFSET_THREADNAME
: {
1835 /* PROC_SELFSET_THREADNAME_SIZE = (MAXTHREADNAMESIZE -1) */
1836 if(buffersize
> PROC_SELFSET_THREADNAME_SIZE
)
1837 return ENAMETOOLONG
;
1838 ut
= current_uthread();
1842 ut
->pth_name
= (char*)kalloc(MAXTHREADNAMESIZE
);
1846 bzero(ut
->pth_name
, MAXTHREADNAMESIZE
);
1847 error
= copyin(buffer
, ut
->pth_name
, buffersize
);
1851 case PROC_SELFSET_VMRSRCOWNER
: {
1852 /* need to to be superuser */
1853 if (suser(kauth_cred_get(), (u_short
*)0) != 0) {
1859 /* reset existing control setting while retaining action state */
1860 pself
->p_lflag
|= P_LVMRSRCOWNER
;
1865 case PROC_SELFSET_DELAYIDLESLEEP
: {
1866 /* mark or clear the process property to delay idle sleep disk IO */
1868 OSBitOrAtomic(P_DELAYIDLESLEEP
, &pself
->p_flag
);
1870 OSBitAndAtomic(~((uint32_t)P_DELAYIDLESLEEP
), &pself
->p_flag
);
1882 #if CONFIG_MEMORYSTATUS
1885 proc_dirtycontrol(int pid
, int flavor
, uint64_t arg
, int32_t *retval
) {
1886 struct proc
*target_p
;
1888 uint32_t pcontrol
= (uint32_t)arg
;
1889 kauth_cred_t my_cred
, target_cred
;
1890 boolean_t self
= FALSE
;
1891 boolean_t child
= FALSE
;
1892 boolean_t zombref
= FALSE
;
1895 target_p
= proc_find(pid
);
1897 if (target_p
== PROC_NULL
) {
1898 if (flavor
== PROC_DIRTYCONTROL_GET
) {
1899 target_p
= proc_find_zombref(pid
);
1903 if (target_p
== PROC_NULL
)
1908 my_cred
= kauth_cred_get();
1909 target_cred
= kauth_cred_proc_ref(target_p
);
1911 /* Do we have permission to look into this? */
1912 if ((error
= proc_security_policy(target_p
, PROC_INFO_CALL_DIRTYCONTROL
, flavor
, NO_CHECK_SAME_USER
)))
1915 selfpid
= proc_selfpid();
1916 if (pid
== selfpid
) {
1918 } else if (target_p
->p_ppid
== selfpid
) {
1923 case PROC_DIRTYCONTROL_TRACK
: {
1924 /* Only allow the process itself, its parent, or root */
1925 if ((self
== FALSE
) && (child
== FALSE
) && kauth_cred_issuser(kauth_cred_get()) != TRUE
) {
1930 error
= memorystatus_dirty_track(target_p
, pcontrol
);
1934 case PROC_DIRTYCONTROL_SET
: {
1935 /* Check privileges; use cansignal() here since the process could be terminated */
1936 if (!cansignal(current_proc(), my_cred
, target_p
, SIGKILL
, 0)) {
1941 error
= memorystatus_dirty_set(target_p
, self
, pcontrol
);
1945 case PROC_DIRTYCONTROL_GET
: {
1946 /* No permissions check - dirty state is freely available */
1948 *retval
= memorystatus_dirty_get(target_p
);
1958 proc_drop_zombref(target_p
);
1960 proc_rele(target_p
);
1962 kauth_cred_unref(&target_cred
);
1969 proc_dirtycontrol(__unused
int pid
, __unused
int flavor
, __unused
uint64_t arg
, __unused
int32_t *retval
) {
1973 #endif /* CONFIG_MEMORYSTATUS */
1976 * proc_terminate() provides support for sudden termination.
1977 * SIGKILL is issued to tracked, clean processes; otherwise,
1982 proc_terminate(int pid
, int32_t *retval
)
1986 kauth_cred_t uc
= kauth_cred_get();
1990 /* XXX: Check if these are necessary */
1991 AUDIT_ARG(pid
, pid
);
1992 AUDIT_ARG(signum
, sig
);
1995 if (pid
<= 0 || retval
== NULL
) {
1999 if ((p
= proc_find(pid
)) == NULL
) {
2004 /* XXX: Check if these are necessary */
2005 AUDIT_ARG(process
, p
);
2008 /* Check privileges; if SIGKILL can be issued, then SIGTERM is also OK */
2009 if (!cansignal(current_proc(), uc
, p
, SIGKILL
, 0)) {
2014 /* Not allowed to sudden terminate yourself */
2015 if (p
== current_proc()) {
2020 #if CONFIG_MEMORYSTATUS
2021 /* Determine requisite signal to issue */
2022 sig
= memorystatus_on_terminate(p
);
2027 proc_set_task_policy(p
->task
, THREAD_NULL
, TASK_POLICY_ATTRIBUTE
,
2028 TASK_POLICY_TERMINATED
, TASK_POLICY_ENABLE
);
2040 * copy stat64 structure into vinfo_stat structure.
2043 munge_vinfo_stat(struct stat64
*sbp
, struct vinfo_stat
*vsbp
)
2045 bzero(vsbp
, sizeof(struct vinfo_stat
));
2047 vsbp
->vst_dev
= sbp
->st_dev
;
2048 vsbp
->vst_mode
= sbp
->st_mode
;
2049 vsbp
->vst_nlink
= sbp
->st_nlink
;
2050 vsbp
->vst_ino
= sbp
->st_ino
;
2051 vsbp
->vst_uid
= sbp
->st_uid
;
2052 vsbp
->vst_gid
= sbp
->st_gid
;
2053 vsbp
->vst_atime
= sbp
->st_atimespec
.tv_sec
;
2054 vsbp
->vst_atimensec
= sbp
->st_atimespec
.tv_nsec
;
2055 vsbp
->vst_mtime
= sbp
->st_mtimespec
.tv_sec
;
2056 vsbp
->vst_mtimensec
= sbp
->st_mtimespec
.tv_nsec
;
2057 vsbp
->vst_ctime
= sbp
->st_ctimespec
.tv_sec
;
2058 vsbp
->vst_ctimensec
= sbp
->st_ctimespec
.tv_nsec
;
2059 vsbp
->vst_birthtime
= sbp
->st_birthtimespec
.tv_sec
;
2060 vsbp
->vst_birthtimensec
= sbp
->st_birthtimespec
.tv_nsec
;
2061 vsbp
->vst_size
= sbp
->st_size
;
2062 vsbp
->vst_blocks
= sbp
->st_blocks
;
2063 vsbp
->vst_blksize
= sbp
->st_blksize
;
2064 vsbp
->vst_flags
= sbp
->st_flags
;
2065 vsbp
->vst_gen
= sbp
->st_gen
;
2066 vsbp
->vst_rdev
= sbp
->st_rdev
;
2067 vsbp
->vst_qspare
[0] = sbp
->st_qspare
[0];
2068 vsbp
->vst_qspare
[1] = sbp
->st_qspare
[1];
2072 proc_pid_rusage(int pid
, int flavor
, user_addr_t buffer
, __unused
int32_t *retval
)
2078 if ((p
= proc_find(pid
)) == PROC_NULL
) {
2079 if ((p
= proc_find_zombref(pid
)) == PROC_NULL
) {
2085 /* Do we have permission to look into this? */
2086 if ((error
= proc_security_policy(p
, PROC_INFO_CALL_PIDRUSAGE
, flavor
, CHECK_SAME_USER
)))
2089 error
= proc_get_rusage(p
, flavor
, buffer
, zombie
);
2093 proc_drop_zombref(p
);