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