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