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