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
84struct pshmnode;
85struct psemnode;
86struct pipe;
87struct kqueue;
88struct atalk;
89
90uint64_t get_dispatchqueue_offset_from_proc(void *);
91int 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 */
94int proc_listpids(uint32_t type, uint32_t tyoneinfo, user_addr_t buffer, uint32_t buffersize, int32_t * retval);
95int proc_pidinfo(int pid, int flavor, uint64_t arg, user_addr_t buffer, uint32_t buffersize, int32_t * retval);
96int proc_pidfdinfo(int pid, int flavor,int fd, user_addr_t buffer, uint32_t buffersize, int32_t * retval);
97int proc_kernmsgbuf(user_addr_t buffer, uint32_t buffersize, int32_t * retval);
98int proc_setcontrol(int pid, int flavor, uint64_t arg, user_addr_t buffer, uint32_t buffersize, int32_t * retval);
99int proc_pidfileportinfo(int pid, int flavor, mach_port_name_t name, user_addr_t buffer, uint32_t buffersize, int32_t *retval);
100int proc_dirtycontrol(int pid, int flavor, uint64_t arg, int32_t * retval);
101int proc_terminate(int pid, int32_t * retval);
102
103/* protos for procpidinfo calls */
104int proc_pidfdlist(proc_t p, user_addr_t buffer, uint32_t buffersize, int32_t *retval);
105int proc_pidbsdinfo(proc_t p, struct proc_bsdinfo *pbsd, int zombie);
106int proc_pidshortbsdinfo(proc_t p, struct proc_bsdshortinfo *pbsd_shortp, int zombie);
107int proc_pidtaskinfo(proc_t p, struct proc_taskinfo *ptinfo);
108int proc_pidallinfo(proc_t p, int flavor, uint64_t arg, user_addr_t buffer, uint32_t buffersize, int32_t *retval);
109int proc_pidthreadinfo(proc_t p, uint64_t arg,  int thuniqueid, struct proc_threadinfo *pthinfo);
110int proc_pidthreadpathinfo(proc_t p, uint64_t arg,  struct proc_threadwithpathinfo *pinfo);
111int proc_pidlistthreads(proc_t p,  user_addr_t buffer, uint32_t buffersize, int32_t *retval);
112int proc_pidregioninfo(proc_t p, uint64_t arg, user_addr_t buffer, uint32_t buffersize, int32_t *retval);
113int proc_pidregionpathinfo(proc_t p,  uint64_t arg, user_addr_t buffer, uint32_t buffersize, int32_t *retval);
114int proc_pidvnodepathinfo(proc_t p,  uint64_t arg, user_addr_t buffer, uint32_t buffersize, int32_t *retval);
115int proc_pidpathinfo(proc_t p, uint64_t arg, user_addr_t buffer, uint32_t buffersize, int32_t *retval);
116int proc_pidworkqueueinfo(proc_t p, struct proc_workqueueinfo *pwqinfo);
117int proc_pidfileportlist(proc_t p, user_addr_t buffer, uint32_t buffersize, int32_t *retval);
118
119
120/* protos for proc_pidfdinfo calls */
121int pid_vnodeinfo(vnode_t vp, uint32_t vid, struct fileproc * fp, int closeonexec, user_addr_t  buffer, uint32_t buffersize, int32_t * retval);
122int pid_vnodeinfopath(vnode_t vp, uint32_t vid, struct fileproc * fp, int closeonexec, user_addr_t  buffer, uint32_t buffersize, int32_t * retval);
123int pid_socketinfo(socket_t  so, struct fileproc *fp, int closeonexec, user_addr_t  buffer, uint32_t buffersize, int32_t * retval);
124int pid_pseminfo(struct psemnode * psem, struct fileproc * fp,  int closeonexec, user_addr_t  buffer, uint32_t buffersize, int32_t * retval);
125int pid_pshminfo(struct pshmnode * pshm, struct fileproc * fp,  int closeonexec, user_addr_t  buffer, uint32_t buffersize, int32_t * retval);
126int pid_pipeinfo(struct pipe * p, struct fileproc * fp,  int closeonexec, user_addr_t  buffer, uint32_t buffersize, int32_t * retval);
127int pid_kqueueinfo(struct kqueue * kq, struct fileproc * fp,  int closeonexec, user_addr_t  buffer, uint32_t buffersize, int32_t * retval);
128int 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
133void proc_dirty_start(struct proc *p);
134void proc_dirty_end(struct proc *p);
135
136int fill_vnodeinfo(vnode_t vp, struct vnode_info *vinfo);
137void  fill_fileinfo(struct fileproc * fp, int closeonexec, struct proc_fileinfo * finfo);
138static int proc_security_policy(proc_t p);
139static void munge_vinfo_stat(struct stat64 *sbp, struct vinfo_stat *vsbp);
140
141extern int cansignal(struct proc *, kauth_cred_t, struct proc *, int, int);
142
143uint64_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
155int
156proc_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
162int
163proc_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 ****************/
192int
193proc_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;
229proc_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
313int
314proc_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 */
368static int
369proc_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
378struct fileport_fdtype_args {
379	struct proc_fileportinfo *ffa_pfi;
380	struct proc_fileportinfo *ffa_pfi_end;
381};
382
383static int
384proc_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
397int
398proc_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
479int
480proc_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
590int
591proc_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
660int
661proc_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
675int
676proc_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
691void
692bsd_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
699void
700bsd_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
717int
718proc_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
746int
747proc_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
780int
781proc_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
797int
798proc_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 */
834int
835proc_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	}
892out:
893	return(error);
894}
895
896int
897proc_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
934int
935proc_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
951int
952proc_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
1209out:
1210	if (gotref)
1211		proc_rele(p);
1212	return(error);
1213}
1214
1215
1216int
1217pid_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
1237int
1238pid_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
1262void
1263fill_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
1277int
1278fill_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;
1300out:
1301		return(error);
1302}
1303
1304int
1305pid_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
1324int
1325pid_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
1341int
1342pid_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
1358int
1359pid_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
1374int
1375pid_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
1392int
1393pid_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 ***************************/
1401int
1402proc_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);
1562out1 :
1563	proc_rele(p);
1564out:
1565	return(error);
1566}
1567
1568/*
1569 * Helper function for proc_pidfileportinfo
1570 */
1571
1572struct 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
1579static kern_return_t
1580proc_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 *********************/
1648int
1649proc_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;
1694out1:
1695	proc_rele(p);
1696out:
1697	return (error);
1698}
1699
1700static int
1701proc_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
1718int
1719proc_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 */
1728int
1729proc_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
1799out:
1800	return(error);
1801}
1802
1803void
1804proc_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
1814void
1815proc_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
1825static boolean_t
1826proc_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
1840int
1841proc_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
1969out:
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
1982int
1983proc_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
2034out:
2035	proc_rele(p);
2036
2037	return error;
2038}
2039
2040void
2041proc_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 */
2063static void
2064munge_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}
2091