xref: /NextBSD/sys/compat/mach/proc_info.c (revision 6283aa8b8e910d10094766cf10d892a509825cc1)
1 /*-
2  * Copyright (c) 2014-2015, Matthew Macy <mmacy@nextbsd.org>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  *  1. Redistributions of source code must retain the above copyright notice,
9  *     this list of conditions and the following disclaimer.
10  *
11  *  2. Neither the name of Matthew Macy nor the names of its
12  *     contributors may be used to endorse or promote products derived from
13  *     this software without specific prior written permission.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
19  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25  * POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #include <sys/cdefs.h>
29 __FBSDID("$FreeBSD$");
30 
31 #include <sys/param.h>
32 #include <sys/systm.h>
33 #include <sys/filedesc.h>
34 #include <sys/lock.h>
35 #include <sys/malloc.h>
36 #include <sys/mutex.h>
37 #include <sys/priv.h>
38 #include <sys/proc.h>
39 #include <sys/procctl.h>
40 #include <sys/ptrace.h>
41 #include <sys/rwlock.h>
42 #include <sys/syscallsubr.h>
43 #include <sys/sysent.h>
44 #include <sys/sysproto.h>
45 #include <sys/vnode.h>
46 #include <sys/sx.h>
47 #include <sys/signalvar.h>
48 #include <sys/tty.h>
49 
50 #include <vm/vm.h>
51 #include <vm/pmap.h>
52 #include <vm/vm_extern.h>
53 #include <vm/vm_map.h>
54 #include <vm/vm_kern.h>
55 #include <vm/vm_object.h>
56 #include <vm/vm_page.h>
57 #include <vm/vm_param.h>
58 
59 #include <sys/mach/mach_types.h>
60 #include <sys/mach/ipc/ipc_kmsg.h>
61 #include <sys/mach/thread.h>
62 #define PRIVATE
63 #include <sys/proc_info.h>
64 
65 
66 int set_security_token(task_t);
67 
68 
69 static int
proc_terminate(int pid)70 proc_terminate(int pid)
71 {
72 	int err;
73 	struct proc *p;
74 
75 	err = 0;
76 	if (pid <= 0)
77 		return (EINVAL);
78 	if (pid == curproc->p_pid)
79 		return (EPERM);
80 	if ((p = pfind(pid)) == NULL)
81 		return (ESRCH);
82 	if ((err = p_cansignal(curthread, p, SIGKILL)) == 0) {
83 		/* p_cansignal returns 0 if you can, or an error if you can't. */
84 		kern_psignal(p, SIGTERM);
85 	}
86 	PROC_UNLOCK(p);
87 	return (err);
88 }
89 
90 static int
proc_listpids(uint32_t type,uint32_t flavor,void * ubuffer,uint32_t buffersize)91 proc_listpids(uint32_t type, uint32_t flavor, void *ubuffer, uint32_t buffersize)
92 {
93 	struct proc *p;
94 	struct proclist *list;
95 	struct pgrp *pgrpp;
96 	int err, count, incr, maxpidcount, numpids;
97 	pid_t *buf, *ptr;
98 	uid_t uid;
99 	struct thread *td;
100 
101 	if (type == PROC_TTY_ONLY)
102 		return (EINVAL);
103 
104 	td = curthread;
105 	if (ubuffer == NULL) {
106 		td->td_retval[0] = (nprocs + 30)*sizeof(pid_t);
107 		return (0);
108 	}
109 	if (buffersize < sizeof(pid_t))
110 		return (ENOMEM);
111 
112 	maxpidcount = buffersize/sizeof(pid_t);
113 	numpids = nprocs + 30;
114 	err = count = 0;
115 	if (numpids > maxpidcount)
116 		numpids = maxpidcount;
117 
118 	buf = malloc(numpids *sizeof(pid_t), M_DEVBUF, M_WAITOK);
119 
120 	ptr = buf;
121 	if (type == PROC_PGRP_ONLY) {
122 		count = 0;
123 		pgrpp = pgfind(flavor);
124 		if (pgrpp == NULL)
125 			return (ENOENT);
126 		list = (struct proclist *)&pgrpp->pg_members;
127 		LIST_FOREACH(p, list, p_pglist) {
128 			if (count == numpids)
129 				break;
130 			*ptr++ = p->p_pid;
131 			count++;
132 		}
133 		PGRP_UNLOCK(pgrpp);
134 		goto done;
135 	}
136 
137 	list = &allproc;
138 	sx_slock(&allproc_lock);
139 scan_next:
140 	LIST_FOREACH(p, list, p_list) {
141 		incr = 0;
142 		switch (type) {
143 		case PROC_ALL_PIDS:
144 			incr = 1;
145 			break;
146 		case PROC_PPID_ONLY:
147 			if (((p->p_pptr && (p->p_pptr->p_pid == flavor)) &&
148 				 ((p->p_flag & P_TRACED) == 0)) ||
149 				p->p_oppid == flavor)
150 				incr = 1;
151 			break;
152 		case PROC_UID_ONLY:
153 			if (p->p_ucred != NULL) {
154 				uid = p->p_ucred->cr_uid;
155 				if (uid == flavor)
156 					incr = 1;
157 			}
158 			break;
159 		case PROC_RUID_ONLY:
160 			if (p->p_ucred != NULL) {
161 				uid = p->p_ucred->cr_ruid;
162 				if (uid == flavor)
163 					incr = 1;
164 			}
165 			break;
166 		default:
167 			err = EINVAL;
168 			goto done;
169 		}
170 		if (incr) {
171 			*ptr++ = p->p_pid;
172 			count++;
173 		}
174 		if (count >= numpids)
175 			break;
176 	}
177 	if ((count < numpids) && (list == &allproc)) {
178 		list = &zombproc;
179 		goto scan_next;
180 	}
181 done:
182 	sx_sunlock(&allproc_lock);
183 	if (err)
184 		return (err);
185 
186 	err = copyout(buf, ubuffer, count * sizeof(pid_t));
187 	if (err == 0)
188 		td->td_retval[0] = count * sizeof(pid_t);
189 	free(buf, M_DEVBUF);
190 
191 	return (err);
192 }
193 
194 static int
proc_pidbsdinfo(struct proc * p,struct proc_bsdinfo * pbsd,int zombie)195 proc_pidbsdinfo(struct proc *p, struct proc_bsdinfo * pbsd, int zombie)
196 {
197 	register struct tty *tp;
198 	struct  session *sessionp = NULL;
199 	struct pgrp * pg;
200 	struct ucred *cred;
201 
202 	pg = p->p_pgrp;
203 	if (pg)
204 		sessionp = pg->pg_session;
205 
206 	bzero(pbsd, sizeof(struct proc_bsdinfo));
207 	pbsd->pbi_status = p->p_state;
208 	pbsd->pbi_xstatus = KW_EXITCODE(p->p_xexit, p->p_xsig);
209 	pbsd->pbi_pid = p->p_pid;
210 	if (p->p_pptr)
211 		pbsd->pbi_ppid = p->p_pptr->p_pid;
212 	crhold(p->p_ucred);
213 	cred = p->p_ucred;
214 	pbsd->pbi_uid = cred->cr_uid;
215 	pbsd->pbi_gid = cred->cr_gid;
216 	pbsd->pbi_ruid =  cred->cr_ruid;
217 	pbsd->pbi_rgid = cred->cr_rgid;
218 	pbsd->pbi_svuid =  cred->cr_svuid;
219 	pbsd->pbi_svgid = cred->cr_svgid;
220 	crfree(cred);
221 
222 	pbsd->pbi_nice = p->p_nice;
223 #ifdef notyet
224 	pbsd->pbi_start_tvsec = p->p_start.tv_sec;
225 	pbsd->pbi_start_tvusec = p->p_start.tv_usec;
226 #endif
227 	bcopy(&p->p_comm, &pbsd->pbi_comm[0], MAXCOMLEN);
228 	pbsd->pbi_comm[MAXCOMLEN - 1] = '\0';
229 	pbsd->pbi_flags = 0;
230 	if ((p->p_flag & P_SYSTEM) == P_SYSTEM)
231 		pbsd->pbi_flags |= PROC_FLAG_SYSTEM;
232 	if ((p->p_flag & P_TRACED) == P_TRACED)
233 		pbsd->pbi_flags |= PROC_FLAG_TRACED;
234 	if ((p->p_flag & P_WEXIT) == P_WEXIT)
235 		pbsd->pbi_flags |= PROC_FLAG_INEXIT;
236 	if ((p->p_flag & P_PPWAIT) == P_PPWAIT)
237 		pbsd->pbi_flags |= PROC_FLAG_PPWAIT;
238 #ifdef notyet
239 	if ((p->p_flag & P_LP64) == P_LP64)
240 #endif
241 #ifdef __LP64__
242 		pbsd->pbi_flags |= PROC_FLAG_LP64;
243 #endif
244 	if ((p->p_flag & P_CONTROLT) == P_CONTROLT)
245 		pbsd->pbi_flags |= PROC_FLAG_CONTROLT;
246 	if ((p->p_flag & P_SUGID) == P_SUGID)
247 		pbsd->pbi_flags |= PROC_FLAG_PSUGID;
248 	if ((p->p_flag & P_EXEC) == P_EXEC)
249 		pbsd->pbi_flags |= PROC_FLAG_EXEC;
250 
251 	if (sessionp != NULL) {
252 		if (p == sessionp->s_leader)
253 			pbsd->pbi_flags |= PROC_FLAG_SLEADER;
254 		if (sessionp->s_ttyvp)
255 			pbsd->pbi_flags |= PROC_FLAG_CTTY;
256 	}
257 
258 	if (zombie == 0)
259 		pbsd->pbi_nfiles = p->p_fd->fd_nfiles;
260 
261 	pbsd->e_tdev = NODEV;
262 	if (pg != NULL) {
263 		pbsd->pbi_pgid = pg->pg_id;
264 		pbsd->pbi_pjobc = pg->pg_jobc;
265 		if ((p->p_flag & P_CONTROLT) && (sessionp != NULL) && (tp = sessionp->s_ttyp)) {
266 #ifdef notyet
267 			pbsd->e_tdev = tp->t_dev;
268 #endif
269 			if (tp->t_pgrp)
270 				pbsd->e_tpgid = tp->t_pgrp->pg_id;
271 		}
272 	}
273 	return(0);
274 }
275 
276 static int
proc_pidshortbsdinfo(struct proc * p,struct proc_bsdshortinfo * pbsd_shortp,int zombie)277 proc_pidshortbsdinfo(struct proc *p, struct proc_bsdshortinfo * pbsd_shortp, int zombie)
278 {
279 	struct ucred *cred;
280 
281 	bzero(pbsd_shortp, sizeof(struct proc_bsdshortinfo));
282 	pbsd_shortp->pbsi_pid = p->p_pid;
283 	if (p->p_pptr)
284 		pbsd_shortp->pbsi_ppid = p->p_pptr->p_pid;
285 	if (p->p_pgrp)
286 	pbsd_shortp->pbsi_pgid = p->p_pgrp->pg_id;
287 	pbsd_shortp->pbsi_status = p->p_state;
288 	bcopy(&p->p_comm, &pbsd_shortp->pbsi_comm[0], MAXCOMLEN);
289 	pbsd_shortp->pbsi_comm[MAXCOMLEN - 1] = '\0';
290 
291 	pbsd_shortp->pbsi_flags = 0;
292 	if ((p->p_flag & P_SYSTEM) == P_SYSTEM)
293 		pbsd_shortp->pbsi_flags |= PROC_FLAG_SYSTEM;
294 	if ((p->p_flag & P_TRACED) == P_TRACED)
295 		pbsd_shortp->pbsi_flags |= PROC_FLAG_TRACED;
296 	if ((p->p_flag & P_WEXIT) == P_WEXIT)
297 		pbsd_shortp->pbsi_flags |= PROC_FLAG_INEXIT;
298 	if ((p->p_flag & P_PPWAIT) == P_PPWAIT)
299 		pbsd_shortp->pbsi_flags |= PROC_FLAG_PPWAIT;
300 #ifdef notyet
301 	if ((p->p_flag & P_LP64) == P_LP64)
302 #endif
303 #ifdef __LP64__
304 		pbsd_shortp->pbsi_flags |= PROC_FLAG_LP64;
305 #endif
306 	if ((p->p_flag & P_CONTROLT) == P_CONTROLT)
307 		pbsd_shortp->pbsi_flags |= PROC_FLAG_CONTROLT;
308 	if ((p->p_flag & P_SUGID) == P_SUGID)
309 		pbsd_shortp->pbsi_flags |= PROC_FLAG_PSUGID;
310 	if ((p->p_flag & P_EXEC) == P_EXEC)
311 		pbsd_shortp->pbsi_flags |= PROC_FLAG_EXEC;
312 
313 	crhold(p->p_ucred);
314 	cred = p->p_ucred;
315 	pbsd_shortp->pbsi_uid = cred->cr_uid;
316 	pbsd_shortp->pbsi_gid = cred->cr_gid;
317 	pbsd_shortp->pbsi_ruid =  cred->cr_ruid;
318 	pbsd_shortp->pbsi_rgid = cred->cr_rgid;
319 	pbsd_shortp->pbsi_svuid =  cred->cr_svuid;
320 	pbsd_shortp->pbsi_svgid = cred->cr_svgid;
321 	crfree(cred);
322 
323 	return(0);
324 }
325 
326 static uint64_t
proc_puniqueid(struct proc * p)327 proc_puniqueid(struct proc *p)
328 {
329 	task_t task;
330 
331 	task = p->p_machdata;
332 	return (task->itk_puniqueid);
333 }
334 
335 static uint64_t
proc_uniqueid(struct proc * p)336 proc_uniqueid(struct proc *p)
337 {
338 	task_t task;
339 
340 	task = p->p_machdata;
341 	return (task->itk_uniqueid);
342 }
343 
344 static void
proc_getexecutableuuid(struct proc * p __unused,unsigned char * uuid,int size)345 proc_getexecutableuuid(struct proc *p __unused, unsigned char *uuid, int size)
346 {
347 
348 	bzero(uuid, size);
349 }
350 
351 static void
proc_piduniqidentifierinfo(struct proc * p,struct proc_uniqidentifierinfo * p_uniqidinfo)352 proc_piduniqidentifierinfo(struct proc *p, struct proc_uniqidentifierinfo *p_uniqidinfo)
353 {
354 	p_uniqidinfo->p_uniqueid = proc_uniqueid(p);
355 	proc_getexecutableuuid(p, (unsigned char *)&p_uniqidinfo->p_uuid, sizeof(p_uniqidinfo->p_uuid));
356 	p_uniqidinfo->p_puniqueid = proc_puniqueid(p);
357 	p_uniqidinfo->p_reserve2 = 0;
358 	p_uniqidinfo->p_reserve3 = 0;
359 	p_uniqidinfo->p_reserve4 = 0;
360 }
361 
362 static int
proc_pidinfo(int pid,int flavor,uint64_t arg,void * buffer,uint32_t buffersize)363 proc_pidinfo(int pid, int flavor, uint64_t arg, void *buffer, uint32_t  buffersize)
364 {
365 	struct proc *p;
366 	int err, size, findzomb, iszomb, shortversion, uniqidversion;
367 	void *kbuf;
368 
369 	switch (flavor) {
370 	case PROC_PIDTBSDINFO:
371 		size = PROC_PIDTBSDINFO_SIZE;
372 		break;
373 	case PROC_PIDT_SHORTBSDINFO:
374 		size = PROC_PIDT_SHORTBSDINFO_SIZE;
375 		break;
376 	case PROC_PIDUNIQIDENTIFIERINFO:
377 		size = PROC_PIDUNIQIDENTIFIERINFO_SIZE;
378 		break;
379 	case PROC_PIDT_BSDINFOWITHUNIQID:
380 		size = PROC_PIDT_BSDINFOWITHUNIQID_SIZE;
381 		break;
382 	default:
383 		return (EINVAL);
384 	}
385 
386 	if (buffersize < size)
387 		return (ENOMEM);
388 
389 	kbuf = malloc(size, M_DEVBUF, M_WAITOK);
390 	uniqidversion = shortversion = err = findzomb = iszomb = 0;
391 	if ((flavor == PROC_PIDTBSDINFO) || (flavor == PROC_PIDT_SHORTBSDINFO) || (flavor == PROC_PIDT_BSDINFOWITHUNIQID)
392 	    || (flavor == PROC_PIDUNIQIDENTIFIERINFO)) {
393 		if (arg)
394 			findzomb = 1;
395 	}
396 	if ((p = pfind(pid)) == NULL) {
397 		if (!findzomb || ((p = zpfind(pid)) == NULL)) {
398 			err = ESRCH;
399 			goto done;
400 		}
401 		iszomb = 1;
402 	}
403 
404 	switch (flavor) {
405 	case PROC_PIDUNIQIDENTIFIERINFO: {
406 		struct proc_uniqidentifierinfo p_uniqidinfo;
407 
408 		proc_piduniqidentifierinfo(p, &p_uniqidinfo);
409 		bcopy(&p_uniqidinfo, kbuf, sizeof(struct proc_uniqidentifierinfo));
410 	}
411 		break;
412 	case PROC_PIDT_SHORTBSDINFO:
413 		shortversion = 1;
414 	case PROC_PIDT_BSDINFOWITHUNIQID:
415 	case PROC_PIDTBSDINFO: {
416 		struct proc_bsdinfo pbsd;
417 		struct proc_bsdshortinfo pbsd_short;
418 		struct proc_bsdinfowithuniqid pbsd_uniqid;
419 
420 		if (flavor == PROC_PIDT_BSDINFOWITHUNIQID)
421 			uniqidversion = 1;
422 
423 		if (shortversion != 0) {
424 			err = proc_pidshortbsdinfo(p, &pbsd_short, iszomb);
425 		} else {
426 			err = proc_pidbsdinfo(p, &pbsd, iszomb);
427 			if (uniqidversion != 0) {
428 				proc_piduniqidentifierinfo(p, &pbsd_uniqid.p_uniqidentifier);
429 				pbsd_uniqid.pbsd = pbsd;
430 			}
431 		}
432 
433 		if (err == 0) {
434 			if (shortversion != 0) {
435 				bcopy(&pbsd_short, kbuf, sizeof(struct proc_bsdshortinfo));
436 			} else if (uniqidversion != 0) {
437 				bcopy(&pbsd_uniqid, kbuf, sizeof(struct proc_bsdinfowithuniqid));
438 			} else {
439 				bcopy(&pbsd, kbuf, sizeof(struct proc_bsdinfo));
440 			}
441 		}
442 	}
443 		break;
444 	default:
445 		err = ENOTSUP;
446 	}
447 	PROC_UNLOCK(p);
448 	if (err == 0)
449 		err = copyout(kbuf, buffer, size);
450 	if (err == 0)
451 		curthread->td_retval[0] = size;
452 done:
453 	free(kbuf, M_DEVBUF);
454 	return (err);
455 }
456 
457 static int
proc_info(int op,pid_t pid,uint32_t flavor,uint64_t arg,void * addr,uint32_t buffersize)458 proc_info(int op, pid_t pid, uint32_t flavor, uint64_t arg, void *addr,
459 		  uint32_t buffersize)
460 {
461 
462 	switch (op) {
463 	case PROC_INFO_CALL_LISTPIDS:
464 		return (proc_listpids(pid, flavor, addr, buffersize));
465 		break;
466 	case PROC_INFO_CALL_TERMINATE:
467 		return (proc_terminate(pid));
468 		break;
469 	case PROC_INFO_CALL_PIDINFO:
470 		return (proc_pidinfo(pid, flavor, arg, addr, buffersize));
471 		break;
472 	default:
473 		return (EOPNOTSUPP);
474 	}
475 	/* NOT REACHED */
476 	return (0);
477 }
478 
479 int
set_security_token(task_t task)480 set_security_token(task_t task)
481 {
482 	struct proc *p;
483 	security_token_t sec_token;
484 	audit_token_t audit_token;
485 
486 	p = task->itk_p;
487 
488 	sec_token.val[0] = sec_token.val[1] = 0;
489 	audit_token.val[0] = 0; /* wat: p->p_ucred->cr_au.ai_auid; */
490 	audit_token.val[1] = p->p_ucred->cr_uid;
491 	audit_token.val[2] = p->p_ucred->cr_gid;
492 	audit_token.val[3] = p->p_ucred->cr_ruid;
493 	audit_token.val[4] = p->p_ucred->cr_rgid;
494 	audit_token.val[5] = p->p_pid;
495 	audit_token.val[6] = 0; /* wat: p->p_ucred->cr_au.ai_asid; */
496 	audit_token.val[7] = 0; /* wat: p->p_ucred->cr_au.ai_termid.port; */
497 
498 	task->audit_token = audit_token;
499 	task->sec_token = sec_token;
500 
501 	return (0);
502 }
503 
504 int
sys___proc_info(struct thread * td __unused,struct __proc_info_args * uap)505 sys___proc_info(struct thread *td __unused, struct __proc_info_args *uap)
506 {
507 
508 	return (proc_info(uap->callnum, uap->pid, uap->flavor, uap->arg, uap->buffer,
509 					  uap->buffersize));
510 }
511 
512 
513 int
sys___iopolicysys(struct thread * td __unused,struct __iopolicysys_args * uap __unused)514 sys___iopolicysys(struct thread *td __unused, struct __iopolicysys_args *uap __unused)
515 {
516 
517 	return (ENOSYS);
518 }
519