xref: /netbsd-src/sys/kern/sys_process.c (revision aaf4ece63a859a04e37cf3a7229b5fab0157cc06)
1 /*	$NetBSD: sys_process.c,v 1.97 2005/12/11 12:24:30 christos 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.97 2005/12/11 12:24:30 christos 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(struct lwp *l, void *v, register_t *retval)
122 {
123 	struct sys_ptrace_args /* {
124 		syscallarg(int) req;
125 		syscallarg(pid_t) pid;
126 		syscallarg(caddr_t) addr;
127 		syscallarg(int) data;
128 	} */ *uap = v;
129 	struct proc *p = l->l_proc;
130 	struct lwp *lt, *lr;
131 	struct proc *t;				/* target process */
132 	struct uio uio;
133 	struct iovec iov;
134 	struct ptrace_io_desc piod;
135 	struct ptrace_lwpinfo pl;
136 	int s, error, write, tmp, size;
137 	char *path;
138 
139 	/* "A foolish consistency..." XXX */
140 	if (SCARG(uap, req) == PT_TRACE_ME)
141 		t = p;
142 	else {
143 
144 		/* Find the process we're supposed to be operating on. */
145 		if ((t = pfind(SCARG(uap, pid))) == NULL)
146 			return (ESRCH);
147 	}
148 
149 	/* Can't trace a process that's currently exec'ing. */
150 	if ((t->p_flag & P_INEXEC) != 0)
151 		return EAGAIN;
152 
153 	/* Make sure we can operate on it. */
154 	switch (SCARG(uap, req)) {
155 	case  PT_TRACE_ME:
156 		/* Saying that you're being traced is always legal. */
157 		break;
158 
159 	case  PT_ATTACH:
160 	case  PT_DUMPCORE:
161 		/*
162 		 * You can't attach to a process if:
163 		 *	(1) it's the process that's doing the attaching,
164 		 */
165 		if (t->p_pid == p->p_pid)
166 			return (EINVAL);
167 
168 		/*
169 		 *  (2) it's a system process
170 		 */
171 		if (t->p_flag & P_SYSTEM)
172 			return (EPERM);
173 
174 		/*
175 		 *	(3) it's already being traced, or
176 		 */
177 		if (ISSET(t->p_flag, P_TRACED))
178 			return (EBUSY);
179 
180 		/*
181 		 *	(4) it's not owned by you, or is set-id on exec
182 		 *	    (unless you're root), or...
183 		 */
184 		if ((t->p_cred->p_ruid != p->p_cred->p_ruid ||
185 			ISSET(t->p_flag, P_SUGID)) &&
186 		    (error = suser(p->p_ucred, &p->p_acflag)) != 0)
187 			return (error);
188 
189 		/*
190 		 *	(5) ...it's init, which controls the security level
191 		 *	    of the entire system, and the system was not
192 		 *	    compiled with permanently insecure mode turned on
193 		 */
194 		if (t == initproc && securelevel > -1)
195 			return (EPERM);
196 
197 		/*
198 		 * (6) the tracer is chrooted, and its root directory is
199 		 * not at or above the root directory of the tracee
200 		 */
201 
202 		if (!proc_isunder(t, l))
203 			return EPERM;
204 		break;
205 
206 	case  PT_READ_I:
207 	case  PT_READ_D:
208 	case  PT_WRITE_I:
209 	case  PT_WRITE_D:
210 	case  PT_CONTINUE:
211 	case  PT_IO:
212 	case  PT_KILL:
213 	case  PT_DETACH:
214 	case  PT_LWPINFO:
215 #ifdef PT_STEP
216 	case  PT_STEP:
217 #endif
218 #ifdef PT_GETREGS
219 	case  PT_GETREGS:
220 #endif
221 #ifdef PT_SETREGS
222 	case  PT_SETREGS:
223 #endif
224 #ifdef PT_GETFPREGS
225 	case  PT_GETFPREGS:
226 #endif
227 #ifdef PT_SETFPREGS
228 	case  PT_SETFPREGS:
229 #endif
230 
231 #ifdef __HAVE_PTRACE_MACHDEP
232 	PTRACE_MACHDEP_REQUEST_CASES
233 #endif
234 
235 		/*
236 		 * You can't do what you want to the process if:
237 		 *	(1) It's not being traced at all,
238 		 */
239 		if (!ISSET(t->p_flag, P_TRACED))
240 			return (EPERM);
241 
242 		/*
243 		 *	(2) it's being traced by procfs (which has
244 		 *	    different signal delivery semantics),
245 		 */
246 		if (ISSET(t->p_flag, P_FSTRACE))
247 			return (EBUSY);
248 
249 		/*
250 		 *	(3) it's not being traced by _you_, or
251 		 */
252 		if (t->p_pptr != p)
253 			return (EBUSY);
254 
255 		/*
256 		 *	(4) it's not currently stopped.
257 		 */
258 		if (t->p_stat != SSTOP || !ISSET(t->p_flag, P_WAITED))
259 			return (EBUSY);
260 		break;
261 
262 	default:			/* It was not a legal request. */
263 		return (EINVAL);
264 	}
265 
266 	/* Do single-step fixup if needed. */
267 	FIX_SSTEP(t);
268 
269 	/*
270 	 * XXX NJWLWP
271 	 *
272 	 * The entire ptrace interface needs work to be useful to a
273 	 * process with multiple LWPs. For the moment, we'll kluge
274 	 * this; memory access will be fine, but register access will
275 	 * be weird.
276 	 */
277 
278 	lt = proc_representative_lwp(t);
279 
280 	/* Now do the operation. */
281 	write = 0;
282 	*retval = 0;
283 	tmp = 0;
284 
285 	switch (SCARG(uap, req)) {
286 	case  PT_TRACE_ME:
287 		/* Just set the trace flag. */
288 		SET(t->p_flag, P_TRACED);
289 		t->p_opptr = t->p_pptr;
290 		return (0);
291 
292 	case  PT_WRITE_I:		/* XXX no separate I and D spaces */
293 	case  PT_WRITE_D:
294 #if defined(__HAVE_RAS)
295 		/*
296 		 * Can't write to a RAS
297 		 */
298 		if (!LIST_EMPTY(&t->p_raslist) &&
299 		    (ras_lookup(t, SCARG(uap, addr)) != (caddr_t)-1)) {
300 			return (EACCES);
301 		}
302 #endif
303 		write = 1;
304 		tmp = SCARG(uap, data);
305 	case  PT_READ_I:		/* XXX no separate I and D spaces */
306 	case  PT_READ_D:
307 		/* write = 0 done above. */
308 		iov.iov_base = (caddr_t)&tmp;
309 		iov.iov_len = sizeof(tmp);
310 		uio.uio_iov = &iov;
311 		uio.uio_iovcnt = 1;
312 		uio.uio_offset = (off_t)(unsigned long)SCARG(uap, addr);
313 		uio.uio_resid = sizeof(tmp);
314 		uio.uio_segflg = UIO_SYSSPACE;
315 		uio.uio_rw = write ? UIO_WRITE : UIO_READ;
316 		uio.uio_lwp = NULL;
317 		error = process_domem(l, lt, &uio);
318 		if (!write)
319 			*retval = tmp;
320 		return (error);
321 
322 	case  PT_IO:
323 		error = copyin(SCARG(uap, addr), &piod, sizeof(piod));
324 		if (error)
325 			return (error);
326 		iov.iov_base = piod.piod_addr;
327 		iov.iov_len = piod.piod_len;
328 		uio.uio_iov = &iov;
329 		uio.uio_iovcnt = 1;
330 		uio.uio_offset = (off_t)(unsigned long)piod.piod_offs;
331 		uio.uio_resid = piod.piod_len;
332 		uio.uio_segflg = UIO_USERSPACE;
333 		uio.uio_lwp = l;
334 		switch (piod.piod_op) {
335 		case PIOD_READ_D:
336 		case PIOD_READ_I:
337 			uio.uio_rw = UIO_READ;
338 			break;
339 		case PIOD_WRITE_D:
340 		case PIOD_WRITE_I:
341 			uio.uio_rw = UIO_WRITE;
342 			break;
343 		default:
344 			return (EINVAL);
345 		}
346 		error = process_domem(l, lt, &uio);
347 		piod.piod_len -= uio.uio_resid;
348 		(void) copyout(&piod, SCARG(uap, addr), sizeof(piod));
349 		return (error);
350 
351 	case  PT_DUMPCORE:
352 		if ((path = SCARG(uap, addr)) != NULL) {
353 			char *dst;
354 			int len = SCARG(uap, data);
355 			if (len >= MAXPATHLEN)
356 				return EINVAL;
357 			dst = malloc(len + 1, M_TEMP, M_WAITOK);
358 			if ((error = copyin(path, dst, len)) != 0) {
359 				free(dst, M_TEMP);
360 				return error;
361 			}
362 			path = dst;
363 			path[len] = '\0';
364 		}
365 		error = coredump(lt, path);
366 		if (path)
367 			free(path, M_TEMP);
368 		return error;
369 
370 #ifdef PT_STEP
371 	case  PT_STEP:
372 		/*
373 		 * From the 4.4BSD PRM:
374 		 * "Execution continues as in request PT_CONTINUE; however
375 		 * as soon as possible after execution of at least one
376 		 * instruction, execution stops again. [ ... ]"
377 		 */
378 #endif
379 	case  PT_CONTINUE:
380 	case  PT_DETACH:
381 		/*
382 		 * From the 4.4BSD PRM:
383 		 * "The data argument is taken as a signal number and the
384 		 * child's execution continues at location addr as if it
385 		 * incurred that signal.  Normally the signal number will
386 		 * be either 0 to indicate that the signal that caused the
387 		 * stop should be ignored, or that value fetched out of
388 		 * the process's image indicating which signal caused
389 		 * the stop.  If addr is (int *)1 then execution continues
390 		 * from where it stopped."
391 		 */
392 
393 		/* Check that the data is a valid signal number or zero. */
394 		if (SCARG(uap, data) < 0 || SCARG(uap, data) >= NSIG)
395 			return (EINVAL);
396 
397 		PHOLD(lt);
398 
399 		/* If the address parameter is not (int *)1, set the pc. */
400 		if ((int *)SCARG(uap, addr) != (int *)1)
401 			if ((error = process_set_pc(lt, SCARG(uap, addr))) != 0)
402 				goto relebad;
403 
404 #ifdef PT_STEP
405 		/*
406 		 * Arrange for a single-step, if that's requested and possible.
407 		 */
408 		error = process_sstep(lt, SCARG(uap, req) == PT_STEP);
409 		if (error)
410 			goto relebad;
411 #endif
412 
413 		PRELE(lt);
414 
415 		if (SCARG(uap, req) == PT_DETACH) {
416 			/* give process back to original parent or init */
417 			s = proclist_lock_write();
418 			if (t->p_opptr != t->p_pptr) {
419 				struct proc *pp = t->p_opptr;
420 				proc_reparent(t, pp ? pp : initproc);
421 			}
422 
423 			/* not being traced any more */
424 			t->p_opptr = NULL;
425 			proclist_unlock_write(s);
426 			CLR(t->p_flag, P_TRACED|P_WAITED);
427 		}
428 
429 	sendsig:
430 		/* Finally, deliver the requested signal (or none). */
431 		if (t->p_stat == SSTOP) {
432 			t->p_xstat = SCARG(uap, data);
433 			SCHED_LOCK(s);
434 			lr = proc_unstop(t);
435 			/*
436 			 * If the target needs to take a signal, there
437 			 * is no running LWP that will see it, and
438 			 * there is a LWP sleeping interruptably, then
439 			 * get it moving.
440 			 */
441 			if (lr && (t->p_xstat != 0))
442 			    setrunnable(lr);
443 			SCHED_UNLOCK(s);
444 		} else {
445 			if (SCARG(uap, data) != 0)
446 				psignal(t, SCARG(uap, data));
447 		}
448 		return (0);
449 
450 	relebad:
451 		PRELE(lt);
452 		return (error);
453 
454 	case  PT_KILL:
455 		/* just send the process a KILL signal. */
456 		SCARG(uap, data) = SIGKILL;
457 		goto sendsig;	/* in PT_CONTINUE, above. */
458 
459 	case  PT_ATTACH:
460 		/*
461 		 * Go ahead and set the trace flag.
462 		 * Save the old parent (it's reset in
463 		 *   _DETACH, and also in kern_exit.c:wait4()
464 		 * Reparent the process so that the tracing
465 		 *   proc gets to see all the action.
466 		 * Stop the target.
467 		 */
468 		SET(t->p_flag, P_TRACED);
469 		s = proclist_lock_write();
470 		t->p_opptr = t->p_pptr;
471 		if (t->p_pptr != p) {
472 			t->p_pptr->p_flag |= P_CHTRACED;
473 			proc_reparent(t, p);
474 		}
475 		proclist_unlock_write(s);
476 		SCARG(uap, data) = SIGSTOP;
477 		goto sendsig;
478 
479 	case PT_LWPINFO:
480 		size = SCARG(uap, data);
481 		if (size < sizeof(lwpid_t))
482 			return (EINVAL);
483 		error = copyin(SCARG(uap, addr), &pl, sizeof(lwpid_t));
484 		if (error)
485 			return (error);
486 		tmp = pl.pl_lwpid;
487 		if (tmp == 0)
488 			lt = LIST_FIRST(&t->p_lwps);
489 		else {
490 			LIST_FOREACH(lt, &t->p_lwps, l_sibling)
491 			    if (lt->l_lid == tmp)
492 				    break;
493 			if (lt == NULL)
494 				return (ESRCH);
495 			lt = LIST_NEXT(lt, l_sibling);
496 		}
497 		pl.pl_lwpid = 0;
498 		pl.pl_event = 0;
499 		if (lt) {
500 			pl.pl_lwpid = lt->l_lid;
501 			if (lt->l_lid == t->p_sigctx.ps_lwp)
502 				pl.pl_event = PL_EVENT_SIGNAL;
503 		}
504 
505 		error = copyout(&pl, SCARG(uap, addr), SCARG(uap, data));
506 
507 		return (0);
508 
509 #ifdef PT_SETREGS
510 	case  PT_SETREGS:
511 		write = 1;
512 #endif
513 #ifdef PT_GETREGS
514 	case  PT_GETREGS:
515 		/* write = 0 done above. */
516 #endif
517 #if defined(PT_SETREGS) || defined(PT_GETREGS)
518 		tmp = SCARG(uap, data);
519 		if (tmp != 0 && t->p_nlwps > 1) {
520 			LIST_FOREACH(lt, &t->p_lwps, l_sibling)
521 			    if (lt->l_lid == tmp)
522 				    break;
523 			if (lt == NULL)
524 				return (ESRCH);
525 		}
526 		if (!process_validregs(proc_representative_lwp(t)))
527 			return (EINVAL);
528 		else {
529 			iov.iov_base = SCARG(uap, addr);
530 			iov.iov_len = sizeof(struct reg);
531 			uio.uio_iov = &iov;
532 			uio.uio_iovcnt = 1;
533 			uio.uio_offset = 0;
534 			uio.uio_resid = sizeof(struct reg);
535 			uio.uio_segflg = UIO_USERSPACE;
536 			uio.uio_rw = write ? UIO_WRITE : UIO_READ;
537 			uio.uio_lwp = l;
538 			return (process_doregs(l, lt, &uio));
539 		}
540 #endif
541 
542 #ifdef PT_SETFPREGS
543 	case  PT_SETFPREGS:
544 		write = 1;
545 #endif
546 #ifdef PT_GETFPREGS
547 	case  PT_GETFPREGS:
548 		/* write = 0 done above. */
549 #endif
550 #if defined(PT_SETFPREGS) || defined(PT_GETFPREGS)
551 		tmp = SCARG(uap, data);
552 		if (tmp != 0 && t->p_nlwps > 1) {
553 			LIST_FOREACH(lt, &t->p_lwps, l_sibling)
554 			    if (lt->l_lid == tmp)
555 				    break;
556 			if (lt == NULL)
557 				return (ESRCH);
558 		}
559 		if (!process_validfpregs(proc_representative_lwp(t)))
560 			return (EINVAL);
561 		else {
562 			iov.iov_base = SCARG(uap, addr);
563 			iov.iov_len = sizeof(struct fpreg);
564 			uio.uio_iov = &iov;
565 			uio.uio_iovcnt = 1;
566 			uio.uio_offset = 0;
567 			uio.uio_resid = sizeof(struct fpreg);
568 			uio.uio_segflg = UIO_USERSPACE;
569 			uio.uio_rw = write ? UIO_WRITE : UIO_READ;
570 			uio.uio_lwp = l;
571 			return (process_dofpregs(l, lt, &uio));
572 		}
573 #endif
574 
575 #ifdef __HAVE_PTRACE_MACHDEP
576 	PTRACE_MACHDEP_REQUEST_CASES
577 		return (ptrace_machdep_dorequest(l, lt,
578 		    SCARG(uap, req), SCARG(uap, addr),
579 		    SCARG(uap, data)));
580 #endif
581 	}
582 
583 #ifdef DIAGNOSTIC
584 	panic("ptrace: impossible");
585 #endif
586 	return 0;
587 }
588 
589 int
590 process_doregs(struct lwp *curl /*tracer*/,
591     struct lwp *l /*traced*/,
592     struct uio *uio)
593 {
594 #if defined(PT_GETREGS) || defined(PT_SETREGS)
595 	struct proc *p = l->l_proc;
596 	int error;
597 	struct reg r;
598 	char *kv;
599 	int kl;
600 
601 	if (uio->uio_offset < 0 || uio->uio_offset > (off_t)sizeof(r))
602 		return EINVAL;
603 
604 	if ((error = process_checkioperm(curl, p)) != 0)
605 		return error;
606 
607 	kl = sizeof(r);
608 	kv = (char *)&r;
609 
610 	kv += uio->uio_offset;
611 	kl -= uio->uio_offset;
612 	if ((size_t)kl > uio->uio_resid)
613 		kl = uio->uio_resid;
614 
615 	PHOLD(l);
616 
617 	error = process_read_regs(l, &r);
618 	if (error == 0)
619 		error = uiomove(kv, kl, uio);
620 	if (error == 0 && uio->uio_rw == UIO_WRITE) {
621 		if (l->l_stat != LSSTOP)
622 			error = EBUSY;
623 		else
624 			error = process_write_regs(l, &r);
625 	}
626 
627 	PRELE(l);
628 
629 	uio->uio_offset = 0;
630 	return (error);
631 #else
632 	return (EINVAL);
633 #endif
634 }
635 
636 int
637 process_validregs(struct lwp *l)
638 {
639 
640 #if defined(PT_SETREGS) || defined(PT_GETREGS)
641 	return ((l->l_proc->p_flag & P_SYSTEM) == 0);
642 #else
643 	return (0);
644 #endif
645 }
646 
647 int
648 process_dofpregs(struct lwp *curl /*tracer*/,
649     struct lwp *l /*traced*/,
650     struct uio *uio)
651 {
652 #if defined(PT_GETFPREGS) || defined(PT_SETFPREGS)
653 	struct proc *p = l->l_proc;
654 	int error;
655 	struct fpreg r;
656 	char *kv;
657 	int kl;
658 
659 	if (uio->uio_offset < 0 || uio->uio_offset > (off_t)sizeof(r))
660 		return EINVAL;
661 
662 	if ((error = process_checkioperm(curl, p)) != 0)
663 		return (error);
664 
665 	kl = sizeof(r);
666 	kv = (char *)&r;
667 
668 	kv += uio->uio_offset;
669 	kl -= uio->uio_offset;
670 	if ((size_t)kl > uio->uio_resid)
671 		kl = uio->uio_resid;
672 
673 	PHOLD(l);
674 
675 	error = process_read_fpregs(l, &r);
676 	if (error == 0)
677 		error = uiomove(kv, kl, uio);
678 	if (error == 0 && uio->uio_rw == UIO_WRITE) {
679 		if (l->l_stat != LSSTOP)
680 			error = EBUSY;
681 		else
682 			error = process_write_fpregs(l, &r);
683 	}
684 
685 	PRELE(l);
686 
687 	uio->uio_offset = 0;
688 	return (error);
689 #else
690 	return (EINVAL);
691 #endif
692 }
693 
694 int
695 process_validfpregs(struct lwp *l)
696 {
697 
698 #if defined(PT_SETFPREGS) || defined(PT_GETFPREGS)
699 	return ((l->l_proc->p_flag & P_SYSTEM) == 0);
700 #else
701 	return (0);
702 #endif
703 }
704 
705 int
706 process_domem(struct lwp *curl /*tracer*/,
707     struct lwp *l /*traced*/,
708     struct uio *uio)
709 {
710 	struct proc *p = l->l_proc;	/* traced */
711 	struct vmspace *vm;
712 	int error;
713 
714 	size_t len;
715 #ifdef PMAP_NEED_PROCWR
716 	vaddr_t	addr;
717 #endif
718 
719 	len = uio->uio_resid;
720 
721 	if (len == 0)
722 		return (0);
723 
724 #ifdef PMAP_NEED_PROCWR
725 	addr = uio->uio_offset;
726 #endif
727 
728 	if ((error = process_checkioperm(curl, p)) != 0)
729 		return (error);
730 
731 	vm = p->p_vmspace;
732 
733 	simple_lock(&vm->vm_map.ref_lock);
734 	if ((p->p_flag & P_WEXIT) || vm->vm_refcnt < 1)
735 		error = EFAULT;
736 	if (error == 0)
737 		p->p_vmspace->vm_refcnt++;  /* XXX */
738 	simple_unlock(&vm->vm_map.ref_lock);
739 	if (error != 0)
740 		return (error);
741 	error = uvm_io(&vm->vm_map, uio);
742 	uvmspace_free(vm);
743 
744 #ifdef PMAP_NEED_PROCWR
745 	if (error == 0 && uio->uio_rw == UIO_WRITE)
746 		pmap_procwr(p, addr, len);
747 #endif
748 	return (error);
749 }
750 
751 /*
752  * Ensure that a process has permission to perform I/O on another.
753  * Arguments:
754  *	p	The process wishing to do the I/O (the tracer).
755  *	t	The process who's memory/registers will be read/written.
756  */
757 int
758 process_checkioperm(struct lwp *l, struct proc *t)
759 {
760 	struct proc *p = l->l_proc;
761 	int error;
762 
763 	/*
764 	 * You cannot attach to a processes mem/regs if:
765 	 *
766 	 *	(1) It is currently exec'ing
767 	 */
768 	if (ISSET(t->p_flag, P_INEXEC))
769 		return (EAGAIN);
770 
771 	/*
772 	 *	(2) it's not owned by you, or is set-id on exec
773 	 *	    (unless you're root), or...
774 	 */
775 	if ((t->p_cred->p_ruid != p->p_cred->p_ruid ||
776 		ISSET(t->p_flag, P_SUGID)) &&
777 	    (error = suser(p->p_ucred, &p->p_acflag)) != 0)
778 		return (error);
779 
780 	/*
781 	 *	(3) ...it's init, which controls the security level
782 	 *	    of the entire system, and the system was not
783 	 *	    compiled with permanetly insecure mode turned on.
784 	 */
785 	if (t == initproc && securelevel > -1)
786 		return (EPERM);
787 
788 	/*
789 	 *	(4) the tracer is chrooted, and its root directory is
790 	 * 	    not at or above the root directory of the tracee
791 	 */
792 	if (!proc_isunder(t, l))
793 		return (EPERM);
794 
795 	return (0);
796 }
797