]> git.saurik.com Git - apple/xnu.git/blame - bsd/kern/proc_info.c
xnu-2782.30.5.tar.gz
[apple/xnu.git] / bsd / kern / proc_info.c
CommitLineData
0c530ab8 1/*
39236c6e 2 * Copyright (c) 2005-2013 Apple Inc. All rights reserved.
0c530ab8 3 *
2d21ac55 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
0c530ab8 5 *
2d21ac55
A
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.
0c530ab8 14 *
2d21ac55
A
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
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
0c530ab8
A
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
2d21ac55
A
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.
0c530ab8 25 *
2d21ac55 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
0c530ab8
A
27 */
28
29/*
30 * sysctl system call.
31 */
32
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>
42#include <sys/buf.h>
43#include <sys/ioctl.h>
44#include <sys/namei.h>
45#include <sys/tty.h>
46#include <sys/disklabel.h>
47#include <sys/vm.h>
48#include <sys/sysctl.h>
49#include <sys/user.h>
50#include <sys/aio_kern.h>
316670eb 51#include <sys/kern_memorystatus.h>
0c530ab8 52
b0d623f7 53#include <security/audit/audit.h>
0c530ab8
A
54
55#include <mach/machine.h>
56#include <mach/mach_types.h>
57#include <mach/vm_param.h>
58#include <kern/task.h>
0c530ab8 59#include <kern/kalloc.h>
6d2010ae 60#include <kern/assert.h>
0c530ab8
A
61#include <vm/vm_kern.h>
62#include <vm/vm_map.h>
63#include <mach/host_info.h>
64#include <mach/task_info.h>
65#include <mach/thread_info.h>
66#include <mach/vm_region.h>
67
68#include <sys/mount_internal.h>
69#include <sys/proc_info.h>
70#include <sys/bsdtask_info.h>
71#include <sys/kdebug.h>
72#include <sys/sysproto.h>
73#include <sys/msgbuf.h>
39236c6e 74#include <sys/priv.h>
0c530ab8 75
39236c6e 76#include <sys/guarded.h>
0c530ab8
A
77
78#include <machine/machine_routines.h>
79
6d2010ae
A
80#include <kern/ipc_misc.h>
81
0c530ab8
A
82#include <vm/vm_protos.h>
83
fe8ab488
A
84/* Needed by proc_pidnoteexit() */
85#include <sys/event.h>
86#include <sys/codesign.h>
87
0c530ab8
A
88struct pshmnode;
89struct psemnode;
90struct pipe;
91struct kqueue;
92struct atalk;
93
b0d623f7 94uint64_t get_dispatchqueue_offset_from_proc(void *);
39236c6e 95uint64_t get_dispatchqueue_serialno_offset_from_proc(void *);
b0d623f7 96int proc_info_internal(int callnum, int pid, int flavor, uint64_t arg, user_addr_t buffer, uint32_t buffersize, int32_t * retval);
0c530ab8 97
fe8ab488
A
98/*
99 * TODO: Replace the noinline attribute below. Currently, it serves
100 * to avoid stack bloat caused by inlining multiple functions that
101 * have large stack footprints; when the functions are independent
102 * of each other (will not both be called in any given call to the
103 * caller), this only serves to bloat the stack, as we allocate
104 * space for both functions, despite the fact that we only need a
105 * fraction of that space.
106 *
107 * Long term, these functions should not be allocating everything on
108 * the stack, and should move large allocations (the huge structs
109 * that proc info deals in) to the heap, or eliminate them if
110 * possible.
111 *
112 * The functions that most desperately need to improve stack usage
113 * (starting with the worst offenders):
114 * proc_pidvnodepathinfo
115 * proc_pidinfo
116 * proc_pidregionpathinfo
117 * pid_vnodeinfopath
118 * pid_pshminfo
119 * pid_pseminfo
120 * pid_socketinfo
121 * proc_pid_rusage
122 * proc_pidoriginatorinfo
123 */
124
0c530ab8 125/* protos for proc_info calls */
fe8ab488
A
126int __attribute__ ((noinline)) proc_listpids(uint32_t type, uint32_t tyoneinfo, user_addr_t buffer, uint32_t buffersize, int32_t * retval);
127int __attribute__ ((noinline)) proc_pidinfo(int pid, int flavor, uint64_t arg, user_addr_t buffer, uint32_t buffersize, int32_t * retval);
128int __attribute__ ((noinline)) proc_pidfdinfo(int pid, int flavor,int fd, user_addr_t buffer, uint32_t buffersize, int32_t * retval);
129int __attribute__ ((noinline)) proc_kernmsgbuf(user_addr_t buffer, uint32_t buffersize, int32_t * retval);
130int __attribute__ ((noinline)) proc_setcontrol(int pid, int flavor, uint64_t arg, user_addr_t buffer, uint32_t buffersize, int32_t * retval);
131int __attribute__ ((noinline)) proc_pidfileportinfo(int pid, int flavor, mach_port_name_t name, user_addr_t buffer, uint32_t buffersize, int32_t *retval);
132int __attribute__ ((noinline)) proc_dirtycontrol(int pid, int flavor, uint64_t arg, int32_t * retval);
133int __attribute__ ((noinline)) proc_terminate(int pid, int32_t * retval);
134int __attribute__ ((noinline)) proc_pid_rusage(int pid, int flavor, user_addr_t buffer, int32_t * retval);
135int __attribute__ ((noinline)) proc_pidoriginatorinfo(int pid, int flavor, user_addr_t buffer, uint32_t buffersize, int32_t * retval);
0c530ab8
A
136
137/* protos for procpidinfo calls */
fe8ab488
A
138int __attribute__ ((noinline)) proc_pidfdlist(proc_t p, user_addr_t buffer, uint32_t buffersize, int32_t *retval);
139int __attribute__ ((noinline)) proc_pidbsdinfo(proc_t p, struct proc_bsdinfo *pbsd, int zombie);
140int __attribute__ ((noinline)) proc_pidshortbsdinfo(proc_t p, struct proc_bsdshortinfo *pbsd_shortp, int zombie);
141int __attribute__ ((noinline)) proc_pidtaskinfo(proc_t p, struct proc_taskinfo *ptinfo);
142int __attribute__ ((noinline)) proc_pidthreadinfo(proc_t p, uint64_t arg, int thuniqueid, struct proc_threadinfo *pthinfo);
143int __attribute__ ((noinline)) proc_pidthreadpathinfo(proc_t p, uint64_t arg, struct proc_threadwithpathinfo *pinfo);
144int __attribute__ ((noinline)) proc_pidlistthreads(proc_t p, user_addr_t buffer, uint32_t buffersize, int32_t *retval);
145int __attribute__ ((noinline)) proc_pidregioninfo(proc_t p, uint64_t arg, user_addr_t buffer, uint32_t buffersize, int32_t *retval);
146int __attribute__ ((noinline)) proc_pidregionpathinfo(proc_t p, uint64_t arg, user_addr_t buffer, uint32_t buffersize, int32_t *retval);
147int __attribute__ ((noinline)) proc_pidregionpathinfo2(proc_t p, uint64_t arg, user_addr_t buffer, uint32_t buffersize, int32_t *retval);
148int __attribute__ ((noinline)) proc_pidregionpathinfo3(proc_t p, uint64_t arg, user_addr_t buffer, uint32_t buffersize, int32_t *retval);
149int __attribute__ ((noinline)) proc_pidvnodepathinfo(proc_t p, uint64_t arg, user_addr_t buffer, uint32_t buffersize, int32_t *retval);
150int __attribute__ ((noinline)) proc_pidpathinfo(proc_t p, uint64_t arg, user_addr_t buffer, uint32_t buffersize, int32_t *retval);
151int __attribute__ ((noinline)) proc_pidworkqueueinfo(proc_t p, struct proc_workqueueinfo *pwqinfo);
152int __attribute__ ((noinline)) proc_pidfileportlist(proc_t p, user_addr_t buffer, uint32_t buffersize, int32_t *retval);
153void __attribute__ ((noinline)) proc_piduniqidentifierinfo(proc_t p, struct proc_uniqidentifierinfo *p_uniqidinfo);
154void __attribute__ ((noinline)) proc_archinfo(proc_t p, struct proc_archinfo *pai);
155void __attribute__ ((noinline)) proc_pidcoalitioninfo(proc_t p, struct proc_pidcoalitioninfo *pci);
156int __attribute__ ((noinline)) proc_pidnoteexit(proc_t p, uint64_t arg, uint32_t *data);
0c530ab8
A
157
158
159/* protos for proc_pidfdinfo calls */
fe8ab488
A
160int __attribute__ ((noinline)) pid_vnodeinfo(vnode_t vp, uint32_t vid, struct fileproc * fp, int closeonexec, user_addr_t buffer, uint32_t buffersize, int32_t * retval);
161int __attribute__ ((noinline)) pid_vnodeinfopath(vnode_t vp, uint32_t vid, struct fileproc * fp, int closeonexec, user_addr_t buffer, uint32_t buffersize, int32_t * retval);
162int __attribute__ ((noinline)) pid_socketinfo(socket_t so, struct fileproc *fp, int closeonexec, user_addr_t buffer, uint32_t buffersize, int32_t * retval);
163int __attribute__ ((noinline)) pid_pseminfo(struct psemnode * psem, struct fileproc * fp, int closeonexec, user_addr_t buffer, uint32_t buffersize, int32_t * retval);
164int __attribute__ ((noinline)) pid_pshminfo(struct pshmnode * pshm, struct fileproc * fp, int closeonexec, user_addr_t buffer, uint32_t buffersize, int32_t * retval);
165int __attribute__ ((noinline)) pid_pipeinfo(struct pipe * p, struct fileproc * fp, int closeonexec, user_addr_t buffer, uint32_t buffersize, int32_t * retval);
166int __attribute__ ((noinline)) pid_kqueueinfo(struct kqueue * kq, struct fileproc * fp, int closeonexec, user_addr_t buffer, uint32_t buffersize, int32_t * retval);
167int __attribute__ ((noinline)) pid_atalkinfo(struct atalk * at, struct fileproc * fp, int closeonexec, user_addr_t buffer, uint32_t buffersize, int32_t * retval);
0c530ab8
A
168
169
170/* protos for misc */
171
172int fill_vnodeinfo(vnode_t vp, struct vnode_info *vinfo);
2d21ac55 173void fill_fileinfo(struct fileproc * fp, int closeonexec, struct proc_fileinfo * finfo);
39236c6e 174int proc_security_policy(proc_t targetp, int callnum, int flavor, boolean_t check_same_user);
2d21ac55 175static void munge_vinfo_stat(struct stat64 *sbp, struct vinfo_stat *vsbp);
fe8ab488 176static int proc_piduuidinfo(pid_t pid, uuid_t uuid_buf, uint32_t buffersize);
0c530ab8 177
316670eb 178extern int cansignal(struct proc *, kauth_cred_t, struct proc *, int, int);
39236c6e
A
179extern int proc_get_rusage(proc_t proc, int flavor, user_addr_t buffer, int is_zombie);
180
181#define CHECK_SAME_USER TRUE
182#define NO_CHECK_SAME_USER FALSE
316670eb 183
b0d623f7
A
184uint64_t get_dispatchqueue_offset_from_proc(void *p)
185{
186 if(p != NULL) {
187 proc_t pself = (proc_t)p;
188 return (pself->p_dispatchqueue_offset);
189 } else {
190 return (uint64_t)0;
191 }
192}
193
39236c6e
A
194uint64_t get_dispatchqueue_serialno_offset_from_proc(void *p)
195{
196 if(p != NULL) {
197 proc_t pself = (proc_t)p;
198 return (pself->p_dispatchqueue_serialno_offset);
199 } else {
200 return (uint64_t)0;
201 }
202}
203
0c530ab8
A
204/***************************** proc_info ********************/
205
206int
b0d623f7 207proc_info(__unused struct proc *p, struct proc_info_args * uap, int32_t *retval)
0c530ab8
A
208{
209 return(proc_info_internal(uap->callnum, uap->pid, uap->flavor, uap->arg, uap->buffer, uap->buffersize, retval));
210}
211
212
213int
b0d623f7 214proc_info_internal(int callnum, int pid, int flavor, uint64_t arg, user_addr_t buffer, uint32_t buffersize, int32_t * retval)
0c530ab8
A
215{
216
217 switch(callnum) {
39236c6e 218 case PROC_INFO_CALL_LISTPIDS:
0c530ab8
A
219 /* pid contains type and flavor contains typeinfo */
220 return(proc_listpids(pid, flavor, buffer, buffersize, retval));
39236c6e 221 case PROC_INFO_CALL_PIDINFO:
0c530ab8 222 return(proc_pidinfo(pid, flavor, arg, buffer, buffersize, retval));
39236c6e 223 case PROC_INFO_CALL_PIDFDINFO:
0c530ab8 224 return(proc_pidfdinfo(pid, flavor, (int)arg, buffer, buffersize, retval));
39236c6e 225 case PROC_INFO_CALL_KERNMSGBUF:
2d21ac55 226 return(proc_kernmsgbuf(buffer, buffersize, retval));
39236c6e 227 case PROC_INFO_CALL_SETCONTROL:
b0d623f7 228 return(proc_setcontrol(pid, flavor, arg, buffer, buffersize, retval));
39236c6e 229 case PROC_INFO_CALL_PIDFILEPORTINFO:
6d2010ae 230 return(proc_pidfileportinfo(pid, flavor, (mach_port_name_t)arg, buffer, buffersize, retval));
39236c6e 231 case PROC_INFO_CALL_TERMINATE:
316670eb 232 return(proc_terminate(pid, retval));
39236c6e 233 case PROC_INFO_CALL_DIRTYCONTROL:
316670eb 234 return(proc_dirtycontrol(pid, flavor, arg, retval));
39236c6e
A
235 case PROC_INFO_CALL_PIDRUSAGE:
236 return (proc_pid_rusage(pid, flavor, buffer, retval));
fe8ab488
A
237 case PROC_INFO_CALL_PIDORIGINATORINFO:
238 return (proc_pidoriginatorinfo(pid, flavor, buffer, buffersize, retval));
0c530ab8
A
239 default:
240 return(EINVAL);
241 }
242
243 return(EINVAL);
244}
245
246/******************* proc_listpids routine ****************/
247int
b0d623f7 248proc_listpids(uint32_t type, uint32_t typeinfo, user_addr_t buffer, uint32_t buffersize, int32_t * retval)
0c530ab8 249{
0c530ab8
A
250 int numprocs, wantpids;
251 char * kbuf;
252 int * ptr;
253 int n, skip;
254 struct proc * p;
b0d623f7 255 struct tty * tp;
0c530ab8 256 int error = 0;
6d2010ae 257 struct proclist *current_list;
0c530ab8 258
39236c6e
A
259 /* Do we have permission to look into this? */
260 if ((error = proc_security_policy(PROC_NULL, PROC_INFO_CALL_LISTPIDS, type, NO_CHECK_SAME_USER)))
261 return (error);
262
0c530ab8
A
263 /* if the buffer is null, return num of procs */
264 if (buffer == (user_addr_t)0) {
265 *retval = ((nprocs+20) * sizeof(int));
266 return(0);
267 }
268
269 if (buffersize < sizeof(int)) {
270 return(ENOMEM);
271 }
272 wantpids = buffersize/sizeof(int);
273 numprocs = nprocs+20;
274 if (numprocs > wantpids)
275 numprocs = wantpids;
276
277 kbuf = (char *)kalloc((vm_size_t)(numprocs * sizeof(int)));
2d21ac55
A
278 if (kbuf == NULL)
279 return(ENOMEM);
0c530ab8
A
280 bzero(kbuf, sizeof(int));
281
2d21ac55
A
282 proc_list_lock();
283
0c530ab8
A
284
285 n = 0;
286 ptr = (int *)kbuf;
6d2010ae
A
287 current_list = &allproc;
288proc_loop:
289 LIST_FOREACH(p, current_list, p_list) {
0c530ab8
A
290 skip = 0;
291 switch (type) {
292 case PROC_PGRP_ONLY:
2d21ac55 293 if (p->p_pgrpid != (pid_t)typeinfo)
0c530ab8
A
294 skip = 1;
295 break;
6d2010ae
A
296 case PROC_PPID_ONLY:
297 if ((p->p_ppid != (pid_t)typeinfo) && (((p->p_lflag & P_LTRACED) == 0) || (p->p_oppid != (pid_t)typeinfo)))
298 skip = 1;
299 break;
300
0c530ab8
A
301 case PROC_ALL_PIDS:
302 skip = 0;
303 break;
304 case PROC_TTY_ONLY:
2d21ac55 305 /* racy but list lock is held */
0c530ab8 306 if ((p->p_flag & P_CONTROLT) == 0 ||
2d21ac55 307 (p->p_pgrp == NULL) || (p->p_pgrp->pg_session == NULL) ||
b0d623f7
A
308 (tp = SESSION_TP(p->p_pgrp->pg_session)) == TTY_NULL ||
309 tp->t_dev != (dev_t)typeinfo)
0c530ab8
A
310 skip = 1;
311 break;
312 case PROC_UID_ONLY:
2d21ac55 313 if (p->p_ucred == NULL)
0c530ab8 314 skip = 1;
2d21ac55
A
315 else {
316 kauth_cred_t my_cred;
317 uid_t uid;
318
319 my_cred = kauth_cred_proc_ref(p);
320 uid = kauth_cred_getuid(my_cred);
321 kauth_cred_unref(&my_cred);
322 if (uid != (uid_t)typeinfo)
323 skip = 1;
324 }
0c530ab8
A
325 break;
326 case PROC_RUID_ONLY:
2d21ac55
A
327 if (p->p_ucred == NULL)
328 skip = 1;
329 else {
330 kauth_cred_t my_cred;
331 uid_t uid;
332
333 my_cred = kauth_cred_proc_ref(p);
6d2010ae 334 uid = kauth_cred_getruid(my_cred);
2d21ac55
A
335 kauth_cred_unref(&my_cred);
336 if (uid != (uid_t)typeinfo)
337 skip = 1;
338 }
0c530ab8
A
339 break;
340 default:
341 skip = 1;
342 break;
343 };
344
0c530ab8
A
345 if(skip == 0) {
346 *ptr++ = p->p_pid;
347 n++;
348 }
349 if (n >= numprocs)
350 break;
351 }
352
6d2010ae
A
353 if ((n < numprocs) && (current_list == &allproc)) {
354 current_list = &zombproc;
355 goto proc_loop;
0c530ab8 356 }
2d21ac55
A
357
358 proc_list_unlock();
0c530ab8
A
359
360 ptr = (int *)kbuf;
361 error = copyout((caddr_t)ptr, buffer, n * sizeof(int));
362 if (error == 0)
363 *retval = (n * sizeof(int));
364 kfree((void *)kbuf, (vm_size_t)(numprocs * sizeof(int)));
365
366 return(error);
367}
368
369
fe8ab488 370/********************************** proc_pidfdlist routines ********************************/
0c530ab8
A
371
372int
b0d623f7 373proc_pidfdlist(proc_t p, user_addr_t buffer, uint32_t buffersize, int32_t *retval)
0c530ab8
A
374{
375 int numfds, needfds;
376 char * kbuf;
377 struct proc_fdinfo * pfd;
378 struct fileproc * fp;
379 int n;
380 int count = 0;
381 int error = 0;
382
383 numfds = p->p_fd->fd_nfiles;
384
385 if (buffer == (user_addr_t) 0) {
386 numfds += 20;
387 *retval = (numfds * sizeof(struct proc_fdinfo));
388 return(0);
389 }
390
391 /* buffersize is big enough atleast for one struct */
392 needfds = buffersize/sizeof(struct proc_fdinfo);
393
394 if (numfds > needfds)
395 numfds = needfds;
396
397 kbuf = (char *)kalloc((vm_size_t)(numfds * sizeof(struct proc_fdinfo)));
2d21ac55
A
398 if (kbuf == NULL)
399 return(ENOMEM);
0c530ab8
A
400 bzero(kbuf, numfds * sizeof(struct proc_fdinfo));
401
402 proc_fdlock(p);
403
404 pfd = (struct proc_fdinfo *)kbuf;
405
406 for (n = 0; ((n < numfds) && (n < p->p_fd->fd_nfiles)); n++) {
407 if (((fp = p->p_fd->fd_ofiles[n]) != 0)
408 && ((p->p_fd->fd_ofileflags[n] & UF_RESERVED) == 0)) {
39236c6e 409 file_type_t fdtype = FILEGLOB_DTYPE(fp->f_fglob);
0c530ab8 410 pfd->proc_fd = n;
39236c6e
A
411 pfd->proc_fdtype = (fdtype != DTYPE_ATALK) ?
412 fdtype : PROX_FDTYPE_ATALK;
0c530ab8
A
413 count++;
414 pfd++;
415 }
416 }
417 proc_fdunlock(p);
418
419 error = copyout(kbuf, buffer, count * sizeof(struct proc_fdinfo));
420 kfree((void *)kbuf, (vm_size_t)(numfds * sizeof(struct proc_fdinfo)));
421 if (error == 0)
422 *retval = (count * sizeof(struct proc_fdinfo));
423 return(error);
424}
425
6d2010ae
A
426/*
427 * Helper functions for proc_pidfileportlist.
428 */
429static int
430proc_fileport_count(__unused mach_port_name_t name,
431 __unused struct fileglob *fg, void *arg)
432{
433 uint32_t *counter = arg;
434
435 *counter += 1;
436 return (0);
437}
438
439struct fileport_fdtype_args {
440 struct proc_fileportinfo *ffa_pfi;
441 struct proc_fileportinfo *ffa_pfi_end;
442};
443
444static int
445proc_fileport_fdtype(mach_port_name_t name, struct fileglob *fg, void *arg)
446{
447 struct fileport_fdtype_args *ffa = arg;
448
449 if (ffa->ffa_pfi != ffa->ffa_pfi_end) {
39236c6e
A
450 file_type_t fdtype = FILEGLOB_DTYPE(fg);
451
452 ffa->ffa_pfi->proc_fdtype = (fdtype != DTYPE_ATALK) ?
453 fdtype : PROX_FDTYPE_ATALK;
6d2010ae
A
454 ffa->ffa_pfi->proc_fileport = name;
455 ffa->ffa_pfi++;
456 return (0); /* keep walking */
457 } else
458 return (-1); /* stop the walk! */
459}
460
461int
462proc_pidfileportlist(proc_t p,
463 user_addr_t buffer, uint32_t buffersize, int32_t *retval)
464{
465 void *kbuf;
466 vm_size_t kbufsize;
467 struct proc_fileportinfo *pfi;
468 uint32_t needfileports, numfileports;
469 struct fileport_fdtype_args ffa;
470 int error;
471
472 needfileports = buffersize / sizeof (*pfi);
473 if ((user_addr_t)0 == buffer || needfileports > (uint32_t)maxfiles) {
474 /*
475 * Either (i) the user is asking for a fileport count,
476 * or (ii) the number of fileports they're asking for is
477 * larger than the maximum number of open files (!); count
478 * them to bound subsequent heap allocations.
479 */
480 numfileports = 0;
481 switch (fileport_walk(p->task,
482 proc_fileport_count, &numfileports)) {
483 case KERN_SUCCESS:
484 break;
485 case KERN_RESOURCE_SHORTAGE:
486 return (ENOMEM);
487 case KERN_INVALID_TASK:
488 return (ESRCH);
489 default:
490 return (EINVAL);
491 }
492
493 if (numfileports == 0) {
494 *retval = 0; /* none at all, bail */
495 return (0);
496 }
497 if ((user_addr_t)0 == buffer) {
498 numfileports += 20; /* accelerate convergence */
499 *retval = numfileports * sizeof (*pfi);
500 return (0);
501 }
502 if (needfileports > numfileports)
503 needfileports = numfileports;
504 }
505
506 assert(buffersize >= PROC_PIDLISTFILEPORTS_SIZE);
507
508 kbufsize = (vm_size_t)needfileports * sizeof (*pfi);
509 pfi = kbuf = kalloc(kbufsize);
510 if (kbuf == NULL)
511 return (ENOMEM);
512 bzero(kbuf, kbufsize);
513
514 ffa.ffa_pfi = pfi;
515 ffa.ffa_pfi_end = pfi + needfileports;
516
517 switch (fileport_walk(p->task, proc_fileport_fdtype, &ffa)) {
518 case KERN_SUCCESS:
519 error = 0;
520 pfi = ffa.ffa_pfi;
521 if ((numfileports = pfi - (typeof(pfi))kbuf) == 0)
522 break;
523 if (numfileports > needfileports)
524 panic("more fileports returned than requested");
525 error = copyout(kbuf, buffer, numfileports * sizeof (*pfi));
526 break;
527 case KERN_RESOURCE_SHORTAGE:
528 error = ENOMEM;
529 break;
530 case KERN_INVALID_TASK:
531 error = ESRCH;
532 break;
533 default:
534 error = EINVAL;
535 break;
536 }
537 kfree(kbuf, kbufsize);
538 if (error == 0)
539 *retval = numfileports * sizeof (*pfi);
540 return (error);
541}
0c530ab8
A
542
543int
b0d623f7 544proc_pidbsdinfo(proc_t p, struct proc_bsdinfo * pbsd, int zombie)
0c530ab8
A
545{
546 register struct tty *tp;
547 struct session *sessionp = NULL;
2d21ac55
A
548 struct pgrp * pg;
549 kauth_cred_t my_cred;
0c530ab8 550
2d21ac55
A
551 pg = proc_pgrp(p);
552 sessionp = proc_session(p);
553
554 my_cred = kauth_cred_proc_ref(p);
0c530ab8
A
555 bzero(pbsd, sizeof(struct proc_bsdinfo));
556 pbsd->pbi_status = p->p_stat;
557 pbsd->pbi_xstatus = p->p_xstat;
558 pbsd->pbi_pid = p->p_pid;
2d21ac55 559 pbsd->pbi_ppid = p->p_ppid;
6d2010ae
A
560 pbsd->pbi_uid = kauth_cred_getuid(my_cred);
561 pbsd->pbi_gid = kauth_cred_getgid(my_cred);
562 pbsd->pbi_ruid = kauth_cred_getruid(my_cred);
563 pbsd->pbi_rgid = kauth_cred_getrgid(my_cred);
564 pbsd->pbi_svuid = kauth_cred_getsvuid(my_cred);
565 pbsd->pbi_svgid = kauth_cred_getsvgid(my_cred);
2d21ac55 566 kauth_cred_unref(&my_cred);
0c530ab8
A
567
568 pbsd->pbi_nice = p->p_nice;
b0d623f7
A
569 pbsd->pbi_start_tvsec = p->p_start.tv_sec;
570 pbsd->pbi_start_tvusec = p->p_start.tv_usec;
6d2010ae
A
571 bcopy(&p->p_comm, &pbsd->pbi_comm[0], MAXCOMLEN);
572 pbsd->pbi_comm[MAXCOMLEN - 1] = '\0';
573 bcopy(&p->p_name, &pbsd->pbi_name[0], 2*MAXCOMLEN);
574 pbsd->pbi_name[(2*MAXCOMLEN) - 1] = '\0';
0c530ab8
A
575
576 pbsd->pbi_flags = 0;
577 if ((p->p_flag & P_SYSTEM) == P_SYSTEM)
578 pbsd->pbi_flags |= PROC_FLAG_SYSTEM;
2d21ac55 579 if ((p->p_lflag & P_LTRACED) == P_LTRACED)
0c530ab8 580 pbsd->pbi_flags |= PROC_FLAG_TRACED;
2d21ac55 581 if ((p->p_lflag & P_LEXIT) == P_LEXIT)
0c530ab8 582 pbsd->pbi_flags |= PROC_FLAG_INEXIT;
2d21ac55 583 if ((p->p_lflag & P_LPPWAIT) == P_LPPWAIT)
0c530ab8
A
584 pbsd->pbi_flags |= PROC_FLAG_PPWAIT;
585 if ((p->p_flag & P_LP64) == P_LP64)
586 pbsd->pbi_flags |= PROC_FLAG_LP64;
587 if ((p->p_flag & P_CONTROLT) == P_CONTROLT)
588 pbsd->pbi_flags |= PROC_FLAG_CONTROLT;
2d21ac55
A
589 if ((p->p_flag & P_THCWD) == P_THCWD)
590 pbsd->pbi_flags |= PROC_FLAG_THCWD;
6d2010ae
A
591 if ((p->p_flag & P_SUGID) == P_SUGID)
592 pbsd->pbi_flags |= PROC_FLAG_PSUGID;
593 if ((p->p_flag & P_EXEC) == P_EXEC)
594 pbsd->pbi_flags |= PROC_FLAG_EXEC;
0c530ab8 595
b0d623f7
A
596 if (sessionp != SESSION_NULL) {
597 if (SESS_LEADER(p, sessionp))
598 pbsd->pbi_flags |= PROC_FLAG_SLEADER;
599 if (sessionp->s_ttyvp)
600 pbsd->pbi_flags |= PROC_FLAG_CTTY;
601 }
602
316670eb
A
603 if ((p->p_flag & P_DELAYIDLESLEEP) == P_DELAYIDLESLEEP)
604 pbsd->pbi_flags |= PROC_FLAG_DELAYIDLESLEEP;
b0d623f7
A
605
606 switch(PROC_CONTROL_STATE(p)) {
607 case P_PCTHROTTLE:
608 pbsd->pbi_flags |= PROC_FLAG_PC_THROTTLE;
609 break;
610 case P_PCSUSP:
611 pbsd->pbi_flags |= PROC_FLAG_PC_SUSP;
612 break;
613 case P_PCKILL:
614 pbsd->pbi_flags |= PROC_FLAG_PC_KILL;
615 break;
616 };
617
618 switch(PROC_ACTION_STATE(p)) {
619 case P_PCTHROTTLE:
620 pbsd->pbi_flags |= PROC_FLAG_PA_THROTTLE;
621 break;
622 case P_PCSUSP:
623 pbsd->pbi_flags |= PROC_FLAG_PA_SUSP;
624 break;
625 };
0c530ab8 626
6d2010ae
A
627 /* if process is a zombie skip bg state */
628 if ((zombie == 0) && (p->p_stat != SZOMB) && (p->task != TASK_NULL))
629 proc_get_darwinbgstate(p->task, &pbsd->pbi_flags);
630
b0d623f7
A
631 if (zombie == 0)
632 pbsd->pbi_nfiles = p->p_fd->fd_nfiles;
316670eb
A
633
634 pbsd->e_tdev = NODEV;
2d21ac55
A
635 if (pg != PGRP_NULL) {
636 pbsd->pbi_pgid = p->p_pgrpid;
637 pbsd->pbi_pjobc = pg->pg_jobc;
b0d623f7 638 if ((p->p_flag & P_CONTROLT) && (sessionp != SESSION_NULL) && (tp = SESSION_TP(sessionp))) {
0c530ab8 639 pbsd->e_tdev = tp->t_dev;
2d21ac55 640 pbsd->e_tpgid = sessionp->s_ttypgrpid;
0c530ab8
A
641 }
642 }
2d21ac55
A
643 if (sessionp != SESSION_NULL)
644 session_rele(sessionp);
645 if (pg != PGRP_NULL)
646 pg_rele(pg);
647
0c530ab8
A
648 return(0);
649}
650
651
6d2010ae
A
652int
653proc_pidshortbsdinfo(proc_t p, struct proc_bsdshortinfo * pbsd_shortp, int zombie)
654{
655 bzero(pbsd_shortp, sizeof(struct proc_bsdshortinfo));
656 pbsd_shortp->pbsi_pid = p->p_pid;
657 pbsd_shortp->pbsi_ppid = p->p_ppid;
658 pbsd_shortp->pbsi_pgid = p->p_pgrpid;
659 pbsd_shortp->pbsi_status = p->p_stat;
660 bcopy(&p->p_comm, &pbsd_shortp->pbsi_comm[0], MAXCOMLEN);
661 pbsd_shortp->pbsi_comm[MAXCOMLEN - 1] = '\0';
662
663 pbsd_shortp->pbsi_flags = 0;
664 if ((p->p_flag & P_SYSTEM) == P_SYSTEM)
665 pbsd_shortp->pbsi_flags |= PROC_FLAG_SYSTEM;
666 if ((p->p_lflag & P_LTRACED) == P_LTRACED)
667 pbsd_shortp->pbsi_flags |= PROC_FLAG_TRACED;
668 if ((p->p_lflag & P_LEXIT) == P_LEXIT)
669 pbsd_shortp->pbsi_flags |= PROC_FLAG_INEXIT;
670 if ((p->p_lflag & P_LPPWAIT) == P_LPPWAIT)
671 pbsd_shortp->pbsi_flags |= PROC_FLAG_PPWAIT;
672 if ((p->p_flag & P_LP64) == P_LP64)
673 pbsd_shortp->pbsi_flags |= PROC_FLAG_LP64;
674 if ((p->p_flag & P_CONTROLT) == P_CONTROLT)
675 pbsd_shortp->pbsi_flags |= PROC_FLAG_CONTROLT;
676 if ((p->p_flag & P_THCWD) == P_THCWD)
677 pbsd_shortp->pbsi_flags |= PROC_FLAG_THCWD;
678 if ((p->p_flag & P_SUGID) == P_SUGID)
679 pbsd_shortp->pbsi_flags |= PROC_FLAG_PSUGID;
680 if ((p->p_flag & P_EXEC) == P_EXEC)
681 pbsd_shortp->pbsi_flags |= PROC_FLAG_EXEC;
316670eb
A
682 if ((p->p_flag & P_DELAYIDLESLEEP) == P_DELAYIDLESLEEP)
683 pbsd_shortp->pbsi_flags |= PROC_FLAG_DELAYIDLESLEEP;
6d2010ae
A
684
685 switch(PROC_CONTROL_STATE(p)) {
686 case P_PCTHROTTLE:
687 pbsd_shortp->pbsi_flags |= PROC_FLAG_PC_THROTTLE;
688 break;
689 case P_PCSUSP:
690 pbsd_shortp->pbsi_flags |= PROC_FLAG_PC_SUSP;
691 break;
692 case P_PCKILL:
693 pbsd_shortp->pbsi_flags |= PROC_FLAG_PC_KILL;
694 break;
695 };
696
697 switch(PROC_ACTION_STATE(p)) {
698 case P_PCTHROTTLE:
699 pbsd_shortp->pbsi_flags |= PROC_FLAG_PA_THROTTLE;
700 break;
701 case P_PCSUSP:
702 pbsd_shortp->pbsi_flags |= PROC_FLAG_PA_SUSP;
703 break;
704 };
705
706 /* if process is a zombie skip bg state */
707 if ((zombie == 0) && (p->p_stat != SZOMB) && (p->task != TASK_NULL))
708 proc_get_darwinbgstate(p->task, &pbsd_shortp->pbsi_flags);
709
710 pbsd_shortp->pbsi_uid = p->p_uid;
711 pbsd_shortp->pbsi_gid = p->p_gid;
712 pbsd_shortp->pbsi_ruid = p->p_ruid;
713 pbsd_shortp->pbsi_rgid = p->p_rgid;
714 pbsd_shortp->pbsi_svuid = p->p_svuid;
715 pbsd_shortp->pbsi_svgid = p->p_svgid;
716
717 return(0);
718}
719
0c530ab8
A
720int
721proc_pidtaskinfo(proc_t p, struct proc_taskinfo * ptinfo)
722{
723 task_t task;
724
725 task = p->task;
726
727 bzero(ptinfo, sizeof(struct proc_taskinfo));
728 fill_taskprocinfo(task, (struct proc_taskinfo_internal *)ptinfo);
729
730 return(0);
731}
732
733
734
735int
316670eb 736proc_pidthreadinfo(proc_t p, uint64_t arg, int thuniqueid, struct proc_threadinfo *pthinfo)
0c530ab8
A
737{
738 int error = 0;
739 uint64_t threadaddr = (uint64_t)arg;
740
741 bzero(pthinfo, sizeof(struct proc_threadinfo));
742
316670eb 743 error = fill_taskthreadinfo(p->task, threadaddr, thuniqueid, (struct proc_threadinfo_internal *)pthinfo, NULL, NULL);
0c530ab8
A
744 if (error)
745 return(ESRCH);
746 else
747 return(0);
748
749}
750
b0d623f7
A
751void
752bsd_getthreadname(void *uth, char *buffer)
753{
754 struct uthread *ut = (struct uthread *)uth;
755 if(ut->pth_name)
756 bcopy(ut->pth_name,buffer,MAXTHREADNAMESIZE);
757}
0c530ab8 758
2d21ac55
A
759void
760bsd_threadcdir(void * uth, void *vptr, int *vidp)
761{
762 struct uthread * ut = (struct uthread *)uth;
763 vnode_t vp;
764 vnode_t *vpp = (vnode_t *)vptr;
765
766 vp = ut->uu_cdir;
767 if (vp != NULLVP) {
768 if (vpp != NULL) {
769 *vpp = vp;
770 if (vidp != NULL)
771 *vidp = vp->v_id;
772 }
773 }
774}
775
776
777int
778proc_pidthreadpathinfo(proc_t p, uint64_t arg, struct proc_threadwithpathinfo *pinfo)
779{
780 vnode_t vp = NULLVP;
781 int vid;
782 int error = 0;
783 uint64_t threadaddr = (uint64_t)arg;
784 int count;
785
786 bzero(pinfo, sizeof(struct proc_threadwithpathinfo));
787
316670eb 788 error = fill_taskthreadinfo(p->task, threadaddr, 0, (struct proc_threadinfo_internal *)&pinfo->pt, (void *)&vp, &vid);
2d21ac55
A
789 if (error)
790 return(ESRCH);
791
792 if ((vp != NULLVP) && ((vnode_getwithvid(vp, vid)) == 0)) {
793 error = fill_vnodeinfo(vp, &pinfo->pvip.vip_vi) ;
794 if (error == 0) {
795 count = MAXPATHLEN;
796 vn_getpath(vp, &pinfo->pvip.vip_path[0], &count);
797 pinfo->pvip.vip_path[MAXPATHLEN-1] = 0;
798 }
799 vnode_put(vp);
800 }
801 return(error);
802}
803
804
805
0c530ab8 806int
b0d623f7 807proc_pidlistthreads(proc_t p, user_addr_t buffer, uint32_t buffersize, int32_t *retval)
0c530ab8
A
808{
809 int count = 0;
810 int ret = 0;
811 int error = 0;
812 void * kbuf;
813 int numthreads;
814
815
816 count = buffersize/(sizeof(uint64_t));
817 numthreads = get_numthreads(p->task);
818
819 numthreads += 10;
820
821 if (numthreads > count)
822 numthreads = count;
823
824 kbuf = (void *)kalloc(numthreads * sizeof(uint64_t));
2d21ac55
A
825 if (kbuf == NULL)
826 return(ENOMEM);
0c530ab8
A
827 bzero(kbuf, numthreads * sizeof(uint64_t));
828
829 ret = fill_taskthreadlist(p->task, kbuf, numthreads);
830
831 error = copyout(kbuf, buffer, ret);
832 kfree(kbuf, numthreads * sizeof(uint64_t));
833 if (error == 0)
834 *retval = ret;
835 return(error);
836
837}
838
839
840int
b0d623f7 841proc_pidregioninfo(proc_t p, uint64_t arg, user_addr_t buffer, __unused uint32_t buffersize, int32_t *retval)
0c530ab8
A
842{
843 struct proc_regioninfo preginfo;
844 int ret, error = 0;
845
846 bzero(&preginfo, sizeof(struct proc_regioninfo));
b0d623f7 847 ret = fill_procregioninfo( p->task, arg, (struct proc_regioninfo_internal *)&preginfo, (uintptr_t *)0, (uint32_t *)0);
0c530ab8
A
848 if (ret == 0)
849 return(EINVAL);
850 error = copyout(&preginfo, buffer, sizeof(struct proc_regioninfo));
851 if (error == 0)
852 *retval = sizeof(struct proc_regioninfo);
853 return(error);
854}
855
856
857int
b0d623f7 858proc_pidregionpathinfo(proc_t p, uint64_t arg, user_addr_t buffer, __unused uint32_t buffersize, int32_t *retval)
0c530ab8
A
859{
860 struct proc_regionwithpathinfo preginfo;
861 int ret, error = 0;
b0d623f7 862 uintptr_t vnodeaddr= 0;
0c530ab8
A
863 uint32_t vnodeid= 0;
864 vnode_t vp;
865 int count;
866
867 bzero(&preginfo, sizeof(struct proc_regionwithpathinfo));
868
b0d623f7 869 ret = fill_procregioninfo( p->task, arg, (struct proc_regioninfo_internal *)&preginfo.prp_prinfo, (uintptr_t *)&vnodeaddr, (uint32_t *)&vnodeid);
0c530ab8
A
870 if (ret == 0)
871 return(EINVAL);
872 if (vnodeaddr) {
873 vp = (vnode_t)vnodeaddr;
874 if ((vnode_getwithvid(vp, vnodeid)) == 0) {
875 /* FILL THE VNODEINFO */
876 error = fill_vnodeinfo(vp, &preginfo.prp_vip.vip_vi);
877 count = MAXPATHLEN;
878 vn_getpath(vp, &preginfo.prp_vip.vip_path[0], &count);
879 /* Always make sure it is null terminated */
880 preginfo.prp_vip.vip_path[MAXPATHLEN-1] = 0;
881 vnode_put(vp);
882 }
883 }
884 error = copyout(&preginfo, buffer, sizeof(struct proc_regionwithpathinfo));
885 if (error == 0)
886 *retval = sizeof(struct proc_regionwithpathinfo);
887 return(error);
888}
889
fe8ab488
A
890int
891proc_pidregionpathinfo2(proc_t p, uint64_t arg, user_addr_t buffer, __unused uint32_t buffersize, int32_t *retval)
892{
893 struct proc_regionwithpathinfo preginfo;
894 int ret, error = 0;
895 uintptr_t vnodeaddr= 0;
896 uint32_t vnodeid= 0;
897 vnode_t vp;
898 int count;
899
900 bzero(&preginfo, sizeof(struct proc_regionwithpathinfo));
901
902 ret = fill_procregioninfo_onlymappedvnodes( p->task, arg, (struct proc_regioninfo_internal *)&preginfo.prp_prinfo, (uintptr_t *)&vnodeaddr, (uint32_t *)&vnodeid);
903 if (ret == 0)
904 return(EINVAL);
905 if (!vnodeaddr)
906 return(EINVAL);
907
908 vp = (vnode_t)vnodeaddr;
909 if ((vnode_getwithvid(vp, vnodeid)) == 0) {
910 /* FILL THE VNODEINFO */
911 error = fill_vnodeinfo(vp, &preginfo.prp_vip.vip_vi);
912 count = MAXPATHLEN;
913 vn_getpath(vp, &preginfo.prp_vip.vip_path[0], &count);
914 /* Always make sure it is null terminated */
915 preginfo.prp_vip.vip_path[MAXPATHLEN-1] = 0;
916 vnode_put(vp);
917 } else {
918 return(EINVAL);
919 }
920
921 error = copyout(&preginfo, buffer, sizeof(struct proc_regionwithpathinfo));
922 if (error == 0)
923 *retval = sizeof(struct proc_regionwithpathinfo);
924 return(error);
925}
926
927int
928proc_pidregionpathinfo3(proc_t p, uint64_t arg, user_addr_t buffer, __unused uint32_t buffersize, int32_t *retval)
929{
930 struct proc_regionwithpathinfo preginfo;
931 int ret, error = 0;
932 uintptr_t vnodeaddr;
933 uint32_t vnodeid;
934 vnode_t vp;
935 int count;
936 uint64_t addr = 0;
937
938 /* Loop while looking for vnodes that match dev_t filter */
939 do {
940 bzero(&preginfo, sizeof(struct proc_regionwithpathinfo));
941 vnodeaddr = 0;
942 vnodeid = 0;
943
944 ret = fill_procregioninfo_onlymappedvnodes( p->task, addr, (struct proc_regioninfo_internal *)&preginfo.prp_prinfo, (uintptr_t *)&vnodeaddr, (uint32_t *)&vnodeid);
945 if (ret == 0)
946 return(EINVAL);
947 if (!vnodeaddr)
948 return(EINVAL);
949
950 vp = (vnode_t)vnodeaddr;
951 if ((vnode_getwithvid(vp, vnodeid)) == 0) {
952 /* Check if the vnode matches the filter, otherwise loop looking for the next memory region backed by a vnode */
953 struct vnode_attr va;
954
955 memset(&va, 0, sizeof(va));
956 VATTR_INIT(&va);
957 VATTR_WANTED(&va, va_fsid);
958
959 ret = vnode_getattr(vp, &va, vfs_context_current());
960 if (ret) {
961 vnode_put(vp);
962 return(EINVAL);
963 }
964
965 if (va.va_fsid == arg) {
966 /* FILL THE VNODEINFO */
967 error = fill_vnodeinfo(vp, &preginfo.prp_vip.vip_vi);
968 count = MAXPATHLEN;
969 vn_getpath(vp, &preginfo.prp_vip.vip_path[0], &count);
970 /* Always make sure it is null terminated */
971 preginfo.prp_vip.vip_path[MAXPATHLEN-1] = 0;
972 vnode_put(vp);
973 break;
974 }
975 vnode_put(vp);
976 } else {
977 return(EINVAL);
978 }
979
980 addr = preginfo.prp_prinfo.pri_address + preginfo.prp_prinfo.pri_size;
981 } while (1);
982
983 error = copyout(&preginfo, buffer, sizeof(struct proc_regionwithpathinfo));
984 if (error == 0)
985 *retval = sizeof(struct proc_regionwithpathinfo);
986 return(error);
987}
988
2d21ac55
A
989/*
990 * Path is relative to current process directory; may different from current
991 * thread directory.
992 */
0c530ab8 993int
b0d623f7 994proc_pidvnodepathinfo(proc_t p, __unused uint64_t arg, user_addr_t buffer, __unused uint32_t buffersize, int32_t *retval)
0c530ab8
A
995{
996 struct proc_vnodepathinfo pvninfo;
997 int error = 0;
998 vnode_t vncdirvp = NULLVP;
999 uint32_t vncdirid=0;
1000 vnode_t vnrdirvp = NULLVP;
1001 uint32_t vnrdirid=0;
1002 int count;
1003
1004 bzero(&pvninfo, sizeof(struct proc_vnodepathinfo));
1005
1006 proc_fdlock(p);
1007 if (p->p_fd->fd_cdir) {
1008 vncdirvp = p->p_fd->fd_cdir;
1009 vncdirid = p->p_fd->fd_cdir->v_id;
1010 }
1011 if (p->p_fd->fd_rdir) {
1012 vnrdirvp = p->p_fd->fd_rdir;
1013 vnrdirid = p->p_fd->fd_rdir->v_id;
1014 }
1015 proc_fdunlock(p);
1016
1017 if (vncdirvp != NULLVP) {
1018 if ((error = vnode_getwithvid(vncdirvp, vncdirid)) == 0) {
1019 /* FILL THE VNODEINFO */
1020 error = fill_vnodeinfo(vncdirvp, &pvninfo.pvi_cdir.vip_vi);
1021 if ( error == 0) {
1022 count = MAXPATHLEN;
1023 vn_getpath(vncdirvp, &pvninfo.pvi_cdir.vip_path[0], &count);
1024 pvninfo.pvi_cdir.vip_path[MAXPATHLEN-1] = 0;
1025 }
1026 vnode_put(vncdirvp);
1027 } else {
1028 goto out;
1029 }
1030 }
1031
1032 if ((error == 0) && (vnrdirvp != NULLVP)) {
1033 if ((error = vnode_getwithvid(vnrdirvp, vnrdirid)) == 0) {
1034 /* FILL THE VNODEINFO */
1035 error = fill_vnodeinfo(vnrdirvp, &pvninfo.pvi_rdir.vip_vi);
1036 if ( error == 0) {
1037 count = MAXPATHLEN;
1038 vn_getpath(vnrdirvp, &pvninfo.pvi_rdir.vip_path[0], &count);
1039 pvninfo.pvi_rdir.vip_path[MAXPATHLEN-1] = 0;
1040 }
1041 vnode_put(vnrdirvp);
1042 } else {
1043 goto out;
1044 }
1045 }
1046 if (error == 0) {
1047 error = copyout(&pvninfo, buffer, sizeof(struct proc_vnodepathinfo));
1048 if (error == 0)
1049 *retval = sizeof(struct proc_vnodepathinfo);
1050 }
1051out:
1052 return(error);
1053}
1054
2d21ac55 1055int
b0d623f7 1056proc_pidpathinfo(proc_t p, __unused uint64_t arg, user_addr_t buffer, uint32_t buffersize, __unused int32_t *retval)
2d21ac55
A
1057{
1058 int vid, error;
1059 vnode_t tvp;
1060 vnode_t nvp = NULLVP;
1061 int len = buffersize;
1062 char * buf;
1063
1064 tvp = p->p_textvp;
1065
1066 if (tvp == NULLVP)
1067 return(ESRCH);
1068
1069 buf = (char *)kalloc(buffersize);
1070 if (buf == NULL)
1071 return(ENOMEM);
1072
1073
1074 vid = vnode_vid(tvp);
1075 error = vnode_getwithvid(tvp, vid);
1076 if (error == 0) {
b0d623f7 1077 error = vn_getpath_fsenter(tvp, buf, &len);
2d21ac55
A
1078 vnode_put(tvp);
1079 if (error == 0) {
1080 error = vnode_lookup(buf, 0, &nvp, vfs_context_current());
1081 if ((error == 0) && ( nvp != NULLVP))
1082 vnode_put(nvp);
1083 if (error == 0) {
1084 error = copyout(buf, buffer, len);
1085 }
1086 }
1087 }
1088 kfree(buf, buffersize);
1089 return(error);
1090}
1091
1092
b0d623f7
A
1093int
1094proc_pidworkqueueinfo(proc_t p, struct proc_workqueueinfo *pwqinfo)
1095{
1096 int error = 0;
1097
1098 bzero(pwqinfo, sizeof(struct proc_workqueueinfo));
1099
1100 error = fill_procworkqueue(p, pwqinfo);
1101 if (error)
1102 return(ESRCH);
1103 else
1104 return(0);
1105
1106}
39236c6e
A
1107
1108
1109void
1110proc_piduniqidentifierinfo(proc_t p, struct proc_uniqidentifierinfo *p_uniqidinfo)
1111{
1112 p_uniqidinfo->p_uniqueid = proc_uniqueid(p);
1113 proc_getexecutableuuid(p, (unsigned char *)&p_uniqidinfo->p_uuid, sizeof(p_uniqidinfo->p_uuid));
1114 p_uniqidinfo->p_puniqueid = proc_puniqueid(p);
1115 p_uniqidinfo->p_reserve2 = 0;
1116 p_uniqidinfo->p_reserve3 = 0;
1117 p_uniqidinfo->p_reserve4 = 0;
1118}
1119
fe8ab488
A
1120
1121static int
1122proc_piduuidinfo(pid_t pid, uuid_t uuid_buf, uint32_t buffersize)
1123{
1124 struct proc * p = PROC_NULL;
1125 int zombref = 0;
1126
1127 if (buffersize < sizeof(uuid_t))
1128 return EINVAL;
1129
1130 if ((p = proc_find(pid)) == PROC_NULL) {
1131 p = proc_find_zombref(pid);
1132 zombref = 1;
1133 }
1134 if (p == PROC_NULL) {
1135 return ESRCH;
1136 }
1137
1138 proc_getexecutableuuid(p, (unsigned char *)uuid_buf, buffersize);
1139
1140 if (zombref)
1141 proc_drop_zombref(p);
1142 else
1143 proc_rele(p);
1144
1145 return 0;
1146}
1147
1148/*
1149 * Function to get the uuid of the originator of the voucher.
1150 */
1151int
1152proc_pidoriginatoruuid(uuid_t uuid, uint32_t buffersize)
1153{
1154 pid_t originator_pid;
1155 kern_return_t kr;
1156 int error;
1157
1158 /*
1159 * Get the current voucher origin pid. The pid returned here
1160 * might not be valid or may have been recycled.
1161 */
1162 kr = thread_get_current_voucher_origin_pid(&originator_pid);
1163 /* If errors, convert errors to appropriate format */
1164 if (kr) {
1165 if (kr == KERN_INVALID_TASK)
1166 error = ESRCH;
1167 else if (kr == KERN_INVALID_VALUE)
1168 error = ENOATTR;
1169 else
1170 error = EINVAL;
1171 return error;
1172 }
1173
1174 error = proc_piduuidinfo(originator_pid, uuid, buffersize);
1175 return error;
1176}
1177
1178/***************************** proc_pidoriginatorinfo ***************************/
1179
1180int
1181proc_pidoriginatorinfo(int pid, int flavor, user_addr_t buffer, uint32_t buffersize, int32_t * retval)
1182{
1183 int error = ENOTSUP;
1184 uint32_t size;
1185
1186 switch (flavor) {
1187 case PROC_PIDORIGINATOR_UUID:
1188 size = PROC_PIDORIGINATOR_UUID_SIZE;
1189 break;
1190 case PROC_PIDORIGINATOR_BGSTATE:
1191 size = PROC_PIDORIGINATOR_BGSTATE_SIZE;
1192 break;
1193 default:
1194 return(EINVAL);
1195 }
1196
1197 if (buffersize < size)
1198 return(ENOMEM);
1199
1200 if (pid != 0 && pid != proc_selfpid())
1201 return (EINVAL);
1202
1203 switch (flavor) {
1204 case PROC_PIDORIGINATOR_UUID: {
1205 uuid_t uuid;
1206
1207 error = proc_pidoriginatoruuid(uuid, sizeof(uuid));
1208 if (error != 0)
1209 goto out;
1210
1211 error = copyout(uuid, buffer, size);
1212 if (error == 0)
1213 *retval = size;
1214 }
1215 break;
1216
1217 case PROC_PIDORIGINATOR_BGSTATE: {
1218 uint32_t is_backgrounded;
1219 error = proc_get_originatorbgstate(&is_backgrounded);
1220 if (error)
1221 goto out;
1222
1223 error = copyout(&is_backgrounded, buffer, size);
1224 if (error == 0)
1225 *retval = size;
1226 }
1227 break;
1228
1229 default:
1230 error = ENOTSUP;
1231 }
1232out:
1233 return error;
1234}
1235
0c530ab8
A
1236/********************************** proc_pidinfo ********************************/
1237
1238
1239int
b0d623f7 1240proc_pidinfo(int pid, int flavor, uint64_t arg, user_addr_t buffer, uint32_t buffersize, int32_t * retval)
0c530ab8
A
1241{
1242 struct proc * p = PROC_NULL;
1243 int error = ENOTSUP;
1244 int gotref = 0;
1245 int findzomb = 0;
39236c6e 1246 int shortversion = 0;
0c530ab8 1247 uint32_t size;
b0d623f7 1248 int zombie = 0;
316670eb 1249 int thuniqueid = 0;
39236c6e
A
1250 int uniqidversion = 0;
1251 boolean_t check_same_user;
0c530ab8
A
1252
1253 switch (flavor) {
1254 case PROC_PIDLISTFDS:
1255 size = PROC_PIDLISTFD_SIZE;
1256 if (buffer == (user_addr_t)0)
1257 size = 0;
1258 break;
1259 case PROC_PIDTBSDINFO:
1260 size = PROC_PIDTBSDINFO_SIZE;
1261 break;
1262 case PROC_PIDTASKINFO:
1263 size = PROC_PIDTASKINFO_SIZE;
1264 break;
1265 case PROC_PIDTASKALLINFO:
1266 size = PROC_PIDTASKALLINFO_SIZE;
1267 break;
1268 case PROC_PIDTHREADINFO:
1269 size = PROC_PIDTHREADINFO_SIZE;
1270 break;
1271 case PROC_PIDLISTTHREADS:
1272 size = PROC_PIDLISTTHREADS_SIZE;
1273 break;
1274 case PROC_PIDREGIONINFO:
1275 size = PROC_PIDREGIONINFO_SIZE;
1276 break;
1277 case PROC_PIDREGIONPATHINFO:
1278 size = PROC_PIDREGIONPATHINFO_SIZE;
1279 break;
1280 case PROC_PIDVNODEPATHINFO:
1281 size = PROC_PIDVNODEPATHINFO_SIZE;
1282 break;
2d21ac55
A
1283 case PROC_PIDTHREADPATHINFO:
1284 size = PROC_PIDTHREADPATHINFO_SIZE;
1285 break;
1286 case PROC_PIDPATHINFO:
1287 size = MAXPATHLEN;
1288 break;
b0d623f7
A
1289 case PROC_PIDWORKQUEUEINFO:
1290 /* kernel does not have workq info */
1291 if (pid == 0)
1292 return(EINVAL);
1293 else
1294 size = PROC_PIDWORKQUEUEINFO_SIZE;
1295 break;
6d2010ae
A
1296 case PROC_PIDT_SHORTBSDINFO:
1297 size = PROC_PIDT_SHORTBSDINFO_SIZE;
1298 break;
1299 case PROC_PIDLISTFILEPORTS:
1300 size = PROC_PIDLISTFILEPORTS_SIZE;
1301 if (buffer == (user_addr_t)0)
1302 size = 0;
1303 break;
316670eb
A
1304 case PROC_PIDTHREADID64INFO:
1305 size = PROC_PIDTHREADID64INFO_SIZE;
1306 break;
39236c6e
A
1307 case PROC_PIDUNIQIDENTIFIERINFO:
1308 size = PROC_PIDUNIQIDENTIFIERINFO_SIZE;
1309 break;
1310 case PROC_PIDT_BSDINFOWITHUNIQID:
1311 size = PROC_PIDT_BSDINFOWITHUNIQID_SIZE;
1312 break;
fe8ab488
A
1313 case PROC_PIDARCHINFO:
1314 size = PROC_PIDARCHINFO_SIZE;
1315 break;
1316 case PROC_PIDCOALITIONINFO:
1317 size = PROC_PIDCOALITIONINFO_SIZE;
1318 break;
1319 case PROC_PIDNOTEEXIT:
1320 /*
1321 * Set findzomb explicitly because arg passed
1322 * in is used as note exit status bits.
1323 */
1324 size = PROC_PIDNOTEEXIT_SIZE;
1325 findzomb = 1;
1326 break;
1327 case PROC_PIDREGIONPATHINFO2:
1328 size = PROC_PIDREGIONPATHINFO2_SIZE;
1329 break;
1330 case PROC_PIDREGIONPATHINFO3:
1331 size = PROC_PIDREGIONPATHINFO3_SIZE;
1332 break;
0c530ab8
A
1333 default:
1334 return(EINVAL);
1335 }
1336
1337 if (buffersize < size)
1338 return(ENOMEM);
1339
2d21ac55
A
1340 if ((flavor == PROC_PIDPATHINFO) && (buffersize > PROC_PIDPATHINFO_MAXSIZE)) {
1341 return(EOVERFLOW);
1342 }
1343
39236c6e
A
1344 /* Check if we need to look for zombies */
1345 if ((flavor == PROC_PIDTBSDINFO) || (flavor == PROC_PIDT_SHORTBSDINFO) || (flavor == PROC_PIDT_BSDINFOWITHUNIQID)
fe8ab488 1346 || (flavor == PROC_PIDUNIQIDENTIFIERINFO)) {
39236c6e
A
1347 if (arg)
1348 findzomb = 1;
1349 }
0c530ab8 1350
39236c6e
A
1351 if ((p = proc_find(pid)) == PROC_NULL) {
1352 if (findzomb)
1353 p = proc_find_zombref(pid);
1354 if (p == PROC_NULL) {
1355 error = ESRCH;
1356 goto out;
1357 }
1358 zombie = 1;
1359 } else {
1360 gotref = 1;
0c530ab8 1361 }
39236c6e
A
1362
1363 /* Certain operations don't require privileges */
1364 switch (flavor) {
1365 case PROC_PIDT_SHORTBSDINFO:
1366 case PROC_PIDUNIQIDENTIFIERINFO:
1367 case PROC_PIDPATHINFO:
1368 check_same_user = NO_CHECK_SAME_USER;
1369 break;
1370 default:
1371 check_same_user = CHECK_SAME_USER;
1372 break;
1373 }
1374
1375 /* Do we have permission to look into this? */
1376 if ((error = proc_security_policy(p, PROC_INFO_CALL_PIDINFO, flavor, check_same_user)))
1377 goto out;
1378
0c530ab8
A
1379 switch (flavor) {
1380 case PROC_PIDLISTFDS: {
1381 error = proc_pidfdlist(p, buffer, buffersize, retval);
1382 }
1383 break;
1384
39236c6e
A
1385 case PROC_PIDUNIQIDENTIFIERINFO: {
1386 struct proc_uniqidentifierinfo p_uniqidinfo;
1387
1388 proc_piduniqidentifierinfo(p, &p_uniqidinfo);
1389 error = copyout(&p_uniqidinfo, buffer, sizeof(struct proc_uniqidentifierinfo));
1390 if (error == 0)
1391 *retval = sizeof(struct proc_uniqidentifierinfo);
1392 }
1393 break;
1394
6d2010ae
A
1395 case PROC_PIDT_SHORTBSDINFO:
1396 shortversion = 1;
39236c6e 1397 case PROC_PIDT_BSDINFOWITHUNIQID:
0c530ab8
A
1398 case PROC_PIDTBSDINFO: {
1399 struct proc_bsdinfo pbsd;
6d2010ae 1400 struct proc_bsdshortinfo pbsd_short;
39236c6e
A
1401 struct proc_bsdinfowithuniqid pbsd_uniqid;
1402
1403 if (flavor == PROC_PIDT_BSDINFOWITHUNIQID)
1404 uniqidversion = 1;
1405
6d2010ae
A
1406 if (shortversion != 0) {
1407 error = proc_pidshortbsdinfo(p, &pbsd_short, zombie);
1408 } else {
1409 error = proc_pidbsdinfo(p, &pbsd, zombie);
39236c6e
A
1410 if (uniqidversion != 0) {
1411 proc_piduniqidentifierinfo(p, &pbsd_uniqid.p_uniqidentifier);
1412 pbsd_uniqid.pbsd = pbsd;
1413 }
6d2010ae 1414 }
39236c6e 1415
0c530ab8 1416 if (error == 0) {
6d2010ae
A
1417 if (shortversion != 0) {
1418 error = copyout(&pbsd_short, buffer, sizeof(struct proc_bsdshortinfo));
1419 if (error == 0)
1420 *retval = sizeof(struct proc_bsdshortinfo);
39236c6e
A
1421 } else if (uniqidversion != 0) {
1422 error = copyout(&pbsd_uniqid, buffer, sizeof(struct proc_bsdinfowithuniqid));
1423 if (error == 0)
1424 *retval = sizeof(struct proc_bsdinfowithuniqid);
1425 } else {
6d2010ae
A
1426 error = copyout(&pbsd, buffer, sizeof(struct proc_bsdinfo));
1427 if (error == 0)
1428 *retval = sizeof(struct proc_bsdinfo);
1429 }
0c530ab8
A
1430 }
1431 }
1432 break;
1433
1434 case PROC_PIDTASKINFO: {
1435 struct proc_taskinfo ptinfo;
1436
1437 error = proc_pidtaskinfo(p, &ptinfo);
1438 if (error == 0) {
1439 error = copyout(&ptinfo, buffer, sizeof(struct proc_taskinfo));
1440 if (error == 0)
1441 *retval = sizeof(struct proc_taskinfo);
1442 }
1443 }
1444 break;
1445
1446 case PROC_PIDTASKALLINFO: {
1447 struct proc_taskallinfo pall;
1448
b0d623f7 1449 error = proc_pidbsdinfo(p, &pall.pbsd, 0);
0c530ab8
A
1450 error = proc_pidtaskinfo(p, &pall.ptinfo);
1451 if (error == 0) {
1452 error = copyout(&pall, buffer, sizeof(struct proc_taskallinfo));
1453 if (error == 0)
1454 *retval = sizeof(struct proc_taskallinfo);
1455 }
1456 }
1457 break;
1458
316670eb
A
1459 case PROC_PIDTHREADID64INFO:
1460 thuniqueid = 1;
0c530ab8
A
1461 case PROC_PIDTHREADINFO:{
1462 struct proc_threadinfo pthinfo;
1463
316670eb 1464 error = proc_pidthreadinfo(p, arg, thuniqueid, &pthinfo);
0c530ab8
A
1465 if (error == 0) {
1466 error = copyout(&pthinfo, buffer, sizeof(struct proc_threadinfo));
1467 if (error == 0)
1468 *retval = sizeof(struct proc_threadinfo);
1469 }
1470 }
1471 break;
1472
1473 case PROC_PIDLISTTHREADS:{
1474 error = proc_pidlistthreads(p, buffer, buffersize, retval);
1475 }
1476 break;
1477
1478 case PROC_PIDREGIONINFO:{
1479 error = proc_pidregioninfo(p, arg, buffer, buffersize, retval);
1480 }
1481 break;
1482
1483
1484 case PROC_PIDREGIONPATHINFO:{
1485 error = proc_pidregionpathinfo(p, arg, buffer, buffersize, retval);
1486 }
1487 break;
1488
fe8ab488
A
1489 case PROC_PIDREGIONPATHINFO2:{
1490 error = proc_pidregionpathinfo2(p, arg, buffer, buffersize, retval);
1491 }
1492 break;
1493
1494 case PROC_PIDREGIONPATHINFO3:{
1495 error = proc_pidregionpathinfo3(p, arg, buffer, buffersize, retval);
1496 }
1497 break;
1498
0c530ab8
A
1499 case PROC_PIDVNODEPATHINFO:{
1500 error = proc_pidvnodepathinfo(p, arg, buffer, buffersize, retval);
1501 }
1502 break;
1503
2d21ac55
A
1504
1505 case PROC_PIDTHREADPATHINFO:{
1506 struct proc_threadwithpathinfo pinfo;
1507
1508 error = proc_pidthreadpathinfo(p, arg, &pinfo);
1509 if (error == 0) {
1510 error = copyout((caddr_t)&pinfo, buffer, sizeof(struct proc_threadwithpathinfo));
1511 if (error == 0)
1512 *retval = sizeof(struct proc_threadwithpathinfo);
1513 }
1514 }
1515 break;
1516
1517 case PROC_PIDPATHINFO: {
2d21ac55
A
1518 error = proc_pidpathinfo(p, arg, buffer, buffersize, retval);
1519 }
1520 break;
1521
b0d623f7
A
1522
1523 case PROC_PIDWORKQUEUEINFO:{
1524 struct proc_workqueueinfo pwqinfo;
1525
1526 error = proc_pidworkqueueinfo(p, &pwqinfo);
1527 if (error == 0) {
1528 error = copyout(&pwqinfo, buffer, sizeof(struct proc_workqueueinfo));
1529 if (error == 0)
1530 *retval = sizeof(struct proc_workqueueinfo);
1531 }
1532 }
1533 break;
1534
6d2010ae
A
1535 case PROC_PIDLISTFILEPORTS: {
1536 error = proc_pidfileportlist(p, buffer, buffersize,
1537 retval);
1538 }
1539 break;
1540
fe8ab488
A
1541 case PROC_PIDARCHINFO: {
1542 struct proc_archinfo pai;
1543 proc_archinfo(p, &pai);
1544 error = copyout(&pai, buffer, sizeof(struct proc_archinfo));
1545 if (error == 0) {
1546 *retval = sizeof(struct proc_archinfo);
1547 }
1548 }
1549
1550 case PROC_PIDCOALITIONINFO: {
1551 struct proc_pidcoalitioninfo pci;
1552 proc_pidcoalitioninfo(p, &pci);
1553 error = copyout(&pci, buffer, sizeof(struct proc_pidcoalitioninfo));
1554 if (error == 0) {
1555 *retval = sizeof(struct proc_pidcoalitioninfo);
1556 }
1557 }
1558 break;
1559
1560 case PROC_PIDNOTEEXIT: {
1561 uint32_t data;
1562 error = proc_pidnoteexit(p, arg, &data);
1563 if (error == 0) {
1564 error = copyout(&data, buffer, sizeof(data));
1565 if (error == 0) {
1566 *retval = sizeof(data);
1567 }
1568 }
1569 }
1570 break;
1571
0c530ab8
A
1572 default:
1573 error = ENOTSUP;
1574 }
1575
1576out:
1577 if (gotref)
2d21ac55 1578 proc_rele(p);
39236c6e
A
1579 else if (zombie)
1580 proc_drop_zombref(p);
0c530ab8
A
1581 return(error);
1582}
1583
1584
1585int
b0d623f7 1586pid_vnodeinfo(vnode_t vp, uint32_t vid, struct fileproc * fp, int closeonexec, user_addr_t buffer, __unused uint32_t buffersize, int32_t * retval)
0c530ab8
A
1587{
1588 struct vnode_fdinfo vfi;
1589 int error= 0;
1590
1591 if ((error = vnode_getwithvid(vp, vid)) != 0) {
1592 return(error);
1593 }
1594 bzero(&vfi, sizeof(struct vnode_fdinfo));
2d21ac55 1595 fill_fileinfo(fp, closeonexec, &vfi.pfi);
0c530ab8
A
1596 error = fill_vnodeinfo(vp, &vfi.pvi);
1597 vnode_put(vp);
1598 if (error == 0) {
1599 error = copyout((caddr_t)&vfi, buffer, sizeof(struct vnode_fdinfo));
1600 if (error == 0)
1601 *retval = sizeof(struct vnode_fdinfo);
1602 }
1603 return(error);
1604}
1605
1606int
b0d623f7 1607pid_vnodeinfopath(vnode_t vp, uint32_t vid, struct fileproc * fp, int closeonexec, user_addr_t buffer, __unused uint32_t buffersize, int32_t * retval)
0c530ab8
A
1608{
1609 struct vnode_fdinfowithpath vfip;
1610 int count, error= 0;
1611
1612 if ((error = vnode_getwithvid(vp, vid)) != 0) {
1613 return(error);
1614 }
1615 bzero(&vfip, sizeof(struct vnode_fdinfowithpath));
2d21ac55 1616 fill_fileinfo(fp, closeonexec, &vfip.pfi);
0c530ab8
A
1617 error = fill_vnodeinfo(vp, &vfip.pvip.vip_vi) ;
1618 if (error == 0) {
1619 count = MAXPATHLEN;
1620 vn_getpath(vp, &vfip.pvip.vip_path[0], &count);
1621 vfip.pvip.vip_path[MAXPATHLEN-1] = 0;
1622 vnode_put(vp);
1623 error = copyout((caddr_t)&vfip, buffer, sizeof(struct vnode_fdinfowithpath));
1624 if (error == 0)
1625 *retval = sizeof(struct vnode_fdinfowithpath);
1626 } else
1627 vnode_put(vp);
1628 return(error);
1629}
1630
1631void
2d21ac55 1632fill_fileinfo(struct fileproc * fp, int closeonexec, struct proc_fileinfo * fproc)
0c530ab8 1633{
39236c6e
A
1634 fproc->fi_openflags = fp->f_fglob->fg_flag;
1635 fproc->fi_status = 0;
1636 fproc->fi_offset = fp->f_fglob->fg_offset;
1637 fproc->fi_type = FILEGLOB_DTYPE(fp->f_fglob);
1638 if (fp->f_fglob->fg_count > 1)
1639 fproc->fi_status |= PROC_FP_SHARED;
1640 if (closeonexec != 0)
1641 fproc->fi_status |= PROC_FP_CLEXEC;
1642
1643 if (FILEPROC_TYPE(fp) == FTYPE_GUARDED) {
1644 fproc->fi_status |= PROC_FP_GUARDED;
1645 fproc->fi_guardflags = 0;
1646 if (fp_isguarded(fp, GUARD_CLOSE))
1647 fproc->fi_guardflags |= PROC_FI_GUARD_CLOSE;
1648 if (fp_isguarded(fp, GUARD_DUP))
1649 fproc->fi_guardflags |= PROC_FI_GUARD_DUP;
1650 if (fp_isguarded(fp, GUARD_SOCKET_IPC))
1651 fproc->fi_guardflags |= PROC_FI_GUARD_SOCKET_IPC;
1652 if (fp_isguarded(fp, GUARD_FILEPORT))
1653 fproc->fi_guardflags |= PROC_FI_GUARD_FILEPORT;
1654 }
0c530ab8
A
1655}
1656
1657
1658
1659int
1660fill_vnodeinfo(vnode_t vp, struct vnode_info *vinfo)
1661{
1662 vfs_context_t context;
2d21ac55 1663 struct stat64 sb;
0c530ab8
A
1664 int error = 0;
1665
04b8595b 1666 bzero(&sb, sizeof(struct stat64));
0c530ab8 1667 context = vfs_context_create((vfs_context_t)0);
2d21ac55 1668 error = vn_stat(vp, &sb, NULL, 1, context);
0c530ab8
A
1669 (void)vfs_context_rele(context);
1670
2d21ac55
A
1671 munge_vinfo_stat(&sb, &vinfo->vi_stat);
1672
0c530ab8
A
1673 if (error != 0)
1674 goto out;
1675
1676 if (vp->v_mount != dead_mountp) {
1677 vinfo->vi_fsid = vp->v_mount->mnt_vfsstat.f_fsid;
1678 } else {
1679 vinfo->vi_fsid.val[0] = 0;
1680 vinfo->vi_fsid.val[1] = 0;
1681 }
1682 vinfo->vi_type = vp->v_type;
1683out:
1684 return(error);
1685}
1686
1687int
b0d623f7 1688pid_socketinfo(socket_t so, struct fileproc *fp, int closeonexec, user_addr_t buffer, __unused uint32_t buffersize, int32_t * retval)
0c530ab8 1689{
2d21ac55 1690#if SOCKETS
0c530ab8
A
1691 struct socket_fdinfo s;
1692 int error = 0;
1693
1694 bzero(&s, sizeof(struct socket_fdinfo));
2d21ac55 1695 fill_fileinfo(fp, closeonexec, &s.pfi);
0c530ab8
A
1696 if ((error = fill_socketinfo(so, &s.psi)) == 0) {
1697 if ((error = copyout(&s, buffer, sizeof(struct socket_fdinfo))) == 0)
1698 *retval = sizeof(struct socket_fdinfo);
1699 }
0c530ab8 1700 return (error);
2d21ac55 1701#else
39236c6e 1702#pragma unused(so, fp, closeonexec, buffer)
2d21ac55
A
1703 *retval = 0;
1704 return (ENOTSUP);
1705#endif
0c530ab8
A
1706}
1707
1708int
b0d623f7 1709pid_pseminfo(struct psemnode *psem, struct fileproc *fp, int closeonexec, user_addr_t buffer, __unused uint32_t buffersize, int32_t * retval)
0c530ab8
A
1710{
1711 struct psem_fdinfo pseminfo;
1712 int error = 0;
1713
1714 bzero(&pseminfo, sizeof(struct psem_fdinfo));
2d21ac55 1715 fill_fileinfo(fp, closeonexec, &pseminfo.pfi);
0c530ab8
A
1716
1717 if ((error = fill_pseminfo(psem, &pseminfo.pseminfo)) == 0) {
1718 if ((error = copyout(&pseminfo, buffer, sizeof(struct psem_fdinfo))) == 0)
1719 *retval = sizeof(struct psem_fdinfo);
1720 }
1721
1722 return(error);
1723}
1724
1725int
b0d623f7 1726pid_pshminfo(struct pshmnode *pshm, struct fileproc *fp, int closeonexec, user_addr_t buffer, __unused uint32_t buffersize, int32_t * retval)
0c530ab8
A
1727{
1728 struct pshm_fdinfo pshminfo;
1729 int error = 0;
1730
1731 bzero(&pshminfo, sizeof(struct pshm_fdinfo));
2d21ac55 1732 fill_fileinfo(fp, closeonexec, &pshminfo.pfi);
0c530ab8
A
1733
1734 if ((error = fill_pshminfo(pshm, &pshminfo.pshminfo)) == 0) {
1735 if ((error = copyout(&pshminfo, buffer, sizeof(struct pshm_fdinfo))) == 0)
1736 *retval = sizeof(struct pshm_fdinfo);
1737 }
1738
1739 return(error);
1740}
1741
1742int
b0d623f7 1743pid_pipeinfo(struct pipe * p, struct fileproc *fp, int closeonexec, user_addr_t buffer, __unused uint32_t buffersize, int32_t * retval)
0c530ab8
A
1744{
1745 struct pipe_fdinfo pipeinfo;
1746 int error = 0;
1747
1748 bzero(&pipeinfo, sizeof(struct pipe_fdinfo));
2d21ac55 1749 fill_fileinfo(fp, closeonexec, &pipeinfo.pfi);
0c530ab8
A
1750 if ((error = fill_pipeinfo(p, &pipeinfo.pipeinfo)) == 0) {
1751 if ((error = copyout(&pipeinfo, buffer, sizeof(struct pipe_fdinfo))) == 0)
1752 *retval = sizeof(struct pipe_fdinfo);
1753 }
1754
1755 return(error);
1756}
1757
1758int
b0d623f7 1759pid_kqueueinfo(struct kqueue * kq, struct fileproc *fp, int closeonexec, user_addr_t buffer, __unused uint32_t buffersize, int32_t * retval)
0c530ab8
A
1760{
1761 struct kqueue_fdinfo kqinfo;
1762 int error = 0;
1763
1764 bzero(&kqinfo, sizeof(struct kqueue_fdinfo));
1765
2d21ac55 1766 fill_fileinfo(fp, closeonexec, &kqinfo.pfi);
0c530ab8
A
1767
1768 if ((error = fill_kqueueinfo(kq, &kqinfo.kqueueinfo)) == 0) {
1769 if ((error = copyout(&kqinfo, buffer, sizeof(struct kqueue_fdinfo))) == 0)
1770 *retval = sizeof(struct kqueue_fdinfo);
1771 }
1772
1773 return(error);
1774}
1775
1776int
b0d623f7 1777pid_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)
0c530ab8
A
1778{
1779 return ENOTSUP;
1780}
1781
1782
1783
1784/************************** proc_pidfdinfo routine ***************************/
1785int
b0d623f7 1786proc_pidfdinfo(int pid, int flavor, int fd, user_addr_t buffer, uint32_t buffersize, int32_t * retval)
0c530ab8
A
1787{
1788 proc_t p;
1789 int error = ENOTSUP;
1790 struct fileproc * fp;
1791 uint32_t size;
2d21ac55 1792 int closeonexec = 0;
0c530ab8
A
1793
1794 switch (flavor) {
1795 case PROC_PIDFDVNODEINFO:
1796 size = PROC_PIDFDVNODEINFO_SIZE;
1797 break;
1798 case PROC_PIDFDVNODEPATHINFO:
1799 size = PROC_PIDFDVNODEPATHINFO_SIZE;
1800 break;
1801 case PROC_PIDFDSOCKETINFO:
1802 size = PROC_PIDFDSOCKETINFO_SIZE;
1803 break;
1804 case PROC_PIDFDPSEMINFO:
1805 size = PROC_PIDFDPSEMINFO_SIZE;
1806 break;
1807 case PROC_PIDFDPSHMINFO:
1808 size = PROC_PIDFDPSHMINFO_SIZE;
1809 break;
1810 case PROC_PIDFDPIPEINFO:
1811 size = PROC_PIDFDPIPEINFO_SIZE;
1812 break;
1813 case PROC_PIDFDKQUEUEINFO:
1814 size = PROC_PIDFDKQUEUEINFO_SIZE;
1815 break;
1816 case PROC_PIDFDATALKINFO:
1817 size = PROC_PIDFDATALKINFO_SIZE;
1818 break;
1819
1820 default:
1821 return(EINVAL);
1822
1823 }
1824
1825 if (buffersize < size)
1826 return(ENOMEM);
1827
2d21ac55 1828 if ((p = proc_find(pid)) == PROC_NULL) {
0c530ab8
A
1829 error = ESRCH;
1830 goto out;
1831 }
39236c6e
A
1832
1833 /* Do we have permission to look into this? */
1834 if ((error = proc_security_policy(p, PROC_INFO_CALL_PIDFDINFO, flavor, CHECK_SAME_USER)))
0c530ab8 1835 goto out1;
0c530ab8
A
1836
1837 switch (flavor) {
1838 case PROC_PIDFDVNODEINFO: {
1839 vnode_t vp;
1840 uint32_t vid=0;
1841
1842 if ((error = fp_getfvpandvid(p, fd, &fp, &vp, &vid)) !=0) {
1843 goto out1;
1844 }
2d21ac55
A
1845 /* no need to be under the fdlock */
1846 closeonexec = p->p_fd->fd_ofileflags[fd] & UF_EXCLOSE;
1847 error = pid_vnodeinfo(vp, vid, fp, closeonexec, buffer, buffersize, retval);
0c530ab8
A
1848 }
1849 break;
1850
1851 case PROC_PIDFDVNODEPATHINFO: {
1852 vnode_t vp;
1853 uint32_t vid=0;
1854
1855 if ((error = fp_getfvpandvid(p, fd, &fp, &vp, &vid)) !=0) {
1856 goto out1;
1857 }
1858
2d21ac55
A
1859 /* no need to be under the fdlock */
1860 closeonexec = p->p_fd->fd_ofileflags[fd] & UF_EXCLOSE;
1861 error = pid_vnodeinfopath(vp, vid, fp, closeonexec, buffer, buffersize, retval);
0c530ab8
A
1862 }
1863 break;
1864
1865 case PROC_PIDFDSOCKETINFO: {
1866 socket_t so;
1867
1868 if ((error = fp_getfsock(p, fd, &fp, &so)) !=0) {
1869 goto out1;
1870 }
2d21ac55
A
1871 /* no need to be under the fdlock */
1872 closeonexec = p->p_fd->fd_ofileflags[fd] & UF_EXCLOSE;
1873 error = pid_socketinfo(so, fp, closeonexec, buffer, buffersize, retval);
0c530ab8
A
1874 }
1875 break;
1876
1877 case PROC_PIDFDPSEMINFO: {
1878 struct psemnode * psem;
1879
1880 if ((error = fp_getfpsem(p, fd, &fp, &psem)) !=0) {
1881 goto out1;
1882 }
2d21ac55
A
1883 /* no need to be under the fdlock */
1884 closeonexec = p->p_fd->fd_ofileflags[fd] & UF_EXCLOSE;
1885 error = pid_pseminfo(psem, fp, closeonexec, buffer, buffersize, retval);
0c530ab8
A
1886 }
1887 break;
1888
1889 case PROC_PIDFDPSHMINFO: {
1890 struct pshmnode * pshm;
1891
1892 if ((error = fp_getfpshm(p, fd, &fp, &pshm)) !=0) {
1893 goto out1;
1894 }
2d21ac55
A
1895 /* no need to be under the fdlock */
1896 closeonexec = p->p_fd->fd_ofileflags[fd] & UF_EXCLOSE;
1897 error = pid_pshminfo(pshm, fp, closeonexec, buffer, buffersize, retval);
0c530ab8
A
1898 }
1899 break;
1900
1901 case PROC_PIDFDPIPEINFO: {
1902 struct pipe * cpipe;
1903
1904 if ((error = fp_getfpipe(p, fd, &fp, &cpipe)) !=0) {
1905 goto out1;
1906 }
2d21ac55
A
1907 /* no need to be under the fdlock */
1908 closeonexec = p->p_fd->fd_ofileflags[fd] & UF_EXCLOSE;
1909 error = pid_pipeinfo(cpipe, fp, closeonexec, buffer, buffersize, retval);
0c530ab8
A
1910 }
1911 break;
1912
1913 case PROC_PIDFDKQUEUEINFO: {
1914 struct kqueue * kq;
1915
1916 if ((error = fp_getfkq(p, fd, &fp, &kq)) !=0) {
1917 goto out1;
1918 }
2d21ac55
A
1919 /* no need to be under the fdlock */
1920 closeonexec = p->p_fd->fd_ofileflags[fd] & UF_EXCLOSE;
1921 error = pid_kqueueinfo(kq, fp, closeonexec, buffer, buffersize, retval);
0c530ab8
A
1922 }
1923 break;
1924
0c530ab8
A
1925 default: {
1926 error = EINVAL;
6d2010ae 1927 goto out1;
0c530ab8 1928 }
0c530ab8
A
1929 }
1930
1931 fp_drop(p, fd, fp , 0);
1932out1 :
2d21ac55 1933 proc_rele(p);
0c530ab8
A
1934out:
1935 return(error);
1936}
1937
6d2010ae
A
1938/*
1939 * Helper function for proc_pidfileportinfo
1940 */
1941
1942struct fileport_info_args {
1943 int fia_flavor;
1944 user_addr_t fia_buffer;
1945 uint32_t fia_buffersize;
1946 int32_t *fia_retval;
1947};
1948
1949static kern_return_t
1950proc_fileport_info(__unused mach_port_name_t name,
1951 struct fileglob *fg, void *arg)
1952{
1953 struct fileport_info_args *fia = arg;
1954 struct fileproc __fileproc, *fp = &__fileproc;
1955 int error;
1956
1957 bzero(fp, sizeof (*fp));
1958 fp->f_fglob = fg;
1959
1960 switch (fia->fia_flavor) {
1961 case PROC_PIDFILEPORTVNODEPATHINFO: {
1962 vnode_t vp;
1963
39236c6e 1964 if (FILEGLOB_DTYPE(fg) != DTYPE_VNODE) {
6d2010ae
A
1965 error = ENOTSUP;
1966 break;
1967 }
1968 vp = (struct vnode *)fg->fg_data;
1969 error = pid_vnodeinfopath(vp, vnode_vid(vp), fp, 0,
1970 fia->fia_buffer, fia->fia_buffersize, fia->fia_retval);
1971 } break;
1972
1973 case PROC_PIDFILEPORTSOCKETINFO: {
1974 socket_t so;
1975
39236c6e 1976 if (FILEGLOB_DTYPE(fg) != DTYPE_SOCKET) {
6d2010ae
A
1977 error = EOPNOTSUPP;
1978 break;
1979 }
1980 so = (socket_t)fg->fg_data;
1981 error = pid_socketinfo(so, fp, 0,
1982 fia->fia_buffer, fia->fia_buffersize, fia->fia_retval);
1983 } break;
1984
1985 case PROC_PIDFILEPORTPSHMINFO: {
1986 struct pshmnode *pshm;
1987
39236c6e 1988 if (FILEGLOB_DTYPE(fg) != DTYPE_PSXSHM) {
6d2010ae
A
1989 error = EBADF; /* ick - mirror fp_getfpshm */
1990 break;
1991 }
1992 pshm = (struct pshmnode *)fg->fg_data;
1993 error = pid_pshminfo(pshm, fp, 0,
1994 fia->fia_buffer, fia->fia_buffersize, fia->fia_retval);
1995 } break;
1996
1997 case PROC_PIDFILEPORTPIPEINFO: {
1998 struct pipe *cpipe;
1999
39236c6e 2000 if (FILEGLOB_DTYPE(fg) != DTYPE_PIPE) {
6d2010ae
A
2001 error = EBADF; /* ick - mirror fp_getfpipe */
2002 break;
2003 }
2004 cpipe = (struct pipe *)fg->fg_data;
2005 error = pid_pipeinfo(cpipe, fp, 0,
2006 fia->fia_buffer, fia->fia_buffersize, fia->fia_retval);
2007 } break;
2008
2009 default:
2010 error = EINVAL;
2011 break;
2012 }
2013
2014 return (error);
2015}
2016
2017/************************* proc_pidfileportinfo routine *********************/
2018int
2019proc_pidfileportinfo(int pid, int flavor, mach_port_name_t name,
2020 user_addr_t buffer, uint32_t buffersize, int32_t *retval)
2021{
2022 proc_t p;
2023 int error = ENOTSUP;
2024 uint32_t size;
2025 struct fileport_info_args fia;
2026
2027 /* fileport types are restricted by filetype_issendable() */
2028
2029 switch (flavor) {
2030 case PROC_PIDFILEPORTVNODEPATHINFO:
2031 size = PROC_PIDFILEPORTVNODEPATHINFO_SIZE;
2032 break;
2033 case PROC_PIDFILEPORTSOCKETINFO:
2034 size = PROC_PIDFILEPORTSOCKETINFO_SIZE;
2035 break;
2036 case PROC_PIDFILEPORTPSHMINFO:
2037 size = PROC_PIDFILEPORTPSHMINFO_SIZE;
2038 break;
2039 case PROC_PIDFILEPORTPIPEINFO:
2040 size = PROC_PIDFILEPORTPIPEINFO_SIZE;
2041 break;
2042 default:
2043 return (EINVAL);
2044 }
2045
2046 if (buffersize < size)
2047 return (ENOMEM);
2048 if ((p = proc_find(pid)) == PROC_NULL) {
2049 error = ESRCH;
2050 goto out;
2051 }
39236c6e
A
2052
2053 /* Do we have permission to look into this? */
2054 if ((error = proc_security_policy(p, PROC_INFO_CALL_PIDFILEPORTINFO, flavor, CHECK_SAME_USER)))
6d2010ae 2055 goto out1;
6d2010ae
A
2056
2057 fia.fia_flavor = flavor;
2058 fia.fia_buffer = buffer;
2059 fia.fia_buffersize = buffersize;
2060 fia.fia_retval = retval;
2061
2062 if (fileport_invoke(p->task, name,
2063 proc_fileport_info, &fia, &error) != KERN_SUCCESS)
2064 error = EINVAL;
2065out1:
2066 proc_rele(p);
2067out:
2068 return (error);
2069}
0c530ab8 2070
39236c6e
A
2071int
2072proc_security_policy(proc_t targetp, __unused int callnum, __unused int flavor, boolean_t check_same_user)
0c530ab8 2073{
39236c6e
A
2074#if CONFIG_MACF
2075 int error = 0;
2d21ac55 2076
39236c6e
A
2077 if ((error = mac_proc_check_proc_info(current_proc(), targetp, callnum, flavor)))
2078 return (error);
2079#endif
2080
2081 /* The 'listpids' call doesn't have a target proc */
2082 if (targetp == PROC_NULL) {
2083 assert(callnum == PROC_INFO_CALL_LISTPIDS && check_same_user == NO_CHECK_SAME_USER);
2084 return (0);
2085 }
2086
2087 /*
2088 * Check for 'get information for processes owned by other users' privilege
2089 * root has this privilege by default
2090 */
2091 if (priv_check_cred(kauth_cred_get(), PRIV_GLOBAL_PROC_INFO, 0) == 0)
2092 check_same_user = FALSE;
2093
2094 if (check_same_user) {
2095 kauth_cred_t target_cred;
2096 uid_t target_uid;
2097
2098 target_cred = kauth_cred_proc_ref(targetp);
2099 target_uid = kauth_cred_getuid(target_cred);
2100 kauth_cred_unref(&target_cred);
2101
2102 if (kauth_getuid() != target_uid)
0c530ab8 2103 return(EPERM);
39236c6e 2104 }
0c530ab8
A
2105
2106 return(0);
2107}
2108
0c530ab8 2109int
b0d623f7 2110proc_kernmsgbuf(user_addr_t buffer, uint32_t buffersize, int32_t * retval)
0c530ab8 2111{
0c530ab8 2112 if (suser(kauth_cred_get(), (u_short *)0) == 0) {
2d21ac55 2113 return(log_dmesg(buffer, buffersize, retval));
0c530ab8
A
2114 } else
2115 return(EPERM);
2116}
2117
b0d623f7
A
2118/* ********* process control sets on self only */
2119int
6d2010ae 2120proc_setcontrol(int pid, int flavor, uint64_t arg, user_addr_t buffer, uint32_t buffersize, __unused int32_t * retval)
b0d623f7
A
2121{
2122 struct proc * pself = PROC_NULL;
2123 int error = 0;
2124 uint32_t pcontrol = (uint32_t)arg;
6d2010ae 2125 struct uthread *ut = NULL;
b0d623f7
A
2126
2127
2128 pself = current_proc();
2129 if (pid != pself->p_pid)
2130 return(EINVAL);
2131
39236c6e
A
2132 /* Do we have permission to look into this? */
2133 if ((error = proc_security_policy(pself, PROC_INFO_CALL_SETCONTROL, flavor, NO_CHECK_SAME_USER)))
2134 goto out;
b0d623f7
A
2135
2136 switch (flavor) {
2137 case PROC_SELFSET_PCONTROL: {
6d2010ae
A
2138 if (pcontrol > P_PCMAX)
2139 return(EINVAL);
b0d623f7
A
2140 proc_lock(pself);
2141 /* reset existing control setting while retaining action state */
2142 pself->p_pcaction &= PROC_ACTION_MASK;
2143 /* set new control state */
2144 pself->p_pcaction |= pcontrol;
2145 proc_unlock(pself);
2146 }
2147 break;
2148
6d2010ae
A
2149 case PROC_SELFSET_THREADNAME: {
2150 /* PROC_SELFSET_THREADNAME_SIZE = (MAXTHREADNAMESIZE -1) */
2151 if(buffersize > PROC_SELFSET_THREADNAME_SIZE)
2152 return ENAMETOOLONG;
2153 ut = current_uthread();
2154
2155 if(!ut->pth_name)
2156 {
2157 ut->pth_name = (char*)kalloc(MAXTHREADNAMESIZE );
2158 if(!ut->pth_name)
2159 return ENOMEM;
2160 }
2161 bzero(ut->pth_name, MAXTHREADNAMESIZE);
2162 error = copyin(buffer, ut->pth_name, buffersize);
2163 }
2164 break;
2165
2166 case PROC_SELFSET_VMRSRCOWNER: {
2167 /* need to to be superuser */
2168 if (suser(kauth_cred_get(), (u_short *)0) != 0) {
2169 error = EPERM;
2170 goto out;
2171 }
2172
2173 proc_lock(pself);
2174 /* reset existing control setting while retaining action state */
2175 pself->p_lflag |= P_LVMRSRCOWNER;
2176 proc_unlock(pself);
2177 }
2178 break;
2179
316670eb
A
2180 case PROC_SELFSET_DELAYIDLESLEEP: {
2181 /* mark or clear the process property to delay idle sleep disk IO */
2182 if (pcontrol != 0)
2183 OSBitOrAtomic(P_DELAYIDLESLEEP, &pself->p_flag);
2184 else
2185 OSBitAndAtomic(~((uint32_t)P_DELAYIDLESLEEP), &pself->p_flag);
2186 }
2187 break;
2188
b0d623f7
A
2189 default:
2190 error = ENOTSUP;
2191 }
2192
6d2010ae 2193out:
b0d623f7
A
2194 return(error);
2195}
2196
39236c6e 2197#if CONFIG_MEMORYSTATUS
316670eb
A
2198
2199int
2200proc_dirtycontrol(int pid, int flavor, uint64_t arg, int32_t *retval) {
2201 struct proc *target_p;
2202 int error = 0;
2203 uint32_t pcontrol = (uint32_t)arg;
2204 kauth_cred_t my_cred, target_cred;
2205 boolean_t self = FALSE;
2206 boolean_t child = FALSE;
39236c6e 2207 boolean_t zombref = FALSE;
316670eb
A
2208 pid_t selfpid;
2209
2210 target_p = proc_find(pid);
39236c6e 2211
316670eb 2212 if (target_p == PROC_NULL) {
39236c6e
A
2213 if (flavor == PROC_DIRTYCONTROL_GET) {
2214 target_p = proc_find_zombref(pid);
2215 zombref = 1;
2216 }
2217
2218 if (target_p == PROC_NULL)
2219 return(ESRCH);
2220
316670eb 2221 }
39236c6e 2222
316670eb
A
2223 my_cred = kauth_cred_get();
2224 target_cred = kauth_cred_proc_ref(target_p);
39236c6e
A
2225
2226 /* Do we have permission to look into this? */
2227 if ((error = proc_security_policy(target_p, PROC_INFO_CALL_DIRTYCONTROL, flavor, NO_CHECK_SAME_USER)))
2228 goto out;
2229
316670eb
A
2230 selfpid = proc_selfpid();
2231 if (pid == selfpid) {
2232 self = TRUE;
2233 } else if (target_p->p_ppid == selfpid) {
2234 child = TRUE;
2235 }
2236
2237 switch (flavor) {
2238 case PROC_DIRTYCONTROL_TRACK: {
2239 /* Only allow the process itself, its parent, or root */
2240 if ((self == FALSE) && (child == FALSE) && kauth_cred_issuser(kauth_cred_get()) != TRUE) {
2241 error = EPERM;
2242 goto out;
2243 }
316670eb 2244
39236c6e 2245 error = memorystatus_dirty_track(target_p, pcontrol);
316670eb
A
2246 }
2247 break;
2248
39236c6e 2249 case PROC_DIRTYCONTROL_SET: {
316670eb
A
2250 /* Check privileges; use cansignal() here since the process could be terminated */
2251 if (!cansignal(current_proc(), my_cred, target_p, SIGKILL, 0)) {
2252 error = EPERM;
2253 goto out;
2254 }
2255
39236c6e 2256 error = memorystatus_dirty_set(target_p, self, pcontrol);
316670eb
A
2257 }
2258 break;
2259
2260 case PROC_DIRTYCONTROL_GET: {
2261 /* No permissions check - dirty state is freely available */
2262 if (retval) {
39236c6e 2263 *retval = memorystatus_dirty_get(target_p);
316670eb
A
2264 } else {
2265 error = EINVAL;
2266 }
2267 }
2268 break;
fe8ab488
A
2269
2270 case PROC_DIRTYCONTROL_CLEAR: {
2271 /* Check privileges; use cansignal() here since the process could be terminated */
2272 if (!cansignal(current_proc(), my_cred, target_p, SIGKILL, 0)) {
2273 error = EPERM;
2274 goto out;
2275 }
2276
2277 error = memorystatus_dirty_clear(target_p, pcontrol);
2278 }
2279 break;
316670eb
A
2280 }
2281
2282out:
39236c6e
A
2283 if (zombref)
2284 proc_drop_zombref(target_p);
2285 else
2286 proc_rele(target_p);
2287
2288 kauth_cred_unref(&target_cred);
316670eb
A
2289
2290 return(error);
2291}
39236c6e
A
2292#else
2293
2294int
2295proc_dirtycontrol(__unused int pid, __unused int flavor, __unused uint64_t arg, __unused int32_t *retval) {
2296 return ENOTSUP;
2297}
2298
2299#endif /* CONFIG_MEMORYSTATUS */
316670eb
A
2300
2301/*
2302 * proc_terminate() provides support for sudden termination.
2303 * SIGKILL is issued to tracked, clean processes; otherwise,
2304 * SIGTERM is sent.
2305 */
2306
2307int
2308proc_terminate(int pid, int32_t *retval)
2309{
2310 int error = 0;
2311 proc_t p;
2312 kauth_cred_t uc = kauth_cred_get();
2313 int sig;
2314
2315#if 0
2316 /* XXX: Check if these are necessary */
2317 AUDIT_ARG(pid, pid);
2318 AUDIT_ARG(signum, sig);
2319#endif
2320
2321 if (pid <= 0 || retval == NULL) {
2322 return (EINVAL);
2323 }
2324
2325 if ((p = proc_find(pid)) == NULL) {
2326 return (ESRCH);
2327 }
2328
2329#if 0
2330 /* XXX: Check if these are necessary */
2331 AUDIT_ARG(process, p);
2332#endif
2333
2334 /* Check privileges; if SIGKILL can be issued, then SIGTERM is also OK */
2335 if (!cansignal(current_proc(), uc, p, SIGKILL, 0)) {
2336 error = EPERM;
2337 goto out;
2338 }
39236c6e
A
2339
2340 /* Not allowed to sudden terminate yourself */
2341 if (p == current_proc()) {
2342 error = EPERM;
2343 goto out;
316670eb
A
2344 }
2345
39236c6e
A
2346#if CONFIG_MEMORYSTATUS
2347 /* Determine requisite signal to issue */
2348 sig = memorystatus_on_terminate(p);
2349#else
2350 sig = SIGTERM;
2351#endif
316670eb 2352
39236c6e
A
2353 proc_set_task_policy(p->task, THREAD_NULL, TASK_POLICY_ATTRIBUTE,
2354 TASK_POLICY_TERMINATED, TASK_POLICY_ENABLE);
316670eb
A
2355
2356 psignal(p, sig);
2357 *retval = sig;
2358
2359out:
2360 proc_rele(p);
2361
2362 return error;
2363}
2364
2d21ac55
A
2365/*
2366 * copy stat64 structure into vinfo_stat structure.
2367 */
2368static void
2369munge_vinfo_stat(struct stat64 *sbp, struct vinfo_stat *vsbp)
2370{
2371 bzero(vsbp, sizeof(struct vinfo_stat));
2372
2373 vsbp->vst_dev = sbp->st_dev;
2374 vsbp->vst_mode = sbp->st_mode;
2375 vsbp->vst_nlink = sbp->st_nlink;
2376 vsbp->vst_ino = sbp->st_ino;
2377 vsbp->vst_uid = sbp->st_uid;
2378 vsbp->vst_gid = sbp->st_gid;
2379 vsbp->vst_atime = sbp->st_atimespec.tv_sec;
2380 vsbp->vst_atimensec = sbp->st_atimespec.tv_nsec;
2381 vsbp->vst_mtime = sbp->st_mtimespec.tv_sec;
2382 vsbp->vst_mtimensec = sbp->st_mtimespec.tv_nsec;
2383 vsbp->vst_ctime = sbp->st_ctimespec.tv_sec;
2384 vsbp->vst_ctimensec = sbp->st_ctimespec.tv_nsec;
2385 vsbp->vst_birthtime = sbp->st_birthtimespec.tv_sec;
2386 vsbp->vst_birthtimensec = sbp->st_birthtimespec.tv_nsec;
2387 vsbp->vst_size = sbp->st_size;
2388 vsbp->vst_blocks = sbp->st_blocks;
2389 vsbp->vst_blksize = sbp->st_blksize;
2390 vsbp->vst_flags = sbp->st_flags;
2391 vsbp->vst_gen = sbp->st_gen;
2392 vsbp->vst_rdev = sbp->st_rdev;
2393 vsbp->vst_qspare[0] = sbp->st_qspare[0];
2394 vsbp->vst_qspare[1] = sbp->st_qspare[1];
2395}
39236c6e
A
2396
2397int
2398proc_pid_rusage(int pid, int flavor, user_addr_t buffer, __unused int32_t *retval)
2399{
2400 proc_t p;
2401 int error;
2402 int zombie = 0;
2403
2404 if ((p = proc_find(pid)) == PROC_NULL) {
2405 if ((p = proc_find_zombref(pid)) == PROC_NULL) {
2406 return (ESRCH);
2407 }
2408 zombie = 1;
2409 }
2410
2411 /* Do we have permission to look into this? */
2412 if ((error = proc_security_policy(p, PROC_INFO_CALL_PIDRUSAGE, flavor, CHECK_SAME_USER)))
2413 goto out;
2414
2415 error = proc_get_rusage(p, flavor, buffer, zombie);
2416
2417out:
2418 if (zombie)
2419 proc_drop_zombref(p);
2420 else
2421 proc_rele(p);
2422
2423 return (error);
2424}
2425
fe8ab488
A
2426void
2427proc_archinfo(proc_t p, struct proc_archinfo *pai)
2428{
2429 proc_lock(p);
2430 pai->p_cputype = p->p_cputype;
2431 pai->p_cpusubtype = p->p_cpusubtype;
2432 proc_unlock(p);
2433}
2434
2435void
2436proc_pidcoalitioninfo(proc_t p, struct proc_pidcoalitioninfo *ppci)
2437{
2438 bzero(ppci, sizeof(*ppci));
2439 ppci->coalition_id = proc_coalitionid(p);
2440}
2441
2442
2443
2444/*
2445 * Wrapper to provide NOTE_EXIT_DETAIL and NOTE_EXITSTATUS
2446 * It mimics the data that is typically captured by the
2447 * EVFILT_PROC, NOTE_EXIT event mechanism.
2448 * See filt_proc() in kern_event.c.
2449 */
2450int
2451proc_pidnoteexit(proc_t p, uint64_t flags, uint32_t *data)
2452{
2453 uint32_t exit_data = 0;
2454 uint32_t exit_flags = (uint32_t)flags;
2455
2456 proc_lock(p);
2457
2458 /*
2459 * Allow access to the parent of the exiting
2460 * child or the parent debugger only.
2461 */
2462 do {
2463 pid_t selfpid = proc_selfpid();
2464
2465 if (p->p_ppid == selfpid)
2466 break; /* parent => ok */
2467
2468 if ((p->p_lflag & P_LTRACED) != 0 &&
2469 (p->p_oppid == selfpid))
2470 break; /* parent-in-waiting => ok */
2471
2472 proc_unlock(p);
2473 return (EACCES);
2474 } while (0);
2475
2476 if ((exit_flags & NOTE_EXITSTATUS) != 0) {
2477 /* The signal and exit status */
2478 exit_data |= (p->p_xstat & NOTE_PDATAMASK);
2479 }
2480
2481 if ((exit_flags & NOTE_EXIT_DETAIL) != 0) {
2482 /* The exit detail */
2483 if ((p->p_lflag & P_LTERM_DECRYPTFAIL) != 0) {
2484 exit_data |= NOTE_EXIT_DECRYPTFAIL;
2485 }
2486
2487 if ((p->p_lflag & P_LTERM_JETSAM) != 0) {
2488 exit_data |= NOTE_EXIT_MEMORY;
2489
2490 switch (p->p_lflag & P_JETSAM_MASK) {
2491 case P_JETSAM_VMPAGESHORTAGE:
2492 exit_data |= NOTE_EXIT_MEMORY_VMPAGESHORTAGE;
2493 break;
2494 case P_JETSAM_VMTHRASHING:
2495 exit_data |= NOTE_EXIT_MEMORY_VMTHRASHING;
2496 break;
2497 case P_JETSAM_FCTHRASHING:
2498 exit_data |= NOTE_EXIT_MEMORY_FCTHRASHING;
2499 break;
2500 case P_JETSAM_VNODE:
2501 exit_data |= NOTE_EXIT_MEMORY_VNODE;
2502 break;
2503 case P_JETSAM_HIWAT:
2504 exit_data |= NOTE_EXIT_MEMORY_HIWAT;
2505 break;
2506 case P_JETSAM_PID:
2507 exit_data |= NOTE_EXIT_MEMORY_PID;
2508 break;
2509 case P_JETSAM_IDLEEXIT:
2510 exit_data |= NOTE_EXIT_MEMORY_IDLE;
2511 break;
2512 }
2513 }
2514
2515 if ((p->p_csflags & CS_KILLED) != 0) {
2516 exit_data |= NOTE_EXIT_CSERROR;
2517 }
2518 }
2519
2520 proc_unlock(p);
2521
2522 *data = exit_data;
2523
2524 return (0);
2525}
2526