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