]> git.saurik.com Git - apple/xnu.git/blob - bsd/kern/proc_info.c
2af5cc29e2b81423594279252ad318f2b102eae4
[apple/xnu.git] / bsd / kern / proc_info.c
1 /*
2 * Copyright (c) 2005-2013 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
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.
14 *
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
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
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>
51 #include <sys/kern_memorystatus.h>
52
53 #include <security/audit/audit.h>
54
55 #include <mach/machine.h>
56 #include <mach/mach_types.h>
57 #include <mach/vm_param.h>
58 #include <kern/task.h>
59 #include <kern/kalloc.h>
60 #include <kern/assert.h>
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>
74 #include <sys/priv.h>
75
76 #include <sys/guarded.h>
77
78 #include <machine/machine_routines.h>
79
80 #include <kern/ipc_misc.h>
81
82 #include <vm/vm_protos.h>
83
84 /* Needed by proc_pidnoteexit() */
85 #include <sys/event.h>
86 #include <sys/codesign.h>
87
88 struct pshmnode;
89 struct psemnode;
90 struct pipe;
91 struct kqueue;
92 struct atalk;
93
94 uint64_t get_dispatchqueue_offset_from_proc(void *);
95 uint64_t get_dispatchqueue_serialno_offset_from_proc(void *);
96 int proc_info_internal(int callnum, int pid, int flavor, uint64_t arg, user_addr_t buffer, uint32_t buffersize, int32_t * retval);
97
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
125 /* protos for proc_info calls */
126 int __attribute__ ((noinline)) proc_listpids(uint32_t type, uint32_t tyoneinfo, user_addr_t buffer, uint32_t buffersize, int32_t * retval);
127 int __attribute__ ((noinline)) proc_pidinfo(int pid, int flavor, uint64_t arg, user_addr_t buffer, uint32_t buffersize, int32_t * retval);
128 int __attribute__ ((noinline)) proc_pidfdinfo(int pid, int flavor,int fd, user_addr_t buffer, uint32_t buffersize, int32_t * retval);
129 int __attribute__ ((noinline)) proc_kernmsgbuf(user_addr_t buffer, uint32_t buffersize, int32_t * retval);
130 int __attribute__ ((noinline)) proc_setcontrol(int pid, int flavor, uint64_t arg, user_addr_t buffer, uint32_t buffersize, int32_t * retval);
131 int __attribute__ ((noinline)) proc_pidfileportinfo(int pid, int flavor, mach_port_name_t name, user_addr_t buffer, uint32_t buffersize, int32_t *retval);
132 int __attribute__ ((noinline)) proc_dirtycontrol(int pid, int flavor, uint64_t arg, int32_t * retval);
133 int __attribute__ ((noinline)) proc_terminate(int pid, int32_t * retval);
134 int __attribute__ ((noinline)) proc_pid_rusage(int pid, int flavor, user_addr_t buffer, int32_t * retval);
135 int __attribute__ ((noinline)) proc_pidoriginatorinfo(int pid, int flavor, user_addr_t buffer, uint32_t buffersize, int32_t * retval);
136
137 /* protos for procpidinfo calls */
138 int __attribute__ ((noinline)) proc_pidfdlist(proc_t p, user_addr_t buffer, uint32_t buffersize, int32_t *retval);
139 int __attribute__ ((noinline)) proc_pidbsdinfo(proc_t p, struct proc_bsdinfo *pbsd, int zombie);
140 int __attribute__ ((noinline)) proc_pidshortbsdinfo(proc_t p, struct proc_bsdshortinfo *pbsd_shortp, int zombie);
141 int __attribute__ ((noinline)) proc_pidtaskinfo(proc_t p, struct proc_taskinfo *ptinfo);
142 int __attribute__ ((noinline)) proc_pidthreadinfo(proc_t p, uint64_t arg, int thuniqueid, struct proc_threadinfo *pthinfo);
143 int __attribute__ ((noinline)) proc_pidthreadpathinfo(proc_t p, uint64_t arg, struct proc_threadwithpathinfo *pinfo);
144 int __attribute__ ((noinline)) proc_pidlistthreads(proc_t p, user_addr_t buffer, uint32_t buffersize, int32_t *retval);
145 int __attribute__ ((noinline)) proc_pidregioninfo(proc_t p, uint64_t arg, user_addr_t buffer, uint32_t buffersize, int32_t *retval);
146 int __attribute__ ((noinline)) proc_pidregionpathinfo(proc_t p, uint64_t arg, user_addr_t buffer, uint32_t buffersize, int32_t *retval);
147 int __attribute__ ((noinline)) proc_pidregionpathinfo2(proc_t p, uint64_t arg, user_addr_t buffer, uint32_t buffersize, int32_t *retval);
148 int __attribute__ ((noinline)) proc_pidregionpathinfo3(proc_t p, uint64_t arg, user_addr_t buffer, uint32_t buffersize, int32_t *retval);
149 int __attribute__ ((noinline)) proc_pidvnodepathinfo(proc_t p, uint64_t arg, user_addr_t buffer, uint32_t buffersize, int32_t *retval);
150 int __attribute__ ((noinline)) proc_pidpathinfo(proc_t p, uint64_t arg, user_addr_t buffer, uint32_t buffersize, int32_t *retval);
151 int __attribute__ ((noinline)) proc_pidworkqueueinfo(proc_t p, struct proc_workqueueinfo *pwqinfo);
152 int __attribute__ ((noinline)) proc_pidfileportlist(proc_t p, user_addr_t buffer, uint32_t buffersize, int32_t *retval);
153 void __attribute__ ((noinline)) proc_piduniqidentifierinfo(proc_t p, struct proc_uniqidentifierinfo *p_uniqidinfo);
154 void __attribute__ ((noinline)) proc_archinfo(proc_t p, struct proc_archinfo *pai);
155 void __attribute__ ((noinline)) proc_pidcoalitioninfo(proc_t p, struct proc_pidcoalitioninfo *pci);
156 int __attribute__ ((noinline)) proc_pidnoteexit(proc_t p, uint64_t arg, uint32_t *data);
157
158
159 /* protos for proc_pidfdinfo calls */
160 int __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);
161 int __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);
162 int __attribute__ ((noinline)) pid_socketinfo(socket_t so, struct fileproc *fp, int closeonexec, user_addr_t buffer, uint32_t buffersize, int32_t * retval);
163 int __attribute__ ((noinline)) pid_pseminfo(struct psemnode * psem, struct fileproc * fp, int closeonexec, user_addr_t buffer, uint32_t buffersize, int32_t * retval);
164 int __attribute__ ((noinline)) pid_pshminfo(struct pshmnode * pshm, struct fileproc * fp, int closeonexec, user_addr_t buffer, uint32_t buffersize, int32_t * retval);
165 int __attribute__ ((noinline)) pid_pipeinfo(struct pipe * p, struct fileproc * fp, int closeonexec, user_addr_t buffer, uint32_t buffersize, int32_t * retval);
166 int __attribute__ ((noinline)) pid_kqueueinfo(struct kqueue * kq, struct fileproc * fp, int closeonexec, user_addr_t buffer, uint32_t buffersize, int32_t * retval);
167 int __attribute__ ((noinline)) pid_atalkinfo(struct atalk * at, struct fileproc * fp, int closeonexec, user_addr_t buffer, uint32_t buffersize, int32_t * retval);
168
169
170 /* protos for misc */
171
172 int fill_vnodeinfo(vnode_t vp, struct vnode_info *vinfo);
173 void fill_fileinfo(struct fileproc * fp, int closeonexec, struct proc_fileinfo * finfo);
174 int proc_security_policy(proc_t targetp, int callnum, int flavor, boolean_t check_same_user);
175 static void munge_vinfo_stat(struct stat64 *sbp, struct vinfo_stat *vsbp);
176 static int proc_piduuidinfo(pid_t pid, uuid_t uuid_buf, uint32_t buffersize);
177
178 extern int cansignal(struct proc *, kauth_cred_t, struct proc *, int, int);
179 extern 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
183
184 uint64_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
194 uint64_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
204 /***************************** proc_info ********************/
205
206 int
207 proc_info(__unused struct proc *p, struct proc_info_args * uap, int32_t *retval)
208 {
209 return(proc_info_internal(uap->callnum, uap->pid, uap->flavor, uap->arg, uap->buffer, uap->buffersize, retval));
210 }
211
212
213 int
214 proc_info_internal(int callnum, int pid, int flavor, uint64_t arg, user_addr_t buffer, uint32_t buffersize, int32_t * retval)
215 {
216
217 switch(callnum) {
218 case PROC_INFO_CALL_LISTPIDS:
219 /* pid contains type and flavor contains typeinfo */
220 return(proc_listpids(pid, flavor, buffer, buffersize, retval));
221 case PROC_INFO_CALL_PIDINFO:
222 return(proc_pidinfo(pid, flavor, arg, buffer, buffersize, retval));
223 case PROC_INFO_CALL_PIDFDINFO:
224 return(proc_pidfdinfo(pid, flavor, (int)arg, buffer, buffersize, retval));
225 case PROC_INFO_CALL_KERNMSGBUF:
226 return(proc_kernmsgbuf(buffer, buffersize, retval));
227 case PROC_INFO_CALL_SETCONTROL:
228 return(proc_setcontrol(pid, flavor, arg, buffer, buffersize, retval));
229 case PROC_INFO_CALL_PIDFILEPORTINFO:
230 return(proc_pidfileportinfo(pid, flavor, (mach_port_name_t)arg, buffer, buffersize, retval));
231 case PROC_INFO_CALL_TERMINATE:
232 return(proc_terminate(pid, retval));
233 case PROC_INFO_CALL_DIRTYCONTROL:
234 return(proc_dirtycontrol(pid, flavor, arg, retval));
235 case PROC_INFO_CALL_PIDRUSAGE:
236 return (proc_pid_rusage(pid, flavor, buffer, retval));
237 case PROC_INFO_CALL_PIDORIGINATORINFO:
238 return (proc_pidoriginatorinfo(pid, flavor, buffer, buffersize, retval));
239 default:
240 return(EINVAL);
241 }
242
243 return(EINVAL);
244 }
245
246 /******************* proc_listpids routine ****************/
247 int
248 proc_listpids(uint32_t type, uint32_t typeinfo, user_addr_t buffer, uint32_t buffersize, int32_t * retval)
249 {
250 int numprocs, wantpids;
251 char * kbuf;
252 int * ptr;
253 int n, skip;
254 struct proc * p;
255 struct tty * tp;
256 int error = 0;
257 struct proclist *current_list;
258
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
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)));
278 if (kbuf == NULL)
279 return(ENOMEM);
280 bzero(kbuf, sizeof(int));
281
282 proc_list_lock();
283
284
285 n = 0;
286 ptr = (int *)kbuf;
287 current_list = &allproc;
288 proc_loop:
289 LIST_FOREACH(p, current_list, p_list) {
290 skip = 0;
291 switch (type) {
292 case PROC_PGRP_ONLY:
293 if (p->p_pgrpid != (pid_t)typeinfo)
294 skip = 1;
295 break;
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
301 case PROC_ALL_PIDS:
302 skip = 0;
303 break;
304 case PROC_TTY_ONLY:
305 /* racy but list lock is held */
306 if ((p->p_flag & P_CONTROLT) == 0 ||
307 (p->p_pgrp == NULL) || (p->p_pgrp->pg_session == NULL) ||
308 (tp = SESSION_TP(p->p_pgrp->pg_session)) == TTY_NULL ||
309 tp->t_dev != (dev_t)typeinfo)
310 skip = 1;
311 break;
312 case PROC_UID_ONLY:
313 if (p->p_ucred == NULL)
314 skip = 1;
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 }
325 break;
326 case PROC_RUID_ONLY:
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);
334 uid = kauth_cred_getruid(my_cred);
335 kauth_cred_unref(&my_cred);
336 if (uid != (uid_t)typeinfo)
337 skip = 1;
338 }
339 break;
340 default:
341 skip = 1;
342 break;
343 };
344
345 if(skip == 0) {
346 *ptr++ = p->p_pid;
347 n++;
348 }
349 if (n >= numprocs)
350 break;
351 }
352
353 if ((n < numprocs) && (current_list == &allproc)) {
354 current_list = &zombproc;
355 goto proc_loop;
356 }
357
358 proc_list_unlock();
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
370 /********************************** proc_pidfdlist routines ********************************/
371
372 int
373 proc_pidfdlist(proc_t p, user_addr_t buffer, uint32_t buffersize, int32_t *retval)
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)));
398 if (kbuf == NULL)
399 return(ENOMEM);
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)) {
409 file_type_t fdtype = FILEGLOB_DTYPE(fp->f_fglob);
410 pfd->proc_fd = n;
411 pfd->proc_fdtype = (fdtype != DTYPE_ATALK) ?
412 fdtype : PROX_FDTYPE_ATALK;
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
426 /*
427 * Helper functions for proc_pidfileportlist.
428 */
429 static int
430 proc_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
439 struct fileport_fdtype_args {
440 struct proc_fileportinfo *ffa_pfi;
441 struct proc_fileportinfo *ffa_pfi_end;
442 };
443
444 static int
445 proc_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) {
450 file_type_t fdtype = FILEGLOB_DTYPE(fg);
451
452 ffa->ffa_pfi->proc_fdtype = (fdtype != DTYPE_ATALK) ?
453 fdtype : PROX_FDTYPE_ATALK;
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
461 int
462 proc_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 }
542
543 int
544 proc_pidbsdinfo(proc_t p, struct proc_bsdinfo * pbsd, int zombie)
545 {
546 register struct tty *tp;
547 struct session *sessionp = NULL;
548 struct pgrp * pg;
549 kauth_cred_t my_cred;
550
551 pg = proc_pgrp(p);
552 sessionp = proc_session(p);
553
554 my_cred = kauth_cred_proc_ref(p);
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;
559 pbsd->pbi_ppid = p->p_ppid;
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);
566 kauth_cred_unref(&my_cred);
567
568 pbsd->pbi_nice = p->p_nice;
569 pbsd->pbi_start_tvsec = p->p_start.tv_sec;
570 pbsd->pbi_start_tvusec = p->p_start.tv_usec;
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';
575
576 pbsd->pbi_flags = 0;
577 if ((p->p_flag & P_SYSTEM) == P_SYSTEM)
578 pbsd->pbi_flags |= PROC_FLAG_SYSTEM;
579 if ((p->p_lflag & P_LTRACED) == P_LTRACED)
580 pbsd->pbi_flags |= PROC_FLAG_TRACED;
581 if ((p->p_lflag & P_LEXIT) == P_LEXIT)
582 pbsd->pbi_flags |= PROC_FLAG_INEXIT;
583 if ((p->p_lflag & P_LPPWAIT) == P_LPPWAIT)
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;
589 if ((p->p_flag & P_THCWD) == P_THCWD)
590 pbsd->pbi_flags |= PROC_FLAG_THCWD;
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;
595
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
603 if ((p->p_flag & P_DELAYIDLESLEEP) == P_DELAYIDLESLEEP)
604 pbsd->pbi_flags |= PROC_FLAG_DELAYIDLESLEEP;
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 };
626
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
631 if (zombie == 0)
632 pbsd->pbi_nfiles = p->p_fd->fd_nfiles;
633
634 pbsd->e_tdev = NODEV;
635 if (pg != PGRP_NULL) {
636 pbsd->pbi_pgid = p->p_pgrpid;
637 pbsd->pbi_pjobc = pg->pg_jobc;
638 if ((p->p_flag & P_CONTROLT) && (sessionp != SESSION_NULL) && (tp = SESSION_TP(sessionp))) {
639 pbsd->e_tdev = tp->t_dev;
640 pbsd->e_tpgid = sessionp->s_ttypgrpid;
641 }
642 }
643 if (sessionp != SESSION_NULL)
644 session_rele(sessionp);
645 if (pg != PGRP_NULL)
646 pg_rele(pg);
647
648 return(0);
649 }
650
651
652 int
653 proc_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;
682 if ((p->p_flag & P_DELAYIDLESLEEP) == P_DELAYIDLESLEEP)
683 pbsd_shortp->pbsi_flags |= PROC_FLAG_DELAYIDLESLEEP;
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
720 int
721 proc_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
735 int
736 proc_pidthreadinfo(proc_t p, uint64_t arg, int thuniqueid, struct proc_threadinfo *pthinfo)
737 {
738 int error = 0;
739 uint64_t threadaddr = (uint64_t)arg;
740
741 bzero(pthinfo, sizeof(struct proc_threadinfo));
742
743 error = fill_taskthreadinfo(p->task, threadaddr, thuniqueid, (struct proc_threadinfo_internal *)pthinfo, NULL, NULL);
744 if (error)
745 return(ESRCH);
746 else
747 return(0);
748
749 }
750
751 void
752 bsd_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 }
758
759 void
760 bsd_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
777 int
778 proc_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
788 error = fill_taskthreadinfo(p->task, threadaddr, 0, (struct proc_threadinfo_internal *)&pinfo->pt, (void *)&vp, &vid);
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
806 int
807 proc_pidlistthreads(proc_t p, user_addr_t buffer, uint32_t buffersize, int32_t *retval)
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));
825 if (kbuf == NULL)
826 return(ENOMEM);
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
840 int
841 proc_pidregioninfo(proc_t p, uint64_t arg, user_addr_t buffer, __unused uint32_t buffersize, int32_t *retval)
842 {
843 struct proc_regioninfo preginfo;
844 int ret, error = 0;
845
846 bzero(&preginfo, sizeof(struct proc_regioninfo));
847 ret = fill_procregioninfo( p->task, arg, (struct proc_regioninfo_internal *)&preginfo, (uintptr_t *)0, (uint32_t *)0);
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
857 int
858 proc_pidregionpathinfo(proc_t p, uint64_t arg, user_addr_t buffer, __unused uint32_t buffersize, int32_t *retval)
859 {
860 struct proc_regionwithpathinfo preginfo;
861 int ret, error = 0;
862 uintptr_t vnodeaddr= 0;
863 uint32_t vnodeid= 0;
864 vnode_t vp;
865 int count;
866
867 bzero(&preginfo, sizeof(struct proc_regionwithpathinfo));
868
869 ret = fill_procregioninfo( p->task, arg, (struct proc_regioninfo_internal *)&preginfo.prp_prinfo, (uintptr_t *)&vnodeaddr, (uint32_t *)&vnodeid);
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
890 int
891 proc_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
927 int
928 proc_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
989 /*
990 * Path is relative to current process directory; may different from current
991 * thread directory.
992 */
993 int
994 proc_pidvnodepathinfo(proc_t p, __unused uint64_t arg, user_addr_t buffer, __unused uint32_t buffersize, int32_t *retval)
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 }
1051 out:
1052 return(error);
1053 }
1054
1055 int
1056 proc_pidpathinfo(proc_t p, __unused uint64_t arg, user_addr_t buffer, uint32_t buffersize, __unused int32_t *retval)
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) {
1077 error = vn_getpath_fsenter(tvp, buf, &len);
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
1093 int
1094 proc_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 }
1107
1108
1109 void
1110 proc_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
1120
1121 static int
1122 proc_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 */
1151 int
1152 proc_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
1180 int
1181 proc_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 }
1232 out:
1233 return error;
1234 }
1235
1236 /********************************** proc_pidinfo ********************************/
1237
1238
1239 int
1240 proc_pidinfo(int pid, int flavor, uint64_t arg, user_addr_t buffer, uint32_t buffersize, int32_t * retval)
1241 {
1242 struct proc * p = PROC_NULL;
1243 int error = ENOTSUP;
1244 int gotref = 0;
1245 int findzomb = 0;
1246 int shortversion = 0;
1247 uint32_t size;
1248 int zombie = 0;
1249 int thuniqueid = 0;
1250 int uniqidversion = 0;
1251 boolean_t check_same_user;
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;
1283 case PROC_PIDTHREADPATHINFO:
1284 size = PROC_PIDTHREADPATHINFO_SIZE;
1285 break;
1286 case PROC_PIDPATHINFO:
1287 size = MAXPATHLEN;
1288 break;
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;
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;
1304 case PROC_PIDTHREADID64INFO:
1305 size = PROC_PIDTHREADID64INFO_SIZE;
1306 break;
1307 case PROC_PIDUNIQIDENTIFIERINFO:
1308 size = PROC_PIDUNIQIDENTIFIERINFO_SIZE;
1309 break;
1310 case PROC_PIDT_BSDINFOWITHUNIQID:
1311 size = PROC_PIDT_BSDINFOWITHUNIQID_SIZE;
1312 break;
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;
1333 default:
1334 return(EINVAL);
1335 }
1336
1337 if (buffersize < size)
1338 return(ENOMEM);
1339
1340 if ((flavor == PROC_PIDPATHINFO) && (buffersize > PROC_PIDPATHINFO_MAXSIZE)) {
1341 return(EOVERFLOW);
1342 }
1343
1344 /* Check if we need to look for zombies */
1345 if ((flavor == PROC_PIDTBSDINFO) || (flavor == PROC_PIDT_SHORTBSDINFO) || (flavor == PROC_PIDT_BSDINFOWITHUNIQID)
1346 || (flavor == PROC_PIDUNIQIDENTIFIERINFO)) {
1347 if (arg)
1348 findzomb = 1;
1349 }
1350
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;
1361 }
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
1379 switch (flavor) {
1380 case PROC_PIDLISTFDS: {
1381 error = proc_pidfdlist(p, buffer, buffersize, retval);
1382 }
1383 break;
1384
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
1395 case PROC_PIDT_SHORTBSDINFO:
1396 shortversion = 1;
1397 case PROC_PIDT_BSDINFOWITHUNIQID:
1398 case PROC_PIDTBSDINFO: {
1399 struct proc_bsdinfo pbsd;
1400 struct proc_bsdshortinfo pbsd_short;
1401 struct proc_bsdinfowithuniqid pbsd_uniqid;
1402
1403 if (flavor == PROC_PIDT_BSDINFOWITHUNIQID)
1404 uniqidversion = 1;
1405
1406 if (shortversion != 0) {
1407 error = proc_pidshortbsdinfo(p, &pbsd_short, zombie);
1408 } else {
1409 error = proc_pidbsdinfo(p, &pbsd, zombie);
1410 if (uniqidversion != 0) {
1411 proc_piduniqidentifierinfo(p, &pbsd_uniqid.p_uniqidentifier);
1412 pbsd_uniqid.pbsd = pbsd;
1413 }
1414 }
1415
1416 if (error == 0) {
1417 if (shortversion != 0) {
1418 error = copyout(&pbsd_short, buffer, sizeof(struct proc_bsdshortinfo));
1419 if (error == 0)
1420 *retval = sizeof(struct proc_bsdshortinfo);
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 {
1426 error = copyout(&pbsd, buffer, sizeof(struct proc_bsdinfo));
1427 if (error == 0)
1428 *retval = sizeof(struct proc_bsdinfo);
1429 }
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
1449 error = proc_pidbsdinfo(p, &pall.pbsd, 0);
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
1459 case PROC_PIDTHREADID64INFO:
1460 thuniqueid = 1;
1461 case PROC_PIDTHREADINFO:{
1462 struct proc_threadinfo pthinfo;
1463
1464 error = proc_pidthreadinfo(p, arg, thuniqueid, &pthinfo);
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
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
1499 case PROC_PIDVNODEPATHINFO:{
1500 error = proc_pidvnodepathinfo(p, arg, buffer, buffersize, retval);
1501 }
1502 break;
1503
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: {
1518 error = proc_pidpathinfo(p, arg, buffer, buffersize, retval);
1519 }
1520 break;
1521
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
1535 case PROC_PIDLISTFILEPORTS: {
1536 error = proc_pidfileportlist(p, buffer, buffersize,
1537 retval);
1538 }
1539 break;
1540
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
1572 default:
1573 error = ENOTSUP;
1574 }
1575
1576 out:
1577 if (gotref)
1578 proc_rele(p);
1579 else if (zombie)
1580 proc_drop_zombref(p);
1581 return(error);
1582 }
1583
1584
1585 int
1586 pid_vnodeinfo(vnode_t vp, uint32_t vid, struct fileproc * fp, int closeonexec, user_addr_t buffer, __unused uint32_t buffersize, int32_t * retval)
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));
1595 fill_fileinfo(fp, closeonexec, &vfi.pfi);
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
1606 int
1607 pid_vnodeinfopath(vnode_t vp, uint32_t vid, struct fileproc * fp, int closeonexec, user_addr_t buffer, __unused uint32_t buffersize, int32_t * retval)
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));
1616 fill_fileinfo(fp, closeonexec, &vfip.pfi);
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
1631 void
1632 fill_fileinfo(struct fileproc * fp, int closeonexec, struct proc_fileinfo * fproc)
1633 {
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 }
1655 }
1656
1657
1658
1659 int
1660 fill_vnodeinfo(vnode_t vp, struct vnode_info *vinfo)
1661 {
1662 vfs_context_t context;
1663 struct stat64 sb;
1664 int error = 0;
1665
1666 context = vfs_context_create((vfs_context_t)0);
1667 error = vn_stat(vp, &sb, NULL, 1, context);
1668 (void)vfs_context_rele(context);
1669
1670 munge_vinfo_stat(&sb, &vinfo->vi_stat);
1671
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;
1682 out:
1683 return(error);
1684 }
1685
1686 int
1687 pid_socketinfo(socket_t so, struct fileproc *fp, int closeonexec, user_addr_t buffer, __unused uint32_t buffersize, int32_t * retval)
1688 {
1689 #if SOCKETS
1690 struct socket_fdinfo s;
1691 int error = 0;
1692
1693 bzero(&s, sizeof(struct socket_fdinfo));
1694 fill_fileinfo(fp, closeonexec, &s.pfi);
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 }
1699 return (error);
1700 #else
1701 #pragma unused(so, fp, closeonexec, buffer)
1702 *retval = 0;
1703 return (ENOTSUP);
1704 #endif
1705 }
1706
1707 int
1708 pid_pseminfo(struct psemnode *psem, struct fileproc *fp, int closeonexec, user_addr_t buffer, __unused uint32_t buffersize, int32_t * retval)
1709 {
1710 struct psem_fdinfo pseminfo;
1711 int error = 0;
1712
1713 bzero(&pseminfo, sizeof(struct psem_fdinfo));
1714 fill_fileinfo(fp, closeonexec, &pseminfo.pfi);
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
1724 int
1725 pid_pshminfo(struct pshmnode *pshm, struct fileproc *fp, int closeonexec, user_addr_t buffer, __unused uint32_t buffersize, int32_t * retval)
1726 {
1727 struct pshm_fdinfo pshminfo;
1728 int error = 0;
1729
1730 bzero(&pshminfo, sizeof(struct pshm_fdinfo));
1731 fill_fileinfo(fp, closeonexec, &pshminfo.pfi);
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
1741 int
1742 pid_pipeinfo(struct pipe * p, struct fileproc *fp, int closeonexec, user_addr_t buffer, __unused uint32_t buffersize, int32_t * retval)
1743 {
1744 struct pipe_fdinfo pipeinfo;
1745 int error = 0;
1746
1747 bzero(&pipeinfo, sizeof(struct pipe_fdinfo));
1748 fill_fileinfo(fp, closeonexec, &pipeinfo.pfi);
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
1757 int
1758 pid_kqueueinfo(struct kqueue * kq, struct fileproc *fp, int closeonexec, user_addr_t buffer, __unused uint32_t buffersize, int32_t * retval)
1759 {
1760 struct kqueue_fdinfo kqinfo;
1761 int error = 0;
1762
1763 bzero(&kqinfo, sizeof(struct kqueue_fdinfo));
1764
1765 fill_fileinfo(fp, closeonexec, &kqinfo.pfi);
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
1775 int
1776 pid_atalkinfo(__unused struct atalk * at, __unused struct fileproc *fp, __unused int closeonexec, __unused user_addr_t buffer, __unused uint32_t buffersize, __unused int32_t * retval)
1777 {
1778 return ENOTSUP;
1779 }
1780
1781
1782
1783 /************************** proc_pidfdinfo routine ***************************/
1784 int
1785 proc_pidfdinfo(int pid, int flavor, int fd, user_addr_t buffer, uint32_t buffersize, int32_t * retval)
1786 {
1787 proc_t p;
1788 int error = ENOTSUP;
1789 struct fileproc * fp;
1790 uint32_t size;
1791 int closeonexec = 0;
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
1827 if ((p = proc_find(pid)) == PROC_NULL) {
1828 error = ESRCH;
1829 goto out;
1830 }
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)))
1834 goto out1;
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 }
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);
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
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);
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 }
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);
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 }
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);
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 }
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);
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 }
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);
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 }
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);
1921 }
1922 break;
1923
1924 default: {
1925 error = EINVAL;
1926 goto out1;
1927 }
1928 }
1929
1930 fp_drop(p, fd, fp , 0);
1931 out1 :
1932 proc_rele(p);
1933 out:
1934 return(error);
1935 }
1936
1937 /*
1938 * Helper function for proc_pidfileportinfo
1939 */
1940
1941 struct 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
1948 static kern_return_t
1949 proc_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
1963 if (FILEGLOB_DTYPE(fg) != DTYPE_VNODE) {
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
1975 if (FILEGLOB_DTYPE(fg) != DTYPE_SOCKET) {
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
1987 if (FILEGLOB_DTYPE(fg) != DTYPE_PSXSHM) {
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
1999 if (FILEGLOB_DTYPE(fg) != DTYPE_PIPE) {
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 *********************/
2017 int
2018 proc_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 }
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)))
2054 goto out1;
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;
2064 out1:
2065 proc_rele(p);
2066 out:
2067 return (error);
2068 }
2069
2070 int
2071 proc_security_policy(proc_t targetp, __unused int callnum, __unused int flavor, boolean_t check_same_user)
2072 {
2073 #if CONFIG_MACF
2074 int error = 0;
2075
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)
2102 return(EPERM);
2103 }
2104
2105 return(0);
2106 }
2107
2108 int
2109 proc_kernmsgbuf(user_addr_t buffer, uint32_t buffersize, int32_t * retval)
2110 {
2111 if (suser(kauth_cred_get(), (u_short *)0) == 0) {
2112 return(log_dmesg(buffer, buffersize, retval));
2113 } else
2114 return(EPERM);
2115 }
2116
2117 /* ********* process control sets on self only */
2118 int
2119 proc_setcontrol(int pid, int flavor, uint64_t arg, user_addr_t buffer, uint32_t buffersize, __unused int32_t * retval)
2120 {
2121 struct proc * pself = PROC_NULL;
2122 int error = 0;
2123 uint32_t pcontrol = (uint32_t)arg;
2124 struct uthread *ut = NULL;
2125
2126
2127 pself = current_proc();
2128 if (pid != pself->p_pid)
2129 return(EINVAL);
2130
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;
2134
2135 switch (flavor) {
2136 case PROC_SELFSET_PCONTROL: {
2137 if (pcontrol > P_PCMAX)
2138 return(EINVAL);
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
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
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
2188 default:
2189 error = ENOTSUP;
2190 }
2191
2192 out:
2193 return(error);
2194 }
2195
2196 #if CONFIG_MEMORYSTATUS
2197
2198 int
2199 proc_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;
2206 boolean_t zombref = FALSE;
2207 pid_t selfpid;
2208
2209 target_p = proc_find(pid);
2210
2211 if (target_p == PROC_NULL) {
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
2220 }
2221
2222 my_cred = kauth_cred_get();
2223 target_cred = kauth_cred_proc_ref(target_p);
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
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 }
2243
2244 error = memorystatus_dirty_track(target_p, pcontrol);
2245 }
2246 break;
2247
2248 case PROC_DIRTYCONTROL_SET: {
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
2255 error = memorystatus_dirty_set(target_p, self, pcontrol);
2256 }
2257 break;
2258
2259 case PROC_DIRTYCONTROL_GET: {
2260 /* No permissions check - dirty state is freely available */
2261 if (retval) {
2262 *retval = memorystatus_dirty_get(target_p);
2263 } else {
2264 error = EINVAL;
2265 }
2266 }
2267 break;
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;
2279 }
2280
2281 out:
2282 if (zombref)
2283 proc_drop_zombref(target_p);
2284 else
2285 proc_rele(target_p);
2286
2287 kauth_cred_unref(&target_cred);
2288
2289 return(error);
2290 }
2291 #else
2292
2293 int
2294 proc_dirtycontrol(__unused int pid, __unused int flavor, __unused uint64_t arg, __unused int32_t *retval) {
2295 return ENOTSUP;
2296 }
2297
2298 #endif /* CONFIG_MEMORYSTATUS */
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
2306 int
2307 proc_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 }
2338
2339 /* Not allowed to sudden terminate yourself */
2340 if (p == current_proc()) {
2341 error = EPERM;
2342 goto out;
2343 }
2344
2345 #if CONFIG_MEMORYSTATUS
2346 /* Determine requisite signal to issue */
2347 sig = memorystatus_on_terminate(p);
2348 #else
2349 sig = SIGTERM;
2350 #endif
2351
2352 proc_set_task_policy(p->task, THREAD_NULL, TASK_POLICY_ATTRIBUTE,
2353 TASK_POLICY_TERMINATED, TASK_POLICY_ENABLE);
2354
2355 psignal(p, sig);
2356 *retval = sig;
2357
2358 out:
2359 proc_rele(p);
2360
2361 return error;
2362 }
2363
2364 /*
2365 * copy stat64 structure into vinfo_stat structure.
2366 */
2367 static void
2368 munge_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 }
2395
2396 int
2397 proc_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
2416 out:
2417 if (zombie)
2418 proc_drop_zombref(p);
2419 else
2420 proc_rele(p);
2421
2422 return (error);
2423 }
2424
2425 void
2426 proc_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
2434 void
2435 proc_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 */
2449 int
2450 proc_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