xref: /netbsd-src/sys/kern/sys_process.c (revision f876c1012ec8280866d3287842a50de849d25967)
1 /*	$NetBSD: sys_process.c,v 1.95 2005/02/26 21:34:55 perry Exp $	*/
2 
3 /*-
4  * Copyright (c) 1982, 1986, 1989, 1993
5  *	The Regents of the University of California.  All rights reserved.
6  * (c) UNIX System Laboratories, Inc.
7  * All or some portions of this file are derived from material licensed
8  * to the University of California by American Telephone and Telegraph
9  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
10  * the permission of UNIX System Laboratories, Inc.
11  *
12  * This code is derived from software contributed to Berkeley by
13  * Jan-Simon Pendry.
14  *
15  * Redistribution and use in source and binary forms, with or without
16  * modification, are permitted provided that the following conditions
17  * are met:
18  * 1. Redistributions of source code must retain the above copyright
19  *    notice, this list of conditions and the following disclaimer.
20  * 2. Redistributions in binary form must reproduce the above copyright
21  *    notice, this list of conditions and the following disclaimer in the
22  *    documentation and/or other materials provided with the distribution.
23  * 3. Neither the name of the University nor the names of its contributors
24  *    may be used to endorse or promote products derived from this software
25  *    without specific prior written permission.
26  *
27  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37  * SUCH DAMAGE.
38  *
39  *	from: @(#)sys_process.c	8.1 (Berkeley) 6/10/93
40  */
41 
42 /*-
43  * Copyright (c) 1993 Jan-Simon Pendry.
44  * Copyright (c) 1994 Christopher G. Demetriou.  All rights reserved.
45  *
46  * This code is derived from software contributed to Berkeley by
47  * Jan-Simon Pendry.
48  *
49  * Redistribution and use in source and binary forms, with or without
50  * modification, are permitted provided that the following conditions
51  * are met:
52  * 1. Redistributions of source code must retain the above copyright
53  *    notice, this list of conditions and the following disclaimer.
54  * 2. Redistributions in binary form must reproduce the above copyright
55  *    notice, this list of conditions and the following disclaimer in the
56  *    documentation and/or other materials provided with the distribution.
57  * 3. All advertising materials mentioning features or use of this software
58  *    must display the following acknowledgement:
59  *	This product includes software developed by the University of
60  *	California, Berkeley and its contributors.
61  * 4. Neither the name of the University nor the names of its contributors
62  *    may be used to endorse or promote products derived from this software
63  *    without specific prior written permission.
64  *
65  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
66  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
67  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
68  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
69  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
70  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
71  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
72  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
73  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
74  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
75  * SUCH DAMAGE.
76  *
77  *	from: @(#)sys_process.c	8.1 (Berkeley) 6/10/93
78  */
79 
80 /*
81  * References:
82  *	(1) Bach's "The Design of the UNIX Operating System",
83  *	(2) sys/miscfs/procfs from UCB's 4.4BSD-Lite distribution,
84  *	(3) the "4.4BSD Programmer's Reference Manual" published
85  *		by USENIX and O'Reilly & Associates.
86  * The 4.4BSD PRM does a reasonably good job of documenting what the various
87  * ptrace() requests should actually do, and its text is quoted several times
88  * in this file.
89  */
90 
91 #include <sys/cdefs.h>
92 __KERNEL_RCSID(0, "$NetBSD: sys_process.c,v 1.95 2005/02/26 21:34:55 perry Exp $");
93 
94 #include <sys/param.h>
95 #include <sys/systm.h>
96 #include <sys/proc.h>
97 #include <sys/errno.h>
98 #include <sys/ptrace.h>
99 #include <sys/uio.h>
100 #include <sys/user.h>
101 #include <sys/ras.h>
102 #include <sys/malloc.h>
103 
104 #include <sys/mount.h>
105 #include <sys/sa.h>
106 #include <sys/syscallargs.h>
107 
108 #include <uvm/uvm_extern.h>
109 
110 #include <machine/reg.h>
111 
112 /* Macros to clear/set/test flags. */
113 #define	SET(t, f)	(t) |= (f)
114 #define	CLR(t, f)	(t) &= ~(f)
115 #define	ISSET(t, f)	((t) & (f))
116 
117 /*
118  * Process debugging system call.
119  */
120 int
121 sys_ptrace(l, v, retval)
122 	struct lwp *l;
123 	void *v;
124 	register_t *retval;
125 {
126 	struct sys_ptrace_args /* {
127 		syscallarg(int) req;
128 		syscallarg(pid_t) pid;
129 		syscallarg(caddr_t) addr;
130 		syscallarg(int) data;
131 	} */ *uap = v;
132 	struct proc *p = l->l_proc;
133 	struct lwp *lt, *lr;
134 	struct proc *t;				/* target process */
135 	struct uio uio;
136 	struct iovec iov;
137 	struct ptrace_io_desc piod;
138 	struct ptrace_lwpinfo pl;
139 	int s, error, write, tmp, size;
140 	char *path;
141 
142 	/* "A foolish consistency..." XXX */
143 	if (SCARG(uap, req) == PT_TRACE_ME)
144 		t = p;
145 	else {
146 
147 		/* Find the process we're supposed to be operating on. */
148 		if ((t = pfind(SCARG(uap, pid))) == NULL)
149 			return (ESRCH);
150 	}
151 
152 	/* Can't trace a process that's currently exec'ing. */
153 	if ((t->p_flag & P_INEXEC) != 0)
154 		return EAGAIN;
155 
156 	/* Make sure we can operate on it. */
157 	switch (SCARG(uap, req)) {
158 	case  PT_TRACE_ME:
159 		/* Saying that you're being traced is always legal. */
160 		break;
161 
162 	case  PT_ATTACH:
163 	case  PT_DUMPCORE:
164 		/*
165 		 * You can't attach to a process if:
166 		 *	(1) it's the process that's doing the attaching,
167 		 */
168 		if (t->p_pid == p->p_pid)
169 			return (EINVAL);
170 
171 		/*
172 		 *  (2) it's a system process
173 		 */
174 		if (t->p_flag & P_SYSTEM)
175 			return (EPERM);
176 
177 		/*
178 		 *	(3) it's already being traced, or
179 		 */
180 		if (ISSET(t->p_flag, P_TRACED))
181 			return (EBUSY);
182 
183 		/*
184 		 *	(4) it's not owned by you, or is set-id on exec
185 		 *	    (unless you're root), or...
186 		 */
187 		if ((t->p_cred->p_ruid != p->p_cred->p_ruid ||
188 			ISSET(t->p_flag, P_SUGID)) &&
189 		    (error = suser(p->p_ucred, &p->p_acflag)) != 0)
190 			return (error);
191 
192 		/*
193 		 *	(5) ...it's init, which controls the security level
194 		 *	    of the entire system, and the system was not
195 		 *	    compiled with permanently insecure mode turned on
196 		 */
197 		if (t == initproc && securelevel > -1)
198 			return (EPERM);
199 
200 		/*
201 		 * (6) the tracer is chrooted, and its root directory is
202 		 * not at or above the root directory of the tracee
203 		 */
204 
205 		if (!proc_isunder(t, p))
206 			return EPERM;
207 		break;
208 
209 	case  PT_READ_I:
210 	case  PT_READ_D:
211 	case  PT_WRITE_I:
212 	case  PT_WRITE_D:
213 	case  PT_CONTINUE:
214 	case  PT_IO:
215 	case  PT_KILL:
216 	case  PT_DETACH:
217 	case  PT_LWPINFO:
218 #ifdef PT_STEP
219 	case  PT_STEP:
220 #endif
221 #ifdef PT_GETREGS
222 	case  PT_GETREGS:
223 #endif
224 #ifdef PT_SETREGS
225 	case  PT_SETREGS:
226 #endif
227 #ifdef PT_GETFPREGS
228 	case  PT_GETFPREGS:
229 #endif
230 #ifdef PT_SETFPREGS
231 	case  PT_SETFPREGS:
232 #endif
233 
234 #ifdef __HAVE_PTRACE_MACHDEP
235 	PTRACE_MACHDEP_REQUEST_CASES
236 #endif
237 
238 		/*
239 		 * You can't do what you want to the process if:
240 		 *	(1) It's not being traced at all,
241 		 */
242 		if (!ISSET(t->p_flag, P_TRACED))
243 			return (EPERM);
244 
245 		/*
246 		 *	(2) it's being traced by procfs (which has
247 		 *	    different signal delivery semantics),
248 		 */
249 		if (ISSET(t->p_flag, P_FSTRACE))
250 			return (EBUSY);
251 
252 		/*
253 		 *	(3) it's not being traced by _you_, or
254 		 */
255 		if (t->p_pptr != p)
256 			return (EBUSY);
257 
258 		/*
259 		 *	(4) it's not currently stopped.
260 		 */
261 		if (t->p_stat != SSTOP || !ISSET(t->p_flag, P_WAITED))
262 			return (EBUSY);
263 		break;
264 
265 	default:			/* It was not a legal request. */
266 		return (EINVAL);
267 	}
268 
269 	/* Do single-step fixup if needed. */
270 	FIX_SSTEP(t);
271 
272 	/*
273 	 * XXX NJWLWP
274 	 *
275 	 * The entire ptrace interface needs work to be useful to a
276 	 * process with multiple LWPs. For the moment, we'll kluge
277 	 * this; memory access will be fine, but register access will
278 	 * be weird.
279 	 */
280 
281 	lt = proc_representative_lwp(t);
282 
283 	/* Now do the operation. */
284 	write = 0;
285 	*retval = 0;
286 	tmp = 0;
287 
288 	switch (SCARG(uap, req)) {
289 	case  PT_TRACE_ME:
290 		/* Just set the trace flag. */
291 		SET(t->p_flag, P_TRACED);
292 		t->p_opptr = t->p_pptr;
293 		return (0);
294 
295 	case  PT_WRITE_I:		/* XXX no separate I and D spaces */
296 	case  PT_WRITE_D:
297 #if defined(__HAVE_RAS)
298 		/*
299 		 * Can't write to a RAS
300 		 */
301 		if (!LIST_EMPTY(&t->p_raslist) &&
302 		    (ras_lookup(t, SCARG(uap, addr)) != (caddr_t)-1)) {
303 			return (EACCES);
304 		}
305 #endif
306 		write = 1;
307 		tmp = SCARG(uap, data);
308 	case  PT_READ_I:		/* XXX no separate I and D spaces */
309 	case  PT_READ_D:
310 		/* write = 0 done above. */
311 		iov.iov_base = (caddr_t)&tmp;
312 		iov.iov_len = sizeof(tmp);
313 		uio.uio_iov = &iov;
314 		uio.uio_iovcnt = 1;
315 		uio.uio_offset = (off_t)(unsigned long)SCARG(uap, addr);
316 		uio.uio_resid = sizeof(tmp);
317 		uio.uio_segflg = UIO_SYSSPACE;
318 		uio.uio_rw = write ? UIO_WRITE : UIO_READ;
319 		uio.uio_procp = NULL;
320 		error = process_domem(p, t, &uio);
321 		if (!write)
322 			*retval = tmp;
323 		return (error);
324 
325 	case  PT_IO:
326 		error = copyin(SCARG(uap, addr), &piod, sizeof(piod));
327 		if (error)
328 			return (error);
329 		iov.iov_base = piod.piod_addr;
330 		iov.iov_len = piod.piod_len;
331 		uio.uio_iov = &iov;
332 		uio.uio_iovcnt = 1;
333 		uio.uio_offset = (off_t)(unsigned long)piod.piod_offs;
334 		uio.uio_resid = piod.piod_len;
335 		uio.uio_segflg = UIO_USERSPACE;
336 		uio.uio_procp = p;
337 		switch (piod.piod_op) {
338 		case PIOD_READ_D:
339 		case PIOD_READ_I:
340 			uio.uio_rw = UIO_READ;
341 			break;
342 		case PIOD_WRITE_D:
343 		case PIOD_WRITE_I:
344 			uio.uio_rw = UIO_WRITE;
345 			break;
346 		default:
347 			return (EINVAL);
348 		}
349 		error = process_domem(p, t, &uio);
350 		piod.piod_len -= uio.uio_resid;
351 		(void) copyout(&piod, SCARG(uap, addr), sizeof(piod));
352 		return (error);
353 
354 	case  PT_DUMPCORE:
355 		if ((path = SCARG(uap, addr)) != NULL) {
356 			char *dst;
357 			int len = SCARG(uap, data);
358 			if (len >= MAXPATHLEN)
359 				return EINVAL;
360 			dst = malloc(len + 1, M_TEMP, M_WAITOK);
361 			if ((error = copyin(path, dst, len)) != 0) {
362 				free(dst, M_TEMP);
363 				return error;
364 			}
365 			path = dst;
366 			path[len] = '\0';
367 		}
368 		error = coredump(lt, path);
369 		if (path)
370 			free(path, M_TEMP);
371 		return error;
372 
373 #ifdef PT_STEP
374 	case  PT_STEP:
375 		/*
376 		 * From the 4.4BSD PRM:
377 		 * "Execution continues as in request PT_CONTINUE; however
378 		 * as soon as possible after execution of at least one
379 		 * instruction, execution stops again. [ ... ]"
380 		 */
381 #endif
382 	case  PT_CONTINUE:
383 	case  PT_DETACH:
384 		/*
385 		 * From the 4.4BSD PRM:
386 		 * "The data argument is taken as a signal number and the
387 		 * child's execution continues at location addr as if it
388 		 * incurred that signal.  Normally the signal number will
389 		 * be either 0 to indicate that the signal that caused the
390 		 * stop should be ignored, or that value fetched out of
391 		 * the process's image indicating which signal caused
392 		 * the stop.  If addr is (int *)1 then execution continues
393 		 * from where it stopped."
394 		 */
395 
396 		/* Check that the data is a valid signal number or zero. */
397 		if (SCARG(uap, data) < 0 || SCARG(uap, data) >= NSIG)
398 			return (EINVAL);
399 
400 		PHOLD(lt);
401 
402 		/* If the address parameter is not (int *)1, set the pc. */
403 		if ((int *)SCARG(uap, addr) != (int *)1)
404 			if ((error = process_set_pc(lt, SCARG(uap, addr))) != 0)
405 				goto relebad;
406 
407 #ifdef PT_STEP
408 		/*
409 		 * Arrange for a single-step, if that's requested and possible.
410 		 */
411 		error = process_sstep(lt, SCARG(uap, req) == PT_STEP);
412 		if (error)
413 			goto relebad;
414 #endif
415 
416 		PRELE(lt);
417 
418 		if (SCARG(uap, req) == PT_DETACH) {
419 			/* give process back to original parent or init */
420 			s = proclist_lock_write();
421 			if (t->p_opptr != t->p_pptr) {
422 				struct proc *pp = t->p_opptr;
423 				proc_reparent(t, pp ? pp : initproc);
424 			}
425 
426 			/* not being traced any more */
427 			t->p_opptr = NULL;
428 			proclist_unlock_write(s);
429 			CLR(t->p_flag, P_TRACED|P_WAITED);
430 		}
431 
432 	sendsig:
433 		/* Finally, deliver the requested signal (or none). */
434 		if (t->p_stat == SSTOP) {
435 			t->p_xstat = SCARG(uap, data);
436 			SCHED_LOCK(s);
437 			lr = proc_unstop(t);
438 			/*
439 			 * If the target needs to take a signal, there
440 			 * is no running LWP that will see it, and
441 			 * there is a LWP sleeping interruptably, then
442 			 * get it moving.
443 			 */
444 			if (lr && (t->p_xstat != 0))
445 			    setrunnable(lr);
446 			SCHED_UNLOCK(s);
447 		} else {
448 			if (SCARG(uap, data) != 0)
449 				psignal(t, SCARG(uap, data));
450 		}
451 		return (0);
452 
453 	relebad:
454 		PRELE(lt);
455 		return (error);
456 
457 	case  PT_KILL:
458 		/* just send the process a KILL signal. */
459 		SCARG(uap, data) = SIGKILL;
460 		goto sendsig;	/* in PT_CONTINUE, above. */
461 
462 	case  PT_ATTACH:
463 		/*
464 		 * Go ahead and set the trace flag.
465 		 * Save the old parent (it's reset in
466 		 *   _DETACH, and also in kern_exit.c:wait4()
467 		 * Reparent the process so that the tracing
468 		 *   proc gets to see all the action.
469 		 * Stop the target.
470 		 */
471 		SET(t->p_flag, P_TRACED);
472 		s = proclist_lock_write();
473 		t->p_opptr = t->p_pptr;
474 		if (t->p_pptr != p) {
475 			t->p_pptr->p_flag |= P_CHTRACED;
476 			proc_reparent(t, p);
477 		}
478 		proclist_unlock_write(s);
479 		SCARG(uap, data) = SIGSTOP;
480 		goto sendsig;
481 
482 	case PT_LWPINFO:
483 		size = SCARG(uap, data);
484 		if (size < sizeof(lwpid_t))
485 			return (EINVAL);
486 		error = copyin(SCARG(uap, addr), &pl, sizeof(lwpid_t));
487 		if (error)
488 			return (error);
489 		tmp = pl.pl_lwpid;
490 		if (tmp == 0)
491 			lt = LIST_FIRST(&t->p_lwps);
492 		else {
493 			LIST_FOREACH(lt, &t->p_lwps, l_sibling)
494 			    if (lt->l_lid == tmp)
495 				    break;
496 			if (lt == NULL)
497 				return (ESRCH);
498 			lt = LIST_NEXT(lt, l_sibling);
499 		}
500 		pl.pl_lwpid = 0;
501 		pl.pl_event = 0;
502 		if (lt) {
503 			pl.pl_lwpid = lt->l_lid;
504 			if (lt->l_lid == t->p_sigctx.ps_lwp)
505 				pl.pl_event = PL_EVENT_SIGNAL;
506 		}
507 
508 		error = copyout(&pl, SCARG(uap, addr), SCARG(uap, data));
509 
510 		return (0);
511 
512 #ifdef PT_SETREGS
513 	case  PT_SETREGS:
514 		write = 1;
515 #endif
516 #ifdef PT_GETREGS
517 	case  PT_GETREGS:
518 		/* write = 0 done above. */
519 #endif
520 #if defined(PT_SETREGS) || defined(PT_GETREGS)
521 		tmp = SCARG(uap, data);
522 		if (tmp != 0 && t->p_nlwps > 1) {
523 			LIST_FOREACH(lt, &t->p_lwps, l_sibling)
524 			    if (lt->l_lid == tmp)
525 				    break;
526 			if (lt == NULL)
527 				return (ESRCH);
528 		}
529 		if (!process_validregs(t))
530 			return (EINVAL);
531 		else {
532 			iov.iov_base = SCARG(uap, addr);
533 			iov.iov_len = sizeof(struct reg);
534 			uio.uio_iov = &iov;
535 			uio.uio_iovcnt = 1;
536 			uio.uio_offset = 0;
537 			uio.uio_resid = sizeof(struct reg);
538 			uio.uio_segflg = UIO_USERSPACE;
539 			uio.uio_rw = write ? UIO_WRITE : UIO_READ;
540 			uio.uio_procp = p;
541 			return (process_doregs(p, lt, &uio));
542 		}
543 #endif
544 
545 #ifdef PT_SETFPREGS
546 	case  PT_SETFPREGS:
547 		write = 1;
548 #endif
549 #ifdef PT_GETFPREGS
550 	case  PT_GETFPREGS:
551 		/* write = 0 done above. */
552 #endif
553 #if defined(PT_SETFPREGS) || defined(PT_GETFPREGS)
554 		tmp = SCARG(uap, data);
555 		if (tmp != 0 && t->p_nlwps > 1) {
556 			LIST_FOREACH(lt, &t->p_lwps, l_sibling)
557 			    if (lt->l_lid == tmp)
558 				    break;
559 			if (lt == NULL)
560 				return (ESRCH);
561 		}
562 		if (!process_validfpregs(t))
563 			return (EINVAL);
564 		else {
565 			iov.iov_base = SCARG(uap, addr);
566 			iov.iov_len = sizeof(struct fpreg);
567 			uio.uio_iov = &iov;
568 			uio.uio_iovcnt = 1;
569 			uio.uio_offset = 0;
570 			uio.uio_resid = sizeof(struct fpreg);
571 			uio.uio_segflg = UIO_USERSPACE;
572 			uio.uio_rw = write ? UIO_WRITE : UIO_READ;
573 			uio.uio_procp = p;
574 			return (process_dofpregs(p, lt, &uio));
575 		}
576 #endif
577 
578 #ifdef __HAVE_PTRACE_MACHDEP
579 	PTRACE_MACHDEP_REQUEST_CASES
580 		return (ptrace_machdep_dorequest(p, lt,
581 		    SCARG(uap, req), SCARG(uap, addr),
582 		    SCARG(uap, data)));
583 #endif
584 	}
585 
586 #ifdef DIAGNOSTIC
587 	panic("ptrace: impossible");
588 #endif
589 	return 0;
590 }
591 
592 int
593 process_doregs(curp, l, uio)
594 	struct proc *curp;		/* tracer */
595 	struct lwp *l;			/* traced */
596 	struct uio *uio;
597 {
598 #if defined(PT_GETREGS) || defined(PT_SETREGS)
599 	int error;
600 	struct reg r;
601 	char *kv;
602 	int kl;
603 
604 	if (uio->uio_offset < 0 || uio->uio_offset > (off_t)sizeof(r))
605 		return EINVAL;
606 
607 	if ((error = process_checkioperm(curp, l->l_proc)) != 0)
608 		return error;
609 
610 	kl = sizeof(r);
611 	kv = (char *)&r;
612 
613 	kv += uio->uio_offset;
614 	kl -= uio->uio_offset;
615 	if ((size_t)kl > uio->uio_resid)
616 		kl = uio->uio_resid;
617 
618 	PHOLD(l);
619 
620 	error = process_read_regs(l, &r);
621 	if (error == 0)
622 		error = uiomove(kv, kl, uio);
623 	if (error == 0 && uio->uio_rw == UIO_WRITE) {
624 		if (l->l_stat != LSSTOP)
625 			error = EBUSY;
626 		else
627 			error = process_write_regs(l, &r);
628 	}
629 
630 	PRELE(l);
631 
632 	uio->uio_offset = 0;
633 	return (error);
634 #else
635 	return (EINVAL);
636 #endif
637 }
638 
639 int
640 process_validregs(p)
641 	struct proc *p;
642 {
643 
644 #if defined(PT_SETREGS) || defined(PT_GETREGS)
645 	return ((p->p_flag & P_SYSTEM) == 0);
646 #else
647 	return (0);
648 #endif
649 }
650 
651 int
652 process_dofpregs(curp, l, uio)
653 	struct proc *curp;		/* tracer */
654 	struct lwp *l;			/* traced */
655 	struct uio *uio;
656 {
657 #if defined(PT_GETFPREGS) || defined(PT_SETFPREGS)
658 	int error;
659 	struct fpreg r;
660 	char *kv;
661 	int kl;
662 
663 	if (uio->uio_offset < 0 || uio->uio_offset > (off_t)sizeof(r))
664 		return EINVAL;
665 
666 	if ((error = process_checkioperm(curp, l->l_proc)) != 0)
667 		return (error);
668 
669 	kl = sizeof(r);
670 	kv = (char *)&r;
671 
672 	kv += uio->uio_offset;
673 	kl -= uio->uio_offset;
674 	if ((size_t)kl > uio->uio_resid)
675 		kl = uio->uio_resid;
676 
677 	PHOLD(l);
678 
679 	error = process_read_fpregs(l, &r);
680 	if (error == 0)
681 		error = uiomove(kv, kl, uio);
682 	if (error == 0 && uio->uio_rw == UIO_WRITE) {
683 		if (l->l_stat != LSSTOP)
684 			error = EBUSY;
685 		else
686 			error = process_write_fpregs(l, &r);
687 	}
688 
689 	PRELE(l);
690 
691 	uio->uio_offset = 0;
692 	return (error);
693 #else
694 	return (EINVAL);
695 #endif
696 }
697 
698 int
699 process_validfpregs(p)
700 	struct proc *p;
701 {
702 
703 #if defined(PT_SETFPREGS) || defined(PT_GETFPREGS)
704 	return ((p->p_flag & P_SYSTEM) == 0);
705 #else
706 	return (0);
707 #endif
708 }
709 
710 int
711 process_domem(curp, p, uio)
712 	struct proc *curp;		/* tracer */
713 	struct proc *p;			/* traced */
714 	struct uio *uio;
715 {
716 	struct vmspace *vm;
717 	int error;
718 
719 	size_t len;
720 #ifdef PMAP_NEED_PROCWR
721 	vaddr_t	addr;
722 #endif
723 
724 	len = uio->uio_resid;
725 
726 	if (len == 0)
727 		return (0);
728 
729 #ifdef PMAP_NEED_PROCWR
730 	addr = uio->uio_offset;
731 #endif
732 
733 	if ((error = process_checkioperm(curp, p)) != 0)
734 		return (error);
735 
736 	vm = p->p_vmspace;
737 
738 	simple_lock(&vm->vm_map.ref_lock);
739 	if ((p->p_flag & P_WEXIT) || vm->vm_refcnt < 1)
740 		error = EFAULT;
741 	if (error == 0)
742 		p->p_vmspace->vm_refcnt++;  /* XXX */
743 	simple_unlock(&vm->vm_map.ref_lock);
744 	if (error != 0)
745 		return (error);
746 	error = uvm_io(&vm->vm_map, uio);
747 	uvmspace_free(vm);
748 
749 #ifdef PMAP_NEED_PROCWR
750 	if (error == 0 && uio->uio_rw == UIO_WRITE)
751 		pmap_procwr(p, addr, len);
752 #endif
753 	return (error);
754 }
755 
756 /*
757  * Ensure that a process has permission to perform I/O on another.
758  * Arguments:
759  *	p	The process wishing to do the I/O (the tracer).
760  *	t	The process who's memory/registers will be read/written.
761  */
762 int
763 process_checkioperm(p, t)
764 	struct proc *p, *t;
765 {
766 	int error;
767 
768 	/*
769 	 * You cannot attach to a processes mem/regs if:
770 	 *
771 	 *	(1) It is currently exec'ing
772 	 */
773 	if (ISSET(t->p_flag, P_INEXEC))
774 		return (EAGAIN);
775 
776 	/*
777 	 *	(2) it's not owned by you, or is set-id on exec
778 	 *	    (unless you're root), or...
779 	 */
780 	if ((t->p_cred->p_ruid != p->p_cred->p_ruid ||
781 		ISSET(t->p_flag, P_SUGID)) &&
782 	    (error = suser(p->p_ucred, &p->p_acflag)) != 0)
783 		return (error);
784 
785 	/*
786 	 *	(3) ...it's init, which controls the security level
787 	 *	    of the entire system, and the system was not
788 	 *	    compiled with permanetly insecure mode turned on.
789 	 */
790 	if (t == initproc && securelevel > -1)
791 		return (EPERM);
792 
793 	/*
794 	 *	(4) the tracer is chrooted, and its root directory is
795 	 * 	    not at or above the root directory of the tracee
796 	 */
797 	if (!proc_isunder(t, p))
798 		return (EPERM);
799 
800 	return (0);
801 }
802