]> git.saurik.com Git - apple/xnu.git/blame - bsd/kern/proc_info.c
xnu-2782.1.97.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
0c530ab8 1666 context = vfs_context_create((vfs_context_t)0);
2d21ac55 1667 error = vn_stat(vp, &sb, NULL, 1, context);
0c530ab8
A
1668 (void)vfs_context_rele(context);
1669
2d21ac55
A
1670 munge_vinfo_stat(&sb, &vinfo->vi_stat);
1671
0c530ab8
A
1672 if (error != 0)
1673 goto out;
1674
1675 if (vp->v_mount != dead_mountp) {
1676 vinfo->vi_fsid = vp->v_mount->mnt_vfsstat.f_fsid;
1677 } else {
1678 vinfo->vi_fsid.val[0] = 0;
1679 vinfo->vi_fsid.val[1] = 0;
1680 }
1681 vinfo->vi_type = vp->v_type;
1682out:
1683 return(error);
1684}
1685
1686int
b0d623f7 1687pid_socketinfo(socket_t so, struct fileproc *fp, int closeonexec, user_addr_t buffer, __unused uint32_t buffersize, int32_t * retval)
0c530ab8 1688{
2d21ac55 1689#if SOCKETS
0c530ab8
A
1690 struct socket_fdinfo s;
1691 int error = 0;
1692
1693 bzero(&s, sizeof(struct socket_fdinfo));
2d21ac55 1694 fill_fileinfo(fp, closeonexec, &s.pfi);
0c530ab8
A
1695 if ((error = fill_socketinfo(so, &s.psi)) == 0) {
1696 if ((error = copyout(&s, buffer, sizeof(struct socket_fdinfo))) == 0)
1697 *retval = sizeof(struct socket_fdinfo);
1698 }
0c530ab8 1699 return (error);
2d21ac55 1700#else
39236c6e 1701#pragma unused(so, fp, closeonexec, buffer)
2d21ac55
A
1702 *retval = 0;
1703 return (ENOTSUP);
1704#endif
0c530ab8
A
1705}
1706
1707int
b0d623f7 1708pid_pseminfo(struct psemnode *psem, struct fileproc *fp, int closeonexec, user_addr_t buffer, __unused uint32_t buffersize, int32_t * retval)
0c530ab8
A
1709{
1710 struct psem_fdinfo pseminfo;
1711 int error = 0;
1712
1713 bzero(&pseminfo, sizeof(struct psem_fdinfo));
2d21ac55 1714 fill_fileinfo(fp, closeonexec, &pseminfo.pfi);
0c530ab8
A
1715
1716 if ((error = fill_pseminfo(psem, &pseminfo.pseminfo)) == 0) {
1717 if ((error = copyout(&pseminfo, buffer, sizeof(struct psem_fdinfo))) == 0)
1718 *retval = sizeof(struct psem_fdinfo);
1719 }
1720
1721 return(error);
1722}
1723
1724int
b0d623f7 1725pid_pshminfo(struct pshmnode *pshm, struct fileproc *fp, int closeonexec, user_addr_t buffer, __unused uint32_t buffersize, int32_t * retval)
0c530ab8
A
1726{
1727 struct pshm_fdinfo pshminfo;
1728 int error = 0;
1729
1730 bzero(&pshminfo, sizeof(struct pshm_fdinfo));
2d21ac55 1731 fill_fileinfo(fp, closeonexec, &pshminfo.pfi);
0c530ab8
A
1732
1733 if ((error = fill_pshminfo(pshm, &pshminfo.pshminfo)) == 0) {
1734 if ((error = copyout(&pshminfo, buffer, sizeof(struct pshm_fdinfo))) == 0)
1735 *retval = sizeof(struct pshm_fdinfo);
1736 }
1737
1738 return(error);
1739}
1740
1741int
b0d623f7 1742pid_pipeinfo(struct pipe * p, struct fileproc *fp, int closeonexec, user_addr_t buffer, __unused uint32_t buffersize, int32_t * retval)
0c530ab8
A
1743{
1744 struct pipe_fdinfo pipeinfo;
1745 int error = 0;
1746
1747 bzero(&pipeinfo, sizeof(struct pipe_fdinfo));
2d21ac55 1748 fill_fileinfo(fp, closeonexec, &pipeinfo.pfi);
0c530ab8
A
1749 if ((error = fill_pipeinfo(p, &pipeinfo.pipeinfo)) == 0) {
1750 if ((error = copyout(&pipeinfo, buffer, sizeof(struct pipe_fdinfo))) == 0)
1751 *retval = sizeof(struct pipe_fdinfo);
1752 }
1753
1754 return(error);
1755}
1756
1757int
b0d623f7 1758pid_kqueueinfo(struct kqueue * kq, struct fileproc *fp, int closeonexec, user_addr_t buffer, __unused uint32_t buffersize, int32_t * retval)
0c530ab8
A
1759{
1760 struct kqueue_fdinfo kqinfo;
1761 int error = 0;
1762
1763 bzero(&kqinfo, sizeof(struct kqueue_fdinfo));
1764
2d21ac55 1765 fill_fileinfo(fp, closeonexec, &kqinfo.pfi);
0c530ab8
A
1766
1767 if ((error = fill_kqueueinfo(kq, &kqinfo.kqueueinfo)) == 0) {
1768 if ((error = copyout(&kqinfo, buffer, sizeof(struct kqueue_fdinfo))) == 0)
1769 *retval = sizeof(struct kqueue_fdinfo);
1770 }
1771
1772 return(error);
1773}
1774
1775int
b0d623f7 1776pid_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
1777{
1778 return ENOTSUP;
1779}
1780
1781
1782
1783/************************** proc_pidfdinfo routine ***************************/
1784int
b0d623f7 1785proc_pidfdinfo(int pid, int flavor, int fd, user_addr_t buffer, uint32_t buffersize, int32_t * retval)
0c530ab8
A
1786{
1787 proc_t p;
1788 int error = ENOTSUP;
1789 struct fileproc * fp;
1790 uint32_t size;
2d21ac55 1791 int closeonexec = 0;
0c530ab8
A
1792
1793 switch (flavor) {
1794 case PROC_PIDFDVNODEINFO:
1795 size = PROC_PIDFDVNODEINFO_SIZE;
1796 break;
1797 case PROC_PIDFDVNODEPATHINFO:
1798 size = PROC_PIDFDVNODEPATHINFO_SIZE;
1799 break;
1800 case PROC_PIDFDSOCKETINFO:
1801 size = PROC_PIDFDSOCKETINFO_SIZE;
1802 break;
1803 case PROC_PIDFDPSEMINFO:
1804 size = PROC_PIDFDPSEMINFO_SIZE;
1805 break;
1806 case PROC_PIDFDPSHMINFO:
1807 size = PROC_PIDFDPSHMINFO_SIZE;
1808 break;
1809 case PROC_PIDFDPIPEINFO:
1810 size = PROC_PIDFDPIPEINFO_SIZE;
1811 break;
1812 case PROC_PIDFDKQUEUEINFO:
1813 size = PROC_PIDFDKQUEUEINFO_SIZE;
1814 break;
1815 case PROC_PIDFDATALKINFO:
1816 size = PROC_PIDFDATALKINFO_SIZE;
1817 break;
1818
1819 default:
1820 return(EINVAL);
1821
1822 }
1823
1824 if (buffersize < size)
1825 return(ENOMEM);
1826
2d21ac55 1827 if ((p = proc_find(pid)) == PROC_NULL) {
0c530ab8
A
1828 error = ESRCH;
1829 goto out;
1830 }
39236c6e
A
1831
1832 /* Do we have permission to look into this? */
1833 if ((error = proc_security_policy(p, PROC_INFO_CALL_PIDFDINFO, flavor, CHECK_SAME_USER)))
0c530ab8 1834 goto out1;
0c530ab8
A
1835
1836 switch (flavor) {
1837 case PROC_PIDFDVNODEINFO: {
1838 vnode_t vp;
1839 uint32_t vid=0;
1840
1841 if ((error = fp_getfvpandvid(p, fd, &fp, &vp, &vid)) !=0) {
1842 goto out1;
1843 }
2d21ac55
A
1844 /* no need to be under the fdlock */
1845 closeonexec = p->p_fd->fd_ofileflags[fd] & UF_EXCLOSE;
1846 error = pid_vnodeinfo(vp, vid, fp, closeonexec, buffer, buffersize, retval);
0c530ab8
A
1847 }
1848 break;
1849
1850 case PROC_PIDFDVNODEPATHINFO: {
1851 vnode_t vp;
1852 uint32_t vid=0;
1853
1854 if ((error = fp_getfvpandvid(p, fd, &fp, &vp, &vid)) !=0) {
1855 goto out1;
1856 }
1857
2d21ac55
A
1858 /* no need to be under the fdlock */
1859 closeonexec = p->p_fd->fd_ofileflags[fd] & UF_EXCLOSE;
1860 error = pid_vnodeinfopath(vp, vid, fp, closeonexec, buffer, buffersize, retval);
0c530ab8
A
1861 }
1862 break;
1863
1864 case PROC_PIDFDSOCKETINFO: {
1865 socket_t so;
1866
1867 if ((error = fp_getfsock(p, fd, &fp, &so)) !=0) {
1868 goto out1;
1869 }
2d21ac55
A
1870 /* no need to be under the fdlock */
1871 closeonexec = p->p_fd->fd_ofileflags[fd] & UF_EXCLOSE;
1872 error = pid_socketinfo(so, fp, closeonexec, buffer, buffersize, retval);
0c530ab8
A
1873 }
1874 break;
1875
1876 case PROC_PIDFDPSEMINFO: {
1877 struct psemnode * psem;
1878
1879 if ((error = fp_getfpsem(p, fd, &fp, &psem)) !=0) {
1880 goto out1;
1881 }
2d21ac55
A
1882 /* no need to be under the fdlock */
1883 closeonexec = p->p_fd->fd_ofileflags[fd] & UF_EXCLOSE;
1884 error = pid_pseminfo(psem, fp, closeonexec, buffer, buffersize, retval);
0c530ab8
A
1885 }
1886 break;
1887
1888 case PROC_PIDFDPSHMINFO: {
1889 struct pshmnode * pshm;
1890
1891 if ((error = fp_getfpshm(p, fd, &fp, &pshm)) !=0) {
1892 goto out1;
1893 }
2d21ac55
A
1894 /* no need to be under the fdlock */
1895 closeonexec = p->p_fd->fd_ofileflags[fd] & UF_EXCLOSE;
1896 error = pid_pshminfo(pshm, fp, closeonexec, buffer, buffersize, retval);
0c530ab8
A
1897 }
1898 break;
1899
1900 case PROC_PIDFDPIPEINFO: {
1901 struct pipe * cpipe;
1902
1903 if ((error = fp_getfpipe(p, fd, &fp, &cpipe)) !=0) {
1904 goto out1;
1905 }
2d21ac55
A
1906 /* no need to be under the fdlock */
1907 closeonexec = p->p_fd->fd_ofileflags[fd] & UF_EXCLOSE;
1908 error = pid_pipeinfo(cpipe, fp, closeonexec, buffer, buffersize, retval);
0c530ab8
A
1909 }
1910 break;
1911
1912 case PROC_PIDFDKQUEUEINFO: {
1913 struct kqueue * kq;
1914
1915 if ((error = fp_getfkq(p, fd, &fp, &kq)) !=0) {
1916 goto out1;
1917 }
2d21ac55
A
1918 /* no need to be under the fdlock */
1919 closeonexec = p->p_fd->fd_ofileflags[fd] & UF_EXCLOSE;
1920 error = pid_kqueueinfo(kq, fp, closeonexec, buffer, buffersize, retval);
0c530ab8
A
1921 }
1922 break;
1923
0c530ab8
A
1924 default: {
1925 error = EINVAL;
6d2010ae 1926 goto out1;
0c530ab8 1927 }
0c530ab8
A
1928 }
1929
1930 fp_drop(p, fd, fp , 0);
1931out1 :
2d21ac55 1932 proc_rele(p);
0c530ab8
A
1933out:
1934 return(error);
1935}
1936
6d2010ae
A
1937/*
1938 * Helper function for proc_pidfileportinfo
1939 */
1940
1941struct fileport_info_args {
1942 int fia_flavor;
1943 user_addr_t fia_buffer;
1944 uint32_t fia_buffersize;
1945 int32_t *fia_retval;
1946};
1947
1948static kern_return_t
1949proc_fileport_info(__unused mach_port_name_t name,
1950 struct fileglob *fg, void *arg)
1951{
1952 struct fileport_info_args *fia = arg;
1953 struct fileproc __fileproc, *fp = &__fileproc;
1954 int error;
1955
1956 bzero(fp, sizeof (*fp));
1957 fp->f_fglob = fg;
1958
1959 switch (fia->fia_flavor) {
1960 case PROC_PIDFILEPORTVNODEPATHINFO: {
1961 vnode_t vp;
1962
39236c6e 1963 if (FILEGLOB_DTYPE(fg) != DTYPE_VNODE) {
6d2010ae
A
1964 error = ENOTSUP;
1965 break;
1966 }
1967 vp = (struct vnode *)fg->fg_data;
1968 error = pid_vnodeinfopath(vp, vnode_vid(vp), fp, 0,
1969 fia->fia_buffer, fia->fia_buffersize, fia->fia_retval);
1970 } break;
1971
1972 case PROC_PIDFILEPORTSOCKETINFO: {
1973 socket_t so;
1974
39236c6e 1975 if (FILEGLOB_DTYPE(fg) != DTYPE_SOCKET) {
6d2010ae
A
1976 error = EOPNOTSUPP;
1977 break;
1978 }
1979 so = (socket_t)fg->fg_data;
1980 error = pid_socketinfo(so, fp, 0,
1981 fia->fia_buffer, fia->fia_buffersize, fia->fia_retval);
1982 } break;
1983
1984 case PROC_PIDFILEPORTPSHMINFO: {
1985 struct pshmnode *pshm;
1986
39236c6e 1987 if (FILEGLOB_DTYPE(fg) != DTYPE_PSXSHM) {
6d2010ae
A
1988 error = EBADF; /* ick - mirror fp_getfpshm */
1989 break;
1990 }
1991 pshm = (struct pshmnode *)fg->fg_data;
1992 error = pid_pshminfo(pshm, fp, 0,
1993 fia->fia_buffer, fia->fia_buffersize, fia->fia_retval);
1994 } break;
1995
1996 case PROC_PIDFILEPORTPIPEINFO: {
1997 struct pipe *cpipe;
1998
39236c6e 1999 if (FILEGLOB_DTYPE(fg) != DTYPE_PIPE) {
6d2010ae
A
2000 error = EBADF; /* ick - mirror fp_getfpipe */
2001 break;
2002 }
2003 cpipe = (struct pipe *)fg->fg_data;
2004 error = pid_pipeinfo(cpipe, fp, 0,
2005 fia->fia_buffer, fia->fia_buffersize, fia->fia_retval);
2006 } break;
2007
2008 default:
2009 error = EINVAL;
2010 break;
2011 }
2012
2013 return (error);
2014}
2015
2016/************************* proc_pidfileportinfo routine *********************/
2017int
2018proc_pidfileportinfo(int pid, int flavor, mach_port_name_t name,
2019 user_addr_t buffer, uint32_t buffersize, int32_t *retval)
2020{
2021 proc_t p;
2022 int error = ENOTSUP;
2023 uint32_t size;
2024 struct fileport_info_args fia;
2025
2026 /* fileport types are restricted by filetype_issendable() */
2027
2028 switch (flavor) {
2029 case PROC_PIDFILEPORTVNODEPATHINFO:
2030 size = PROC_PIDFILEPORTVNODEPATHINFO_SIZE;
2031 break;
2032 case PROC_PIDFILEPORTSOCKETINFO:
2033 size = PROC_PIDFILEPORTSOCKETINFO_SIZE;
2034 break;
2035 case PROC_PIDFILEPORTPSHMINFO:
2036 size = PROC_PIDFILEPORTPSHMINFO_SIZE;
2037 break;
2038 case PROC_PIDFILEPORTPIPEINFO:
2039 size = PROC_PIDFILEPORTPIPEINFO_SIZE;
2040 break;
2041 default:
2042 return (EINVAL);
2043 }
2044
2045 if (buffersize < size)
2046 return (ENOMEM);
2047 if ((p = proc_find(pid)) == PROC_NULL) {
2048 error = ESRCH;
2049 goto out;
2050 }
39236c6e
A
2051
2052 /* Do we have permission to look into this? */
2053 if ((error = proc_security_policy(p, PROC_INFO_CALL_PIDFILEPORTINFO, flavor, CHECK_SAME_USER)))
6d2010ae 2054 goto out1;
6d2010ae
A
2055
2056 fia.fia_flavor = flavor;
2057 fia.fia_buffer = buffer;
2058 fia.fia_buffersize = buffersize;
2059 fia.fia_retval = retval;
2060
2061 if (fileport_invoke(p->task, name,
2062 proc_fileport_info, &fia, &error) != KERN_SUCCESS)
2063 error = EINVAL;
2064out1:
2065 proc_rele(p);
2066out:
2067 return (error);
2068}
0c530ab8 2069
39236c6e
A
2070int
2071proc_security_policy(proc_t targetp, __unused int callnum, __unused int flavor, boolean_t check_same_user)
0c530ab8 2072{
39236c6e
A
2073#if CONFIG_MACF
2074 int error = 0;
2d21ac55 2075
39236c6e
A
2076 if ((error = mac_proc_check_proc_info(current_proc(), targetp, callnum, flavor)))
2077 return (error);
2078#endif
2079
2080 /* The 'listpids' call doesn't have a target proc */
2081 if (targetp == PROC_NULL) {
2082 assert(callnum == PROC_INFO_CALL_LISTPIDS && check_same_user == NO_CHECK_SAME_USER);
2083 return (0);
2084 }
2085
2086 /*
2087 * Check for 'get information for processes owned by other users' privilege
2088 * root has this privilege by default
2089 */
2090 if (priv_check_cred(kauth_cred_get(), PRIV_GLOBAL_PROC_INFO, 0) == 0)
2091 check_same_user = FALSE;
2092
2093 if (check_same_user) {
2094 kauth_cred_t target_cred;
2095 uid_t target_uid;
2096
2097 target_cred = kauth_cred_proc_ref(targetp);
2098 target_uid = kauth_cred_getuid(target_cred);
2099 kauth_cred_unref(&target_cred);
2100
2101 if (kauth_getuid() != target_uid)
0c530ab8 2102 return(EPERM);
39236c6e 2103 }
0c530ab8
A
2104
2105 return(0);
2106}
2107
0c530ab8 2108int
b0d623f7 2109proc_kernmsgbuf(user_addr_t buffer, uint32_t buffersize, int32_t * retval)
0c530ab8 2110{
0c530ab8 2111 if (suser(kauth_cred_get(), (u_short *)0) == 0) {
2d21ac55 2112 return(log_dmesg(buffer, buffersize, retval));
0c530ab8
A
2113 } else
2114 return(EPERM);
2115}
2116
b0d623f7
A
2117/* ********* process control sets on self only */
2118int
6d2010ae 2119proc_setcontrol(int pid, int flavor, uint64_t arg, user_addr_t buffer, uint32_t buffersize, __unused int32_t * retval)
b0d623f7
A
2120{
2121 struct proc * pself = PROC_NULL;
2122 int error = 0;
2123 uint32_t pcontrol = (uint32_t)arg;
6d2010ae 2124 struct uthread *ut = NULL;
b0d623f7
A
2125
2126
2127 pself = current_proc();
2128 if (pid != pself->p_pid)
2129 return(EINVAL);
2130
39236c6e
A
2131 /* Do we have permission to look into this? */
2132 if ((error = proc_security_policy(pself, PROC_INFO_CALL_SETCONTROL, flavor, NO_CHECK_SAME_USER)))
2133 goto out;
b0d623f7
A
2134
2135 switch (flavor) {
2136 case PROC_SELFSET_PCONTROL: {
6d2010ae
A
2137 if (pcontrol > P_PCMAX)
2138 return(EINVAL);
b0d623f7
A
2139 proc_lock(pself);
2140 /* reset existing control setting while retaining action state */
2141 pself->p_pcaction &= PROC_ACTION_MASK;
2142 /* set new control state */
2143 pself->p_pcaction |= pcontrol;
2144 proc_unlock(pself);
2145 }
2146 break;
2147
6d2010ae
A
2148 case PROC_SELFSET_THREADNAME: {
2149 /* PROC_SELFSET_THREADNAME_SIZE = (MAXTHREADNAMESIZE -1) */
2150 if(buffersize > PROC_SELFSET_THREADNAME_SIZE)
2151 return ENAMETOOLONG;
2152 ut = current_uthread();
2153
2154 if(!ut->pth_name)
2155 {
2156 ut->pth_name = (char*)kalloc(MAXTHREADNAMESIZE );
2157 if(!ut->pth_name)
2158 return ENOMEM;
2159 }
2160 bzero(ut->pth_name, MAXTHREADNAMESIZE);
2161 error = copyin(buffer, ut->pth_name, buffersize);
2162 }
2163 break;
2164
2165 case PROC_SELFSET_VMRSRCOWNER: {
2166 /* need to to be superuser */
2167 if (suser(kauth_cred_get(), (u_short *)0) != 0) {
2168 error = EPERM;
2169 goto out;
2170 }
2171
2172 proc_lock(pself);
2173 /* reset existing control setting while retaining action state */
2174 pself->p_lflag |= P_LVMRSRCOWNER;
2175 proc_unlock(pself);
2176 }
2177 break;
2178
316670eb
A
2179 case PROC_SELFSET_DELAYIDLESLEEP: {
2180 /* mark or clear the process property to delay idle sleep disk IO */
2181 if (pcontrol != 0)
2182 OSBitOrAtomic(P_DELAYIDLESLEEP, &pself->p_flag);
2183 else
2184 OSBitAndAtomic(~((uint32_t)P_DELAYIDLESLEEP), &pself->p_flag);
2185 }
2186 break;
2187
b0d623f7
A
2188 default:
2189 error = ENOTSUP;
2190 }
2191
6d2010ae 2192out:
b0d623f7
A
2193 return(error);
2194}
2195
39236c6e 2196#if CONFIG_MEMORYSTATUS
316670eb
A
2197
2198int
2199proc_dirtycontrol(int pid, int flavor, uint64_t arg, int32_t *retval) {
2200 struct proc *target_p;
2201 int error = 0;
2202 uint32_t pcontrol = (uint32_t)arg;
2203 kauth_cred_t my_cred, target_cred;
2204 boolean_t self = FALSE;
2205 boolean_t child = FALSE;
39236c6e 2206 boolean_t zombref = FALSE;
316670eb
A
2207 pid_t selfpid;
2208
2209 target_p = proc_find(pid);
39236c6e 2210
316670eb 2211 if (target_p == PROC_NULL) {
39236c6e
A
2212 if (flavor == PROC_DIRTYCONTROL_GET) {
2213 target_p = proc_find_zombref(pid);
2214 zombref = 1;
2215 }
2216
2217 if (target_p == PROC_NULL)
2218 return(ESRCH);
2219
316670eb 2220 }
39236c6e 2221
316670eb
A
2222 my_cred = kauth_cred_get();
2223 target_cred = kauth_cred_proc_ref(target_p);
39236c6e
A
2224
2225 /* Do we have permission to look into this? */
2226 if ((error = proc_security_policy(target_p, PROC_INFO_CALL_DIRTYCONTROL, flavor, NO_CHECK_SAME_USER)))
2227 goto out;
2228
316670eb
A
2229 selfpid = proc_selfpid();
2230 if (pid == selfpid) {
2231 self = TRUE;
2232 } else if (target_p->p_ppid == selfpid) {
2233 child = TRUE;
2234 }
2235
2236 switch (flavor) {
2237 case PROC_DIRTYCONTROL_TRACK: {
2238 /* Only allow the process itself, its parent, or root */
2239 if ((self == FALSE) && (child == FALSE) && kauth_cred_issuser(kauth_cred_get()) != TRUE) {
2240 error = EPERM;
2241 goto out;
2242 }
316670eb 2243
39236c6e 2244 error = memorystatus_dirty_track(target_p, pcontrol);
316670eb
A
2245 }
2246 break;
2247
39236c6e 2248 case PROC_DIRTYCONTROL_SET: {
316670eb
A
2249 /* Check privileges; use cansignal() here since the process could be terminated */
2250 if (!cansignal(current_proc(), my_cred, target_p, SIGKILL, 0)) {
2251 error = EPERM;
2252 goto out;
2253 }
2254
39236c6e 2255 error = memorystatus_dirty_set(target_p, self, pcontrol);
316670eb
A
2256 }
2257 break;
2258
2259 case PROC_DIRTYCONTROL_GET: {
2260 /* No permissions check - dirty state is freely available */
2261 if (retval) {
39236c6e 2262 *retval = memorystatus_dirty_get(target_p);
316670eb
A
2263 } else {
2264 error = EINVAL;
2265 }
2266 }
2267 break;
fe8ab488
A
2268
2269 case PROC_DIRTYCONTROL_CLEAR: {
2270 /* Check privileges; use cansignal() here since the process could be terminated */
2271 if (!cansignal(current_proc(), my_cred, target_p, SIGKILL, 0)) {
2272 error = EPERM;
2273 goto out;
2274 }
2275
2276 error = memorystatus_dirty_clear(target_p, pcontrol);
2277 }
2278 break;
316670eb
A
2279 }
2280
2281out:
39236c6e
A
2282 if (zombref)
2283 proc_drop_zombref(target_p);
2284 else
2285 proc_rele(target_p);
2286
2287 kauth_cred_unref(&target_cred);
316670eb
A
2288
2289 return(error);
2290}
39236c6e
A
2291#else
2292
2293int
2294proc_dirtycontrol(__unused int pid, __unused int flavor, __unused uint64_t arg, __unused int32_t *retval) {
2295 return ENOTSUP;
2296}
2297
2298#endif /* CONFIG_MEMORYSTATUS */
316670eb
A
2299
2300/*
2301 * proc_terminate() provides support for sudden termination.
2302 * SIGKILL is issued to tracked, clean processes; otherwise,
2303 * SIGTERM is sent.
2304 */
2305
2306int
2307proc_terminate(int pid, int32_t *retval)
2308{
2309 int error = 0;
2310 proc_t p;
2311 kauth_cred_t uc = kauth_cred_get();
2312 int sig;
2313
2314#if 0
2315 /* XXX: Check if these are necessary */
2316 AUDIT_ARG(pid, pid);
2317 AUDIT_ARG(signum, sig);
2318#endif
2319
2320 if (pid <= 0 || retval == NULL) {
2321 return (EINVAL);
2322 }
2323
2324 if ((p = proc_find(pid)) == NULL) {
2325 return (ESRCH);
2326 }
2327
2328#if 0
2329 /* XXX: Check if these are necessary */
2330 AUDIT_ARG(process, p);
2331#endif
2332
2333 /* Check privileges; if SIGKILL can be issued, then SIGTERM is also OK */
2334 if (!cansignal(current_proc(), uc, p, SIGKILL, 0)) {
2335 error = EPERM;
2336 goto out;
2337 }
39236c6e
A
2338
2339 /* Not allowed to sudden terminate yourself */
2340 if (p == current_proc()) {
2341 error = EPERM;
2342 goto out;
316670eb
A
2343 }
2344
39236c6e
A
2345#if CONFIG_MEMORYSTATUS
2346 /* Determine requisite signal to issue */
2347 sig = memorystatus_on_terminate(p);
2348#else
2349 sig = SIGTERM;
2350#endif
316670eb 2351
39236c6e
A
2352 proc_set_task_policy(p->task, THREAD_NULL, TASK_POLICY_ATTRIBUTE,
2353 TASK_POLICY_TERMINATED, TASK_POLICY_ENABLE);
316670eb
A
2354
2355 psignal(p, sig);
2356 *retval = sig;
2357
2358out:
2359 proc_rele(p);
2360
2361 return error;
2362}
2363
2d21ac55
A
2364/*
2365 * copy stat64 structure into vinfo_stat structure.
2366 */
2367static void
2368munge_vinfo_stat(struct stat64 *sbp, struct vinfo_stat *vsbp)
2369{
2370 bzero(vsbp, sizeof(struct vinfo_stat));
2371
2372 vsbp->vst_dev = sbp->st_dev;
2373 vsbp->vst_mode = sbp->st_mode;
2374 vsbp->vst_nlink = sbp->st_nlink;
2375 vsbp->vst_ino = sbp->st_ino;
2376 vsbp->vst_uid = sbp->st_uid;
2377 vsbp->vst_gid = sbp->st_gid;
2378 vsbp->vst_atime = sbp->st_atimespec.tv_sec;
2379 vsbp->vst_atimensec = sbp->st_atimespec.tv_nsec;
2380 vsbp->vst_mtime = sbp->st_mtimespec.tv_sec;
2381 vsbp->vst_mtimensec = sbp->st_mtimespec.tv_nsec;
2382 vsbp->vst_ctime = sbp->st_ctimespec.tv_sec;
2383 vsbp->vst_ctimensec = sbp->st_ctimespec.tv_nsec;
2384 vsbp->vst_birthtime = sbp->st_birthtimespec.tv_sec;
2385 vsbp->vst_birthtimensec = sbp->st_birthtimespec.tv_nsec;
2386 vsbp->vst_size = sbp->st_size;
2387 vsbp->vst_blocks = sbp->st_blocks;
2388 vsbp->vst_blksize = sbp->st_blksize;
2389 vsbp->vst_flags = sbp->st_flags;
2390 vsbp->vst_gen = sbp->st_gen;
2391 vsbp->vst_rdev = sbp->st_rdev;
2392 vsbp->vst_qspare[0] = sbp->st_qspare[0];
2393 vsbp->vst_qspare[1] = sbp->st_qspare[1];
2394}
39236c6e
A
2395
2396int
2397proc_pid_rusage(int pid, int flavor, user_addr_t buffer, __unused int32_t *retval)
2398{
2399 proc_t p;
2400 int error;
2401 int zombie = 0;
2402
2403 if ((p = proc_find(pid)) == PROC_NULL) {
2404 if ((p = proc_find_zombref(pid)) == PROC_NULL) {
2405 return (ESRCH);
2406 }
2407 zombie = 1;
2408 }
2409
2410 /* Do we have permission to look into this? */
2411 if ((error = proc_security_policy(p, PROC_INFO_CALL_PIDRUSAGE, flavor, CHECK_SAME_USER)))
2412 goto out;
2413
2414 error = proc_get_rusage(p, flavor, buffer, zombie);
2415
2416out:
2417 if (zombie)
2418 proc_drop_zombref(p);
2419 else
2420 proc_rele(p);
2421
2422 return (error);
2423}
2424
fe8ab488
A
2425void
2426proc_archinfo(proc_t p, struct proc_archinfo *pai)
2427{
2428 proc_lock(p);
2429 pai->p_cputype = p->p_cputype;
2430 pai->p_cpusubtype = p->p_cpusubtype;
2431 proc_unlock(p);
2432}
2433
2434void
2435proc_pidcoalitioninfo(proc_t p, struct proc_pidcoalitioninfo *ppci)
2436{
2437 bzero(ppci, sizeof(*ppci));
2438 ppci->coalition_id = proc_coalitionid(p);
2439}
2440
2441
2442
2443/*
2444 * Wrapper to provide NOTE_EXIT_DETAIL and NOTE_EXITSTATUS
2445 * It mimics the data that is typically captured by the
2446 * EVFILT_PROC, NOTE_EXIT event mechanism.
2447 * See filt_proc() in kern_event.c.
2448 */
2449int
2450proc_pidnoteexit(proc_t p, uint64_t flags, uint32_t *data)
2451{
2452 uint32_t exit_data = 0;
2453 uint32_t exit_flags = (uint32_t)flags;
2454
2455 proc_lock(p);
2456
2457 /*
2458 * Allow access to the parent of the exiting
2459 * child or the parent debugger only.
2460 */
2461 do {
2462 pid_t selfpid = proc_selfpid();
2463
2464 if (p->p_ppid == selfpid)
2465 break; /* parent => ok */
2466
2467 if ((p->p_lflag & P_LTRACED) != 0 &&
2468 (p->p_oppid == selfpid))
2469 break; /* parent-in-waiting => ok */
2470
2471 proc_unlock(p);
2472 return (EACCES);
2473 } while (0);
2474
2475 if ((exit_flags & NOTE_EXITSTATUS) != 0) {
2476 /* The signal and exit status */
2477 exit_data |= (p->p_xstat & NOTE_PDATAMASK);
2478 }
2479
2480 if ((exit_flags & NOTE_EXIT_DETAIL) != 0) {
2481 /* The exit detail */
2482 if ((p->p_lflag & P_LTERM_DECRYPTFAIL) != 0) {
2483 exit_data |= NOTE_EXIT_DECRYPTFAIL;
2484 }
2485
2486 if ((p->p_lflag & P_LTERM_JETSAM) != 0) {
2487 exit_data |= NOTE_EXIT_MEMORY;
2488
2489 switch (p->p_lflag & P_JETSAM_MASK) {
2490 case P_JETSAM_VMPAGESHORTAGE:
2491 exit_data |= NOTE_EXIT_MEMORY_VMPAGESHORTAGE;
2492 break;
2493 case P_JETSAM_VMTHRASHING:
2494 exit_data |= NOTE_EXIT_MEMORY_VMTHRASHING;
2495 break;
2496 case P_JETSAM_FCTHRASHING:
2497 exit_data |= NOTE_EXIT_MEMORY_FCTHRASHING;
2498 break;
2499 case P_JETSAM_VNODE:
2500 exit_data |= NOTE_EXIT_MEMORY_VNODE;
2501 break;
2502 case P_JETSAM_HIWAT:
2503 exit_data |= NOTE_EXIT_MEMORY_HIWAT;
2504 break;
2505 case P_JETSAM_PID:
2506 exit_data |= NOTE_EXIT_MEMORY_PID;
2507 break;
2508 case P_JETSAM_IDLEEXIT:
2509 exit_data |= NOTE_EXIT_MEMORY_IDLE;
2510 break;
2511 }
2512 }
2513
2514 if ((p->p_csflags & CS_KILLED) != 0) {
2515 exit_data |= NOTE_EXIT_CSERROR;
2516 }
2517 }
2518
2519 proc_unlock(p);
2520
2521 *data = exit_data;
2522
2523 return (0);
2524}
2525