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