]> git.saurik.com Git - apple/xnu.git/blob - bsd/kern/proc_info.c
xnu-1504.15.3.tar.gz
[apple/xnu.git] / bsd / kern / proc_info.c
1 /*
2 * Copyright (c) 2005 Apple Computer, 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
52 #include <security/audit/audit.h>
53
54 #include <mach/machine.h>
55 #include <mach/mach_types.h>
56 #include <mach/vm_param.h>
57 #include <kern/task.h>
58 #include <kern/lock.h>
59 #include <kern/kalloc.h>
60 #include <vm/vm_kern.h>
61 #include <vm/vm_map.h>
62 #include <mach/host_info.h>
63 #include <mach/task_info.h>
64 #include <mach/thread_info.h>
65 #include <mach/vm_region.h>
66
67 #include <sys/mount_internal.h>
68 #include <sys/proc_info.h>
69 #include <sys/bsdtask_info.h>
70 #include <sys/kdebug.h>
71 #include <sys/sysproto.h>
72 #include <sys/msgbuf.h>
73
74 #include <sys/msgbuf.h>
75
76 #include <machine/machine_routines.h>
77
78 #include <vm/vm_protos.h>
79
80 struct pshmnode;
81 struct psemnode;
82 struct pipe;
83 struct kqueue;
84 struct atalk;
85
86 uint64_t get_dispatchqueue_offset_from_proc(void *);
87 int proc_info_internal(int callnum, int pid, int flavor, uint64_t arg, user_addr_t buffer, uint32_t buffersize, int32_t * retval);
88
89 /* protos for proc_info calls */
90 int proc_listpids(uint32_t type, uint32_t tyoneinfo, user_addr_t buffer, uint32_t buffersize, int32_t * retval);
91 int proc_pidinfo(int pid, int flavor, uint64_t arg, user_addr_t buffer, uint32_t buffersize, int32_t * retval);
92 int proc_pidfdinfo(int pid, int flavor,int fd, user_addr_t buffer, uint32_t buffersize, int32_t * retval);
93 int proc_kernmsgbuf(user_addr_t buffer, uint32_t buffersize, int32_t * retval);
94 int proc_setcontrol(int pid, int flavor, uint64_t arg, user_addr_t buffer, uint32_t buffersize, int32_t * retval);
95
96 /* protos for procpidinfo calls */
97 int proc_pidfdlist(proc_t p, user_addr_t buffer, uint32_t buffersize, int32_t *retval);
98 int proc_pidbsdinfo(proc_t p, struct proc_bsdinfo *pbsd, int zombie);
99 int proc_pidtaskinfo(proc_t p, struct proc_taskinfo *ptinfo);
100 int proc_pidallinfo(proc_t p, int flavor, uint64_t arg, user_addr_t buffer, uint32_t buffersize, int32_t *retval);
101 int proc_pidthreadinfo(proc_t p, uint64_t arg, struct proc_threadinfo *pthinfo);
102 int proc_pidthreadpathinfo(proc_t p, uint64_t arg, struct proc_threadwithpathinfo *pinfo);
103 int proc_pidlistthreads(proc_t p, user_addr_t buffer, uint32_t buffersize, int32_t *retval);
104 int proc_pidregioninfo(proc_t p, uint64_t arg, user_addr_t buffer, uint32_t buffersize, int32_t *retval);
105 int proc_pidregionpathinfo(proc_t p, uint64_t arg, user_addr_t buffer, uint32_t buffersize, int32_t *retval);
106 int proc_pidvnodepathinfo(proc_t p, uint64_t arg, user_addr_t buffer, uint32_t buffersize, int32_t *retval);
107 int proc_pidpathinfo(proc_t p, uint64_t arg, user_addr_t buffer, uint32_t buffersize, int32_t *retval);
108 int proc_pidworkqueueinfo(proc_t p, struct proc_workqueueinfo *pwqinfo);
109
110
111 /* protos for proc_pidfdinfo calls */
112 int pid_vnodeinfo(vnode_t vp, uint32_t vid, struct fileproc * fp, int closeonexec, user_addr_t buffer, uint32_t buffersize, int32_t * retval);
113 int pid_vnodeinfopath(vnode_t vp, uint32_t vid, struct fileproc * fp, int closeonexec, user_addr_t buffer, uint32_t buffersize, int32_t * retval);
114 int pid_socketinfo(socket_t so, struct fileproc *fp, int closeonexec, user_addr_t buffer, uint32_t buffersize, int32_t * retval);
115 int pid_pseminfo(struct psemnode * psem, struct fileproc * fp, int closeonexec, user_addr_t buffer, uint32_t buffersize, int32_t * retval);
116 int pid_pshminfo(struct pshmnode * pshm, struct fileproc * fp, int closeonexec, user_addr_t buffer, uint32_t buffersize, int32_t * retval);
117 int pid_pipeinfo(struct pipe * p, struct fileproc * fp, int closeonexec, user_addr_t buffer, uint32_t buffersize, int32_t * retval);
118 int pid_kqueueinfo(struct kqueue * kq, struct fileproc * fp, int closeonexec, user_addr_t buffer, uint32_t buffersize, int32_t * retval);
119 int pid_atalkinfo(struct atalk * at, struct fileproc * fp, int closeonexec, user_addr_t buffer, uint32_t buffersize, int32_t * retval);
120
121
122 /* protos for misc */
123
124 int fill_vnodeinfo(vnode_t vp, struct vnode_info *vinfo);
125 void fill_fileinfo(struct fileproc * fp, int closeonexec, struct proc_fileinfo * finfo);
126 static int proc_security_policy(proc_t p);
127 static void munge_vinfo_stat(struct stat64 *sbp, struct vinfo_stat *vsbp);
128
129 uint64_t get_dispatchqueue_offset_from_proc(void *p)
130 {
131 if(p != NULL) {
132 proc_t pself = (proc_t)p;
133 return (pself->p_dispatchqueue_offset);
134 } else {
135 return (uint64_t)0;
136 }
137 }
138
139 /***************************** proc_info ********************/
140
141 int
142 proc_info(__unused struct proc *p, struct proc_info_args * uap, int32_t *retval)
143 {
144 return(proc_info_internal(uap->callnum, uap->pid, uap->flavor, uap->arg, uap->buffer, uap->buffersize, retval));
145 }
146
147
148 int
149 proc_info_internal(int callnum, int pid, int flavor, uint64_t arg, user_addr_t buffer, uint32_t buffersize, int32_t * retval)
150 {
151
152 switch(callnum) {
153 case 1: /* proc_listpids */
154 /* pid contains type and flavor contains typeinfo */
155 return(proc_listpids(pid, flavor, buffer, buffersize, retval));
156 case 2: /* proc_pidinfo */
157 return(proc_pidinfo(pid, flavor, arg, buffer, buffersize, retval));
158 case 3: /* proc_pidfdinfo */
159 return(proc_pidfdinfo(pid, flavor, (int)arg, buffer, buffersize, retval));
160 case 4: /* proc_kernmsgbuf */
161 return(proc_kernmsgbuf(buffer, buffersize, retval));
162 case 5: /* set on self properties proc_setcontrol */
163 return(proc_setcontrol(pid, flavor, arg, buffer, buffersize, retval));
164
165 default:
166 return(EINVAL);
167 }
168
169 return(EINVAL);
170 }
171
172 /******************* proc_listpids routine ****************/
173 int
174 proc_listpids(uint32_t type, uint32_t typeinfo, user_addr_t buffer, uint32_t buffersize, int32_t * retval)
175 {
176 int numprocs, wantpids;
177 char * kbuf;
178 int * ptr;
179 int n, skip;
180 struct proc * p;
181 struct tty * tp;
182 int error = 0;
183
184 /* if the buffer is null, return num of procs */
185 if (buffer == (user_addr_t)0) {
186 *retval = ((nprocs+20) * sizeof(int));
187 return(0);
188 }
189
190 if (buffersize < sizeof(int)) {
191 return(ENOMEM);
192 }
193 wantpids = buffersize/sizeof(int);
194 numprocs = nprocs+20;
195 if (numprocs > wantpids)
196 numprocs = wantpids;
197
198 kbuf = (char *)kalloc((vm_size_t)(numprocs * sizeof(int)));
199 if (kbuf == NULL)
200 return(ENOMEM);
201 bzero(kbuf, sizeof(int));
202
203 proc_list_lock();
204
205
206 n = 0;
207 ptr = (int *)kbuf;
208 LIST_FOREACH(p, &allproc, p_list) {
209 skip = 0;
210 switch (type) {
211 case PROC_PGRP_ONLY:
212 if (p->p_pgrpid != (pid_t)typeinfo)
213 skip = 1;
214 break;
215 case PROC_ALL_PIDS:
216 skip = 0;
217 break;
218 case PROC_TTY_ONLY:
219 /* racy but list lock is held */
220 if ((p->p_flag & P_CONTROLT) == 0 ||
221 (p->p_pgrp == NULL) || (p->p_pgrp->pg_session == NULL) ||
222 (tp = SESSION_TP(p->p_pgrp->pg_session)) == TTY_NULL ||
223 tp->t_dev != (dev_t)typeinfo)
224 skip = 1;
225 break;
226 case PROC_UID_ONLY:
227 if (p->p_ucred == NULL)
228 skip = 1;
229 else {
230 kauth_cred_t my_cred;
231 uid_t uid;
232
233 my_cred = kauth_cred_proc_ref(p);
234 uid = kauth_cred_getuid(my_cred);
235 kauth_cred_unref(&my_cred);
236 if (uid != (uid_t)typeinfo)
237 skip = 1;
238 }
239 break;
240 case PROC_RUID_ONLY:
241 if (p->p_ucred == NULL)
242 skip = 1;
243 else {
244 kauth_cred_t my_cred;
245 uid_t uid;
246
247 my_cred = kauth_cred_proc_ref(p);
248 uid = my_cred->cr_ruid;
249 kauth_cred_unref(&my_cred);
250 if (uid != (uid_t)typeinfo)
251 skip = 1;
252 }
253 break;
254 default:
255 skip = 1;
256 break;
257 };
258
259 /* Do we have permission to look into this ? */
260 if (proc_security_policy(p) != 0) {
261 skip = 1;
262 }
263
264 if(skip == 0) {
265 *ptr++ = p->p_pid;
266 n++;
267 }
268 if (n >= numprocs)
269 break;
270 }
271
272 if (n < numprocs) {
273 LIST_FOREACH(p, &zombproc, p_list) {
274 *ptr++ = p->p_pid;
275 n++;
276 if (n >= numprocs)
277 break;
278 }
279 }
280
281
282 proc_list_unlock();
283
284 ptr = (int *)kbuf;
285 error = copyout((caddr_t)ptr, buffer, n * sizeof(int));
286 if (error == 0)
287 *retval = (n * sizeof(int));
288 kfree((void *)kbuf, (vm_size_t)(numprocs * sizeof(int)));
289
290 return(error);
291 }
292
293
294 /********************************** proc_pidinfo routines ********************************/
295
296 int
297 proc_pidfdlist(proc_t p, user_addr_t buffer, uint32_t buffersize, int32_t *retval)
298 {
299 int numfds, needfds;
300 char * kbuf;
301 struct proc_fdinfo * pfd;
302 struct fileproc * fp;
303 int n;
304 int count = 0;
305 int error = 0;
306
307 numfds = p->p_fd->fd_nfiles;
308
309 if (buffer == (user_addr_t) 0) {
310 numfds += 20;
311 *retval = (numfds * sizeof(struct proc_fdinfo));
312 return(0);
313 }
314
315 /* buffersize is big enough atleast for one struct */
316 needfds = buffersize/sizeof(struct proc_fdinfo);
317
318 if (numfds > needfds)
319 numfds = needfds;
320
321 kbuf = (char *)kalloc((vm_size_t)(numfds * sizeof(struct proc_fdinfo)));
322 if (kbuf == NULL)
323 return(ENOMEM);
324 bzero(kbuf, numfds * sizeof(struct proc_fdinfo));
325
326 proc_fdlock(p);
327
328 pfd = (struct proc_fdinfo *)kbuf;
329
330 for (n = 0; ((n < numfds) && (n < p->p_fd->fd_nfiles)); n++) {
331 if (((fp = p->p_fd->fd_ofiles[n]) != 0)
332 && ((p->p_fd->fd_ofileflags[n] & UF_RESERVED) == 0)) {
333 pfd->proc_fd = n;
334 pfd->proc_fdtype = fp->f_fglob->fg_type;
335 count++;
336 pfd++;
337 }
338 }
339 proc_fdunlock(p);
340
341 error = copyout(kbuf, buffer, count * sizeof(struct proc_fdinfo));
342 kfree((void *)kbuf, (vm_size_t)(numfds * sizeof(struct proc_fdinfo)));
343 if (error == 0)
344 *retval = (count * sizeof(struct proc_fdinfo));
345 return(error);
346 }
347
348
349 int
350 proc_pidbsdinfo(proc_t p, struct proc_bsdinfo * pbsd, int zombie)
351 {
352 register struct tty *tp;
353 struct session *sessionp = NULL;
354 struct pgrp * pg;
355 kauth_cred_t my_cred;
356
357 pg = proc_pgrp(p);
358 sessionp = proc_session(p);
359
360 my_cred = kauth_cred_proc_ref(p);
361 bzero(pbsd, sizeof(struct proc_bsdinfo));
362 pbsd->pbi_status = p->p_stat;
363 pbsd->pbi_xstatus = p->p_xstat;
364 pbsd->pbi_pid = p->p_pid;
365 pbsd->pbi_ppid = p->p_ppid;
366 pbsd->pbi_uid = my_cred->cr_uid;
367 pbsd->pbi_gid = my_cred->cr_gid;
368 pbsd->pbi_ruid = my_cred->cr_ruid;
369 pbsd->pbi_rgid = my_cred->cr_rgid;
370 pbsd->pbi_svuid = my_cred->cr_svuid;
371 pbsd->pbi_svgid = my_cred->cr_svgid;
372 kauth_cred_unref(&my_cred);
373
374 pbsd->pbi_nice = p->p_nice;
375 pbsd->pbi_start_tvsec = p->p_start.tv_sec;
376 pbsd->pbi_start_tvusec = p->p_start.tv_usec;
377 bcopy(&p->p_comm, &pbsd->pbi_comm[0], MAXCOMLEN-1);
378 bcopy(&p->p_name, &pbsd->pbi_name[0], 2*MAXCOMLEN-1);
379
380 pbsd->pbi_flags = 0;
381 if ((p->p_flag & P_SYSTEM) == P_SYSTEM)
382 pbsd->pbi_flags |= PROC_FLAG_SYSTEM;
383 if ((p->p_lflag & P_LTRACED) == P_LTRACED)
384 pbsd->pbi_flags |= PROC_FLAG_TRACED;
385 if ((p->p_lflag & P_LEXIT) == P_LEXIT)
386 pbsd->pbi_flags |= PROC_FLAG_INEXIT;
387 if ((p->p_lflag & P_LPPWAIT) == P_LPPWAIT)
388 pbsd->pbi_flags |= PROC_FLAG_PPWAIT;
389 if ((p->p_flag & P_LP64) == P_LP64)
390 pbsd->pbi_flags |= PROC_FLAG_LP64;
391 if ((p->p_flag & P_CONTROLT) == P_CONTROLT)
392 pbsd->pbi_flags |= PROC_FLAG_CONTROLT;
393 if ((p->p_flag & P_THCWD) == P_THCWD)
394 pbsd->pbi_flags |= PROC_FLAG_THCWD;
395
396 if (sessionp != SESSION_NULL) {
397 if (SESS_LEADER(p, sessionp))
398 pbsd->pbi_flags |= PROC_FLAG_SLEADER;
399 if (sessionp->s_ttyvp)
400 pbsd->pbi_flags |= PROC_FLAG_CTTY;
401 }
402
403
404 switch(PROC_CONTROL_STATE(p)) {
405 case P_PCTHROTTLE:
406 pbsd->pbi_flags |= PROC_FLAG_PC_THROTTLE;
407 break;
408 case P_PCSUSP:
409 pbsd->pbi_flags |= PROC_FLAG_PC_SUSP;
410 break;
411 case P_PCKILL:
412 pbsd->pbi_flags |= PROC_FLAG_PC_KILL;
413 break;
414 };
415
416 switch(PROC_ACTION_STATE(p)) {
417 case P_PCTHROTTLE:
418 pbsd->pbi_flags |= PROC_FLAG_PA_THROTTLE;
419 break;
420 case P_PCSUSP:
421 pbsd->pbi_flags |= PROC_FLAG_PA_SUSP;
422 break;
423 };
424
425 if (zombie == 0)
426 pbsd->pbi_nfiles = p->p_fd->fd_nfiles;
427 if (pg != PGRP_NULL) {
428 pbsd->pbi_pgid = p->p_pgrpid;
429 pbsd->pbi_pjobc = pg->pg_jobc;
430 if ((p->p_flag & P_CONTROLT) && (sessionp != SESSION_NULL) && (tp = SESSION_TP(sessionp))) {
431 pbsd->e_tdev = tp->t_dev;
432 pbsd->e_tpgid = sessionp->s_ttypgrpid;
433 }
434 }
435 if (sessionp != SESSION_NULL)
436 session_rele(sessionp);
437 if (pg != PGRP_NULL)
438 pg_rele(pg);
439
440 return(0);
441 }
442
443
444 int
445 proc_pidtaskinfo(proc_t p, struct proc_taskinfo * ptinfo)
446 {
447 task_t task;
448
449 task = p->task;
450
451 bzero(ptinfo, sizeof(struct proc_taskinfo));
452 fill_taskprocinfo(task, (struct proc_taskinfo_internal *)ptinfo);
453
454 return(0);
455 }
456
457
458
459 int
460 proc_pidthreadinfo(proc_t p, uint64_t arg, struct proc_threadinfo *pthinfo)
461 {
462 int error = 0;
463 uint64_t threadaddr = (uint64_t)arg;
464
465 bzero(pthinfo, sizeof(struct proc_threadinfo));
466
467 error = fill_taskthreadinfo(p->task, threadaddr, (struct proc_threadinfo_internal *)pthinfo, NULL, NULL);
468 if (error)
469 return(ESRCH);
470 else
471 return(0);
472
473 }
474
475 void
476 bsd_getthreadname(void *uth, char *buffer)
477 {
478 struct uthread *ut = (struct uthread *)uth;
479 if(ut->pth_name)
480 bcopy(ut->pth_name,buffer,MAXTHREADNAMESIZE);
481 }
482
483 void
484 bsd_threadcdir(void * uth, void *vptr, int *vidp)
485 {
486 struct uthread * ut = (struct uthread *)uth;
487 vnode_t vp;
488 vnode_t *vpp = (vnode_t *)vptr;
489
490 vp = ut->uu_cdir;
491 if (vp != NULLVP) {
492 if (vpp != NULL) {
493 *vpp = vp;
494 if (vidp != NULL)
495 *vidp = vp->v_id;
496 }
497 }
498 }
499
500
501 int
502 proc_pidthreadpathinfo(proc_t p, uint64_t arg, struct proc_threadwithpathinfo *pinfo)
503 {
504 vnode_t vp = NULLVP;
505 int vid;
506 int error = 0;
507 uint64_t threadaddr = (uint64_t)arg;
508 int count;
509
510 bzero(pinfo, sizeof(struct proc_threadwithpathinfo));
511
512 error = fill_taskthreadinfo(p->task, threadaddr, (struct proc_threadinfo_internal *)&pinfo->pt, (void *)&vp, &vid);
513 if (error)
514 return(ESRCH);
515
516 if ((vp != NULLVP) && ((vnode_getwithvid(vp, vid)) == 0)) {
517 error = fill_vnodeinfo(vp, &pinfo->pvip.vip_vi) ;
518 if (error == 0) {
519 count = MAXPATHLEN;
520 vn_getpath(vp, &pinfo->pvip.vip_path[0], &count);
521 pinfo->pvip.vip_path[MAXPATHLEN-1] = 0;
522 }
523 vnode_put(vp);
524 }
525 return(error);
526 }
527
528
529
530 int
531 proc_pidlistthreads(proc_t p, user_addr_t buffer, uint32_t buffersize, int32_t *retval)
532 {
533 int count = 0;
534 int ret = 0;
535 int error = 0;
536 void * kbuf;
537 int numthreads;
538
539
540 count = buffersize/(sizeof(uint64_t));
541 numthreads = get_numthreads(p->task);
542
543 numthreads += 10;
544
545 if (numthreads > count)
546 numthreads = count;
547
548 kbuf = (void *)kalloc(numthreads * sizeof(uint64_t));
549 if (kbuf == NULL)
550 return(ENOMEM);
551 bzero(kbuf, numthreads * sizeof(uint64_t));
552
553 ret = fill_taskthreadlist(p->task, kbuf, numthreads);
554
555 error = copyout(kbuf, buffer, ret);
556 kfree(kbuf, numthreads * sizeof(uint64_t));
557 if (error == 0)
558 *retval = ret;
559 return(error);
560
561 }
562
563
564 int
565 proc_pidregioninfo(proc_t p, uint64_t arg, user_addr_t buffer, __unused uint32_t buffersize, int32_t *retval)
566 {
567 struct proc_regioninfo preginfo;
568 int ret, error = 0;
569
570 bzero(&preginfo, sizeof(struct proc_regioninfo));
571 ret = fill_procregioninfo( p->task, arg, (struct proc_regioninfo_internal *)&preginfo, (uintptr_t *)0, (uint32_t *)0);
572 if (ret == 0)
573 return(EINVAL);
574 error = copyout(&preginfo, buffer, sizeof(struct proc_regioninfo));
575 if (error == 0)
576 *retval = sizeof(struct proc_regioninfo);
577 return(error);
578 }
579
580
581 int
582 proc_pidregionpathinfo(proc_t p, uint64_t arg, user_addr_t buffer, __unused uint32_t buffersize, int32_t *retval)
583 {
584 struct proc_regionwithpathinfo preginfo;
585 int ret, error = 0;
586 uintptr_t vnodeaddr= 0;
587 uint32_t vnodeid= 0;
588 vnode_t vp;
589 int count;
590
591 bzero(&preginfo, sizeof(struct proc_regionwithpathinfo));
592
593 ret = fill_procregioninfo( p->task, arg, (struct proc_regioninfo_internal *)&preginfo.prp_prinfo, (uintptr_t *)&vnodeaddr, (uint32_t *)&vnodeid);
594 if (ret == 0)
595 return(EINVAL);
596 if (vnodeaddr) {
597 vp = (vnode_t)vnodeaddr;
598 if ((vnode_getwithvid(vp, vnodeid)) == 0) {
599 /* FILL THE VNODEINFO */
600 error = fill_vnodeinfo(vp, &preginfo.prp_vip.vip_vi);
601 count = MAXPATHLEN;
602 vn_getpath(vp, &preginfo.prp_vip.vip_path[0], &count);
603 /* Always make sure it is null terminated */
604 preginfo.prp_vip.vip_path[MAXPATHLEN-1] = 0;
605 vnode_put(vp);
606 }
607 }
608 error = copyout(&preginfo, buffer, sizeof(struct proc_regionwithpathinfo));
609 if (error == 0)
610 *retval = sizeof(struct proc_regionwithpathinfo);
611 return(error);
612 }
613
614 /*
615 * Path is relative to current process directory; may different from current
616 * thread directory.
617 */
618 int
619 proc_pidvnodepathinfo(proc_t p, __unused uint64_t arg, user_addr_t buffer, __unused uint32_t buffersize, int32_t *retval)
620 {
621 struct proc_vnodepathinfo pvninfo;
622 int error = 0;
623 vnode_t vncdirvp = NULLVP;
624 uint32_t vncdirid=0;
625 vnode_t vnrdirvp = NULLVP;
626 uint32_t vnrdirid=0;
627 int count;
628
629 bzero(&pvninfo, sizeof(struct proc_vnodepathinfo));
630
631 proc_fdlock(p);
632 if (p->p_fd->fd_cdir) {
633 vncdirvp = p->p_fd->fd_cdir;
634 vncdirid = p->p_fd->fd_cdir->v_id;
635 }
636 if (p->p_fd->fd_rdir) {
637 vnrdirvp = p->p_fd->fd_rdir;
638 vnrdirid = p->p_fd->fd_rdir->v_id;
639 }
640 proc_fdunlock(p);
641
642 if (vncdirvp != NULLVP) {
643 if ((error = vnode_getwithvid(vncdirvp, vncdirid)) == 0) {
644 /* FILL THE VNODEINFO */
645 error = fill_vnodeinfo(vncdirvp, &pvninfo.pvi_cdir.vip_vi);
646 if ( error == 0) {
647 count = MAXPATHLEN;
648 vn_getpath(vncdirvp, &pvninfo.pvi_cdir.vip_path[0], &count);
649 pvninfo.pvi_cdir.vip_path[MAXPATHLEN-1] = 0;
650 }
651 vnode_put(vncdirvp);
652 } else {
653 goto out;
654 }
655 }
656
657 if ((error == 0) && (vnrdirvp != NULLVP)) {
658 if ((error = vnode_getwithvid(vnrdirvp, vnrdirid)) == 0) {
659 /* FILL THE VNODEINFO */
660 error = fill_vnodeinfo(vnrdirvp, &pvninfo.pvi_rdir.vip_vi);
661 if ( error == 0) {
662 count = MAXPATHLEN;
663 vn_getpath(vnrdirvp, &pvninfo.pvi_rdir.vip_path[0], &count);
664 pvninfo.pvi_rdir.vip_path[MAXPATHLEN-1] = 0;
665 }
666 vnode_put(vnrdirvp);
667 } else {
668 goto out;
669 }
670 }
671 if (error == 0) {
672 error = copyout(&pvninfo, buffer, sizeof(struct proc_vnodepathinfo));
673 if (error == 0)
674 *retval = sizeof(struct proc_vnodepathinfo);
675 }
676 out:
677 return(error);
678 }
679
680 int
681 proc_pidpathinfo(proc_t p, __unused uint64_t arg, user_addr_t buffer, uint32_t buffersize, __unused int32_t *retval)
682 {
683 int vid, error;
684 vnode_t tvp;
685 vnode_t nvp = NULLVP;
686 int len = buffersize;
687 char * buf;
688
689 tvp = p->p_textvp;
690
691 if (tvp == NULLVP)
692 return(ESRCH);
693
694 buf = (char *)kalloc(buffersize);
695 if (buf == NULL)
696 return(ENOMEM);
697
698
699 vid = vnode_vid(tvp);
700 error = vnode_getwithvid(tvp, vid);
701 if (error == 0) {
702 error = vn_getpath_fsenter(tvp, buf, &len);
703 vnode_put(tvp);
704 if (error == 0) {
705 error = vnode_lookup(buf, 0, &nvp, vfs_context_current());
706 if ((error == 0) && ( nvp != NULLVP))
707 vnode_put(nvp);
708 if (error == 0) {
709 error = copyout(buf, buffer, len);
710 }
711 }
712 }
713 kfree(buf, buffersize);
714 return(error);
715 }
716
717
718 int
719 proc_pidworkqueueinfo(proc_t p, struct proc_workqueueinfo *pwqinfo)
720 {
721 int error = 0;
722
723 bzero(pwqinfo, sizeof(struct proc_workqueueinfo));
724
725 error = fill_procworkqueue(p, pwqinfo);
726 if (error)
727 return(ESRCH);
728 else
729 return(0);
730
731 }
732 /********************************** proc_pidinfo ********************************/
733
734
735 int
736 proc_pidinfo(int pid, int flavor, uint64_t arg, user_addr_t buffer, uint32_t buffersize, int32_t * retval)
737 {
738 struct proc * p = PROC_NULL;
739 int error = ENOTSUP;
740 int gotref = 0;
741 int findzomb = 0;
742 int refheld = 0;
743 uint32_t size;
744 int zombie = 0;
745
746 switch (flavor) {
747 case PROC_PIDLISTFDS:
748 size = PROC_PIDLISTFD_SIZE;
749 if (buffer == (user_addr_t)0)
750 size = 0;
751 break;
752 case PROC_PIDTBSDINFO:
753 size = PROC_PIDTBSDINFO_SIZE;
754 break;
755 case PROC_PIDTASKINFO:
756 size = PROC_PIDTASKINFO_SIZE;
757 break;
758 case PROC_PIDTASKALLINFO:
759 size = PROC_PIDTASKALLINFO_SIZE;
760 break;
761 case PROC_PIDTHREADINFO:
762 size = PROC_PIDTHREADINFO_SIZE;
763 break;
764 case PROC_PIDLISTTHREADS:
765 size = PROC_PIDLISTTHREADS_SIZE;
766 break;
767 case PROC_PIDREGIONINFO:
768 size = PROC_PIDREGIONINFO_SIZE;
769 break;
770 case PROC_PIDREGIONPATHINFO:
771 size = PROC_PIDREGIONPATHINFO_SIZE;
772 break;
773 case PROC_PIDVNODEPATHINFO:
774 size = PROC_PIDVNODEPATHINFO_SIZE;
775 break;
776 case PROC_PIDTHREADPATHINFO:
777 size = PROC_PIDTHREADPATHINFO_SIZE;
778 break;
779 case PROC_PIDPATHINFO:
780 size = MAXPATHLEN;
781 break;
782 case PROC_PIDWORKQUEUEINFO:
783 /* kernel does not have workq info */
784 if (pid == 0)
785 return(EINVAL);
786 else
787 size = PROC_PIDWORKQUEUEINFO_SIZE;
788 break;
789 default:
790 return(EINVAL);
791 }
792
793 if (buffersize < size)
794 return(ENOMEM);
795
796 if ((flavor == PROC_PIDPATHINFO) && (buffersize > PROC_PIDPATHINFO_MAXSIZE)) {
797 return(EOVERFLOW);
798 }
799
800 if ((flavor != PROC_PIDTBSDINFO) && (flavor != PROC_PIDPATHINFO)) {
801 if ((p = proc_find(pid)) == PROC_NULL) {
802 error = ESRCH;
803 goto out;
804 } else {
805 gotref = 1;
806
807 /* Do we have permission to look into this ? */
808 if ((error = proc_security_policy(p)) != 0) {
809 goto out;
810 }
811 }
812 }
813 switch (flavor) {
814 case PROC_PIDLISTFDS: {
815 error = proc_pidfdlist(p, buffer, buffersize, retval);
816 }
817 break;
818
819 case PROC_PIDTBSDINFO: {
820 struct proc_bsdinfo pbsd;
821
822 zombie = 0;
823 if (arg)
824 findzomb = 1;
825 p = proc_find(pid);
826 if (p == PROC_NULL) {
827 if (findzomb)
828 p = pzfind(pid);
829 if (p == NULL) {
830 error = ESRCH;
831 goto out;
832 }
833 zombie = 1;
834 } else
835 refheld = 1;
836 /* Do we have permission to look into this ? */
837 if ((error = proc_security_policy(p)) != 0) {
838 if (refheld != 0)
839 proc_rele(p);
840 goto out;
841 }
842 error = proc_pidbsdinfo(p, &pbsd, zombie);
843 if (refheld != 0)
844 proc_rele(p);
845 if (error == 0) {
846 error = copyout(&pbsd, buffer, sizeof(struct proc_bsdinfo));
847 if (error == 0)
848 *retval = sizeof(struct proc_bsdinfo);
849 }
850 }
851 break;
852
853 case PROC_PIDTASKINFO: {
854 struct proc_taskinfo ptinfo;
855
856 error = proc_pidtaskinfo(p, &ptinfo);
857 if (error == 0) {
858 error = copyout(&ptinfo, buffer, sizeof(struct proc_taskinfo));
859 if (error == 0)
860 *retval = sizeof(struct proc_taskinfo);
861 }
862 }
863 break;
864
865 case PROC_PIDTASKALLINFO: {
866 struct proc_taskallinfo pall;
867
868 error = proc_pidbsdinfo(p, &pall.pbsd, 0);
869 error = proc_pidtaskinfo(p, &pall.ptinfo);
870 if (error == 0) {
871 error = copyout(&pall, buffer, sizeof(struct proc_taskallinfo));
872 if (error == 0)
873 *retval = sizeof(struct proc_taskallinfo);
874 }
875 }
876 break;
877
878 case PROC_PIDTHREADINFO:{
879 struct proc_threadinfo pthinfo;
880
881 error = proc_pidthreadinfo(p, arg, &pthinfo);
882 if (error == 0) {
883 error = copyout(&pthinfo, buffer, sizeof(struct proc_threadinfo));
884 if (error == 0)
885 *retval = sizeof(struct proc_threadinfo);
886 }
887 }
888 break;
889
890 case PROC_PIDLISTTHREADS:{
891 error = proc_pidlistthreads(p, buffer, buffersize, retval);
892 }
893 break;
894
895 case PROC_PIDREGIONINFO:{
896 error = proc_pidregioninfo(p, arg, buffer, buffersize, retval);
897 }
898 break;
899
900
901 case PROC_PIDREGIONPATHINFO:{
902 error = proc_pidregionpathinfo(p, arg, buffer, buffersize, retval);
903 }
904 break;
905
906 case PROC_PIDVNODEPATHINFO:{
907 error = proc_pidvnodepathinfo(p, arg, buffer, buffersize, retval);
908 }
909 break;
910
911
912 case PROC_PIDTHREADPATHINFO:{
913 struct proc_threadwithpathinfo pinfo;
914
915 error = proc_pidthreadpathinfo(p, arg, &pinfo);
916 if (error == 0) {
917 error = copyout((caddr_t)&pinfo, buffer, sizeof(struct proc_threadwithpathinfo));
918 if (error == 0)
919 *retval = sizeof(struct proc_threadwithpathinfo);
920 }
921 }
922 break;
923
924 case PROC_PIDPATHINFO: {
925 p = proc_find(pid);
926 if (p == PROC_NULL) {
927 error = ESRCH;
928 goto out;
929 }
930 gotref = 1;
931 error = proc_pidpathinfo(p, arg, buffer, buffersize, retval);
932 }
933 break;
934
935
936 case PROC_PIDWORKQUEUEINFO:{
937 struct proc_workqueueinfo pwqinfo;
938
939 error = proc_pidworkqueueinfo(p, &pwqinfo);
940 if (error == 0) {
941 error = copyout(&pwqinfo, buffer, sizeof(struct proc_workqueueinfo));
942 if (error == 0)
943 *retval = sizeof(struct proc_workqueueinfo);
944 }
945 }
946 break;
947
948 default:
949 error = ENOTSUP;
950 }
951
952 out:
953 if (gotref)
954 proc_rele(p);
955 return(error);
956 }
957
958
959 int
960 pid_vnodeinfo(vnode_t vp, uint32_t vid, struct fileproc * fp, int closeonexec, user_addr_t buffer, __unused uint32_t buffersize, int32_t * retval)
961 {
962 struct vnode_fdinfo vfi;
963 int error= 0;
964
965 if ((error = vnode_getwithvid(vp, vid)) != 0) {
966 return(error);
967 }
968 bzero(&vfi, sizeof(struct vnode_fdinfo));
969 fill_fileinfo(fp, closeonexec, &vfi.pfi);
970 error = fill_vnodeinfo(vp, &vfi.pvi);
971 vnode_put(vp);
972 if (error == 0) {
973 error = copyout((caddr_t)&vfi, buffer, sizeof(struct vnode_fdinfo));
974 if (error == 0)
975 *retval = sizeof(struct vnode_fdinfo);
976 }
977 return(error);
978 }
979
980 int
981 pid_vnodeinfopath(vnode_t vp, uint32_t vid, struct fileproc * fp, int closeonexec, user_addr_t buffer, __unused uint32_t buffersize, int32_t * retval)
982 {
983 struct vnode_fdinfowithpath vfip;
984 int count, error= 0;
985
986 if ((error = vnode_getwithvid(vp, vid)) != 0) {
987 return(error);
988 }
989 bzero(&vfip, sizeof(struct vnode_fdinfowithpath));
990 fill_fileinfo(fp, closeonexec, &vfip.pfi);
991 error = fill_vnodeinfo(vp, &vfip.pvip.vip_vi) ;
992 if (error == 0) {
993 count = MAXPATHLEN;
994 vn_getpath(vp, &vfip.pvip.vip_path[0], &count);
995 vfip.pvip.vip_path[MAXPATHLEN-1] = 0;
996 vnode_put(vp);
997 error = copyout((caddr_t)&vfip, buffer, sizeof(struct vnode_fdinfowithpath));
998 if (error == 0)
999 *retval = sizeof(struct vnode_fdinfowithpath);
1000 } else
1001 vnode_put(vp);
1002 return(error);
1003 }
1004
1005 void
1006 fill_fileinfo(struct fileproc * fp, int closeonexec, struct proc_fileinfo * fproc)
1007 {
1008 fproc->fi_openflags = fp->f_fglob->fg_flag;
1009 fproc->fi_status = 0;
1010 fproc->fi_offset = fp->f_fglob->fg_offset;
1011 fproc->fi_type = fp->f_fglob->fg_type;
1012 if (fp->f_fglob->fg_count)
1013 fproc->fi_status |= PROC_FP_SHARED;
1014 if (closeonexec != 0)
1015 fproc->fi_status |= PROC_FP_CLEXEC;
1016 }
1017
1018
1019
1020 int
1021 fill_vnodeinfo(vnode_t vp, struct vnode_info *vinfo)
1022 {
1023 vfs_context_t context;
1024 struct stat64 sb;
1025 int error = 0;
1026
1027 context = vfs_context_create((vfs_context_t)0);
1028 error = vn_stat(vp, &sb, NULL, 1, context);
1029 (void)vfs_context_rele(context);
1030
1031 munge_vinfo_stat(&sb, &vinfo->vi_stat);
1032
1033 if (error != 0)
1034 goto out;
1035
1036 if (vp->v_mount != dead_mountp) {
1037 vinfo->vi_fsid = vp->v_mount->mnt_vfsstat.f_fsid;
1038 } else {
1039 vinfo->vi_fsid.val[0] = 0;
1040 vinfo->vi_fsid.val[1] = 0;
1041 }
1042 vinfo->vi_type = vp->v_type;
1043 out:
1044 return(error);
1045 }
1046
1047 int
1048 pid_socketinfo(socket_t so, struct fileproc *fp, int closeonexec, user_addr_t buffer, __unused uint32_t buffersize, int32_t * retval)
1049 {
1050 #if SOCKETS
1051 struct socket_fdinfo s;
1052 int error = 0;
1053
1054 bzero(&s, sizeof(struct socket_fdinfo));
1055 fill_fileinfo(fp, closeonexec, &s.pfi);
1056 if ((error = fill_socketinfo(so, &s.psi)) == 0) {
1057 if ((error = copyout(&s, buffer, sizeof(struct socket_fdinfo))) == 0)
1058 *retval = sizeof(struct socket_fdinfo);
1059 }
1060 return (error);
1061 #else
1062 *retval = 0;
1063 return (ENOTSUP);
1064 #endif
1065 }
1066
1067 int
1068 pid_pseminfo(struct psemnode *psem, struct fileproc *fp, int closeonexec, user_addr_t buffer, __unused uint32_t buffersize, int32_t * retval)
1069 {
1070 struct psem_fdinfo pseminfo;
1071 int error = 0;
1072
1073 bzero(&pseminfo, sizeof(struct psem_fdinfo));
1074 fill_fileinfo(fp, closeonexec, &pseminfo.pfi);
1075
1076 if ((error = fill_pseminfo(psem, &pseminfo.pseminfo)) == 0) {
1077 if ((error = copyout(&pseminfo, buffer, sizeof(struct psem_fdinfo))) == 0)
1078 *retval = sizeof(struct psem_fdinfo);
1079 }
1080
1081 return(error);
1082 }
1083
1084 int
1085 pid_pshminfo(struct pshmnode *pshm, struct fileproc *fp, int closeonexec, user_addr_t buffer, __unused uint32_t buffersize, int32_t * retval)
1086 {
1087 struct pshm_fdinfo pshminfo;
1088 int error = 0;
1089
1090 bzero(&pshminfo, sizeof(struct pshm_fdinfo));
1091 fill_fileinfo(fp, closeonexec, &pshminfo.pfi);
1092
1093 if ((error = fill_pshminfo(pshm, &pshminfo.pshminfo)) == 0) {
1094 if ((error = copyout(&pshminfo, buffer, sizeof(struct pshm_fdinfo))) == 0)
1095 *retval = sizeof(struct pshm_fdinfo);
1096 }
1097
1098 return(error);
1099 }
1100
1101 int
1102 pid_pipeinfo(struct pipe * p, struct fileproc *fp, int closeonexec, user_addr_t buffer, __unused uint32_t buffersize, int32_t * retval)
1103 {
1104 struct pipe_fdinfo pipeinfo;
1105 int error = 0;
1106
1107 bzero(&pipeinfo, sizeof(struct pipe_fdinfo));
1108 fill_fileinfo(fp, closeonexec, &pipeinfo.pfi);
1109 if ((error = fill_pipeinfo(p, &pipeinfo.pipeinfo)) == 0) {
1110 if ((error = copyout(&pipeinfo, buffer, sizeof(struct pipe_fdinfo))) == 0)
1111 *retval = sizeof(struct pipe_fdinfo);
1112 }
1113
1114 return(error);
1115 }
1116
1117 int
1118 pid_kqueueinfo(struct kqueue * kq, struct fileproc *fp, int closeonexec, user_addr_t buffer, __unused uint32_t buffersize, int32_t * retval)
1119 {
1120 struct kqueue_fdinfo kqinfo;
1121 int error = 0;
1122
1123 bzero(&kqinfo, sizeof(struct kqueue_fdinfo));
1124
1125 fill_fileinfo(fp, closeonexec, &kqinfo.pfi);
1126
1127 if ((error = fill_kqueueinfo(kq, &kqinfo.kqueueinfo)) == 0) {
1128 if ((error = copyout(&kqinfo, buffer, sizeof(struct kqueue_fdinfo))) == 0)
1129 *retval = sizeof(struct kqueue_fdinfo);
1130 }
1131
1132 return(error);
1133 }
1134
1135 int
1136 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)
1137 {
1138 return ENOTSUP;
1139 }
1140
1141
1142
1143 /************************** proc_pidfdinfo routine ***************************/
1144 int
1145 proc_pidfdinfo(int pid, int flavor, int fd, user_addr_t buffer, uint32_t buffersize, int32_t * retval)
1146 {
1147 proc_t p;
1148 int error = ENOTSUP;
1149 struct fileproc * fp;
1150 uint32_t size;
1151 int closeonexec = 0;
1152
1153 switch (flavor) {
1154 case PROC_PIDFDVNODEINFO:
1155 size = PROC_PIDFDVNODEINFO_SIZE;
1156 break;
1157 case PROC_PIDFDVNODEPATHINFO:
1158 size = PROC_PIDFDVNODEPATHINFO_SIZE;
1159 break;
1160 case PROC_PIDFDSOCKETINFO:
1161 size = PROC_PIDFDSOCKETINFO_SIZE;
1162 break;
1163 case PROC_PIDFDPSEMINFO:
1164 size = PROC_PIDFDPSEMINFO_SIZE;
1165 break;
1166 case PROC_PIDFDPSHMINFO:
1167 size = PROC_PIDFDPSHMINFO_SIZE;
1168 break;
1169 case PROC_PIDFDPIPEINFO:
1170 size = PROC_PIDFDPIPEINFO_SIZE;
1171 break;
1172 case PROC_PIDFDKQUEUEINFO:
1173 size = PROC_PIDFDKQUEUEINFO_SIZE;
1174 break;
1175 case PROC_PIDFDATALKINFO:
1176 size = PROC_PIDFDATALKINFO_SIZE;
1177 break;
1178
1179 default:
1180 return(EINVAL);
1181
1182 }
1183
1184 if (buffersize < size)
1185 return(ENOMEM);
1186
1187 if ((p = proc_find(pid)) == PROC_NULL) {
1188 error = ESRCH;
1189 goto out;
1190 }
1191 /* Do we have permission to look into this ? */
1192 if ((error = proc_security_policy(p)) != 0) {
1193 goto out1;
1194 }
1195
1196 switch (flavor) {
1197 case PROC_PIDFDVNODEINFO: {
1198 vnode_t vp;
1199 uint32_t vid=0;
1200
1201 if ((error = fp_getfvpandvid(p, fd, &fp, &vp, &vid)) !=0) {
1202 goto out1;
1203 }
1204 /* no need to be under the fdlock */
1205 closeonexec = p->p_fd->fd_ofileflags[fd] & UF_EXCLOSE;
1206 error = pid_vnodeinfo(vp, vid, fp, closeonexec, buffer, buffersize, retval);
1207 }
1208 break;
1209
1210 case PROC_PIDFDVNODEPATHINFO: {
1211 vnode_t vp;
1212 uint32_t vid=0;
1213
1214 if ((error = fp_getfvpandvid(p, fd, &fp, &vp, &vid)) !=0) {
1215 goto out1;
1216 }
1217
1218 /* no need to be under the fdlock */
1219 closeonexec = p->p_fd->fd_ofileflags[fd] & UF_EXCLOSE;
1220 error = pid_vnodeinfopath(vp, vid, fp, closeonexec, buffer, buffersize, retval);
1221 }
1222 break;
1223
1224 case PROC_PIDFDSOCKETINFO: {
1225 socket_t so;
1226
1227 if ((error = fp_getfsock(p, fd, &fp, &so)) !=0) {
1228 goto out1;
1229 }
1230 /* no need to be under the fdlock */
1231 closeonexec = p->p_fd->fd_ofileflags[fd] & UF_EXCLOSE;
1232 error = pid_socketinfo(so, fp, closeonexec, buffer, buffersize, retval);
1233 }
1234 break;
1235
1236 case PROC_PIDFDPSEMINFO: {
1237 struct psemnode * psem;
1238
1239 if ((error = fp_getfpsem(p, fd, &fp, &psem)) !=0) {
1240 goto out1;
1241 }
1242 /* no need to be under the fdlock */
1243 closeonexec = p->p_fd->fd_ofileflags[fd] & UF_EXCLOSE;
1244 error = pid_pseminfo(psem, fp, closeonexec, buffer, buffersize, retval);
1245 }
1246 break;
1247
1248 case PROC_PIDFDPSHMINFO: {
1249 struct pshmnode * pshm;
1250
1251 if ((error = fp_getfpshm(p, fd, &fp, &pshm)) !=0) {
1252 goto out1;
1253 }
1254 /* no need to be under the fdlock */
1255 closeonexec = p->p_fd->fd_ofileflags[fd] & UF_EXCLOSE;
1256 error = pid_pshminfo(pshm, fp, closeonexec, buffer, buffersize, retval);
1257 }
1258 break;
1259
1260 case PROC_PIDFDPIPEINFO: {
1261 struct pipe * cpipe;
1262
1263 if ((error = fp_getfpipe(p, fd, &fp, &cpipe)) !=0) {
1264 goto out1;
1265 }
1266 /* no need to be under the fdlock */
1267 closeonexec = p->p_fd->fd_ofileflags[fd] & UF_EXCLOSE;
1268 error = pid_pipeinfo(cpipe, fp, closeonexec, buffer, buffersize, retval);
1269 }
1270 break;
1271
1272 case PROC_PIDFDKQUEUEINFO: {
1273 struct kqueue * kq;
1274
1275 if ((error = fp_getfkq(p, fd, &fp, &kq)) !=0) {
1276 goto out1;
1277 }
1278 /* no need to be under the fdlock */
1279 closeonexec = p->p_fd->fd_ofileflags[fd] & UF_EXCLOSE;
1280 error = pid_kqueueinfo(kq, fp, closeonexec, buffer, buffersize, retval);
1281 }
1282 break;
1283
1284 #if NETAT
1285 case PROC_PIDFDATALKINFO: {
1286 struct atalk * at;
1287
1288 if ((error = fp_getfatalk(p, fd, &fp, &at)) !=0) {
1289 goto out1;
1290 }
1291
1292 /* no need to be under the fdlock */
1293 closeonexec = p->p_fd->fd_ofileflags[fd] & UF_EXCLOSE;
1294 error = pid_atalkinfo(at, fp, closeonexec, buffer, buffersize, retval);
1295 }
1296 break;
1297 #endif /* NETAT */
1298 default: {
1299 error = EINVAL;
1300 }
1301 break;
1302
1303 }
1304
1305 fp_drop(p, fd, fp , 0);
1306 out1 :
1307 proc_rele(p);
1308 out:
1309 return(error);
1310 }
1311
1312
1313 static int
1314 proc_security_policy(proc_t p)
1315 {
1316 kauth_cred_t my_cred;
1317 uid_t uid;
1318
1319 my_cred = kauth_cred_proc_ref(p);
1320 uid = kauth_cred_getuid(my_cred) ;
1321 kauth_cred_unref(&my_cred);
1322
1323 if ((uid != kauth_cred_getuid(kauth_cred_get()))
1324 && suser(kauth_cred_get(), (u_short *)0)) {
1325 return(EPERM);
1326 }
1327
1328 return(0);
1329 }
1330
1331 int
1332 proc_kernmsgbuf(user_addr_t buffer, uint32_t buffersize, int32_t * retval)
1333 {
1334 if (suser(kauth_cred_get(), (u_short *)0) == 0) {
1335 return(log_dmesg(buffer, buffersize, retval));
1336 } else
1337 return(EPERM);
1338 }
1339
1340 /* ********* process control sets on self only */
1341 int
1342 proc_setcontrol(int pid, int flavor, uint64_t arg, __unused user_addr_t buffer, __unused uint32_t buffersize, __unused int32_t * retval)
1343 {
1344 struct proc * pself = PROC_NULL;
1345 int error = 0;
1346 uint32_t pcontrol = (uint32_t)arg;
1347
1348
1349 pself = current_proc();
1350 if (pid != pself->p_pid)
1351 return(EINVAL);
1352
1353 if (pcontrol > P_PCMAX)
1354 return(EINVAL);
1355
1356 switch (flavor) {
1357 case PROC_SELFSET_PCONTROL: {
1358 proc_lock(pself);
1359 /* reset existing control setting while retaining action state */
1360 pself->p_pcaction &= PROC_ACTION_MASK;
1361 /* set new control state */
1362 pself->p_pcaction |= pcontrol;
1363 proc_unlock(pself);
1364 }
1365 break;
1366
1367 default:
1368 error = ENOTSUP;
1369 }
1370
1371 return(error);
1372 }
1373
1374
1375 /*
1376 * copy stat64 structure into vinfo_stat structure.
1377 */
1378 static void
1379 munge_vinfo_stat(struct stat64 *sbp, struct vinfo_stat *vsbp)
1380 {
1381 bzero(vsbp, sizeof(struct vinfo_stat));
1382
1383 vsbp->vst_dev = sbp->st_dev;
1384 vsbp->vst_mode = sbp->st_mode;
1385 vsbp->vst_nlink = sbp->st_nlink;
1386 vsbp->vst_ino = sbp->st_ino;
1387 vsbp->vst_uid = sbp->st_uid;
1388 vsbp->vst_gid = sbp->st_gid;
1389 vsbp->vst_atime = sbp->st_atimespec.tv_sec;
1390 vsbp->vst_atimensec = sbp->st_atimespec.tv_nsec;
1391 vsbp->vst_mtime = sbp->st_mtimespec.tv_sec;
1392 vsbp->vst_mtimensec = sbp->st_mtimespec.tv_nsec;
1393 vsbp->vst_ctime = sbp->st_ctimespec.tv_sec;
1394 vsbp->vst_ctimensec = sbp->st_ctimespec.tv_nsec;
1395 vsbp->vst_birthtime = sbp->st_birthtimespec.tv_sec;
1396 vsbp->vst_birthtimensec = sbp->st_birthtimespec.tv_nsec;
1397 vsbp->vst_size = sbp->st_size;
1398 vsbp->vst_blocks = sbp->st_blocks;
1399 vsbp->vst_blksize = sbp->st_blksize;
1400 vsbp->vst_flags = sbp->st_flags;
1401 vsbp->vst_gen = sbp->st_gen;
1402 vsbp->vst_rdev = sbp->st_rdev;
1403 vsbp->vst_qspare[0] = sbp->st_qspare[0];
1404 vsbp->vst_qspare[1] = sbp->st_qspare[1];
1405 }