sys_process.c revision 1.18
1/*	$OpenBSD: sys_process.c,v 1.18 2002/03/11 14:20:35 art 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. All advertising materials mentioning features or use of this software
23 *    must display the following acknowledgement:
24 *	This product includes software developed by the University of
25 *	California, Berkeley and its contributors.
26 * 4. Neither the name of the University nor the names of its contributors
27 *    may be used to endorse or promote products derived from this software
28 *    without specific prior written permission.
29 *
30 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
31 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
32 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
34 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
35 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
36 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
37 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
38 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
39 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
40 * SUCH DAMAGE.
41 *
42 *	from: @(#)sys_process.c	8.1 (Berkeley) 6/10/93
43 */
44
45/*
46 * References:
47 *	(1) Bach's "The Design of the UNIX Operating System",
48 *	(2) sys/miscfs/procfs from UCB's 4.4BSD-Lite distribution,
49 *	(3) the "4.4BSD Programmer's Reference Manual" published
50 *		by USENIX and O'Reilly & Associates.
51 * The 4.4BSD PRM does a reasonably good job of documenting what the various
52 * ptrace() requests should actually do, and its text is quoted several times
53 * in this file.
54 */
55
56#include <sys/param.h>
57#include <sys/systm.h>
58#include <sys/proc.h>
59#include <sys/signalvar.h>
60#include <sys/errno.h>
61#include <sys/ptrace.h>
62#include <sys/uio.h>
63#include <sys/user.h>
64
65#include <sys/mount.h>
66#include <sys/syscallargs.h>
67
68#include <uvm/uvm_extern.h>
69
70#include <machine/reg.h>
71
72#include <miscfs/procfs/procfs.h>
73
74/*
75 * Process debugging system call.
76 */
77int
78sys_ptrace(p, v, retval)
79	struct proc *p;
80	void *v;
81	register_t *retval;
82{
83	struct sys_ptrace_args /* {
84		syscallarg(int) req;
85		syscallarg(pid_t) pid;
86		syscallarg(caddr_t) addr;
87		syscallarg(int) data;
88	} */ *uap = v;
89	struct proc *t;				/* target process */
90	struct uio uio;
91	struct iovec iov;
92	int error, write;
93	int temp;
94	struct ptrace_io_desc piod;
95
96	/* "A foolish consistency..." XXX */
97	if (SCARG(uap, req) == PT_TRACE_ME)
98		t = p;
99	else {
100
101		/* Find the process we're supposed to be operating on. */
102		if ((t = pfind(SCARG(uap, pid))) == NULL)
103			return (ESRCH);
104	}
105
106	if ((t->p_flag & P_INEXEC) != 0)
107		return (EAGAIN);
108
109	/* Make sure we can operate on it. */
110	switch (SCARG(uap, req)) {
111	case  PT_TRACE_ME:
112		/* Saying that you're being traced is always legal. */
113		break;
114
115	case  PT_ATTACH:
116		/*
117		 * You can't attach to a process if:
118		 *	(1) it's the process that's doing the attaching,
119		 */
120		if (t->p_pid == p->p_pid)
121			return (EINVAL);
122
123		/*
124		 *	(2) it's already being traced, or
125		 */
126		if (ISSET(t->p_flag, P_TRACED))
127			return (EBUSY);
128
129		/*
130		 *	(3) it's not owned by you, or the last exec
131		 *	    gave us setuid/setgid privs (unless
132		 *	    you're root), or...
133		 *
134		 *      [Note: once P_SUGID gets set in execve(), it stays
135		 *	set until the process does another execve(). Hence
136		 *	this prevents a setuid process which revokes it's
137		 *	special privilidges using setuid() from being
138		 *	traced. This is good security.]
139		 */
140		if ((t->p_cred->p_ruid != p->p_cred->p_ruid ||
141			ISSET(t->p_flag, P_SUGID)) &&
142		    (error = suser(p->p_ucred, &p->p_acflag)) != 0)
143			return (error);
144
145		/*
146		 *	(4) ...it's init, which controls the security level
147		 *	    of the entire system, and the system was not
148		 *          compiled with permanently insecure mode turned
149		 *	    on.
150		 */
151		if ((t->p_pid == 1) && (securelevel > -1))
152			return (EPERM);
153		break;
154
155	case  PT_READ_I:
156	case  PT_READ_D:
157	case  PT_WRITE_I:
158	case  PT_WRITE_D:
159	case  PT_IO:
160	case  PT_CONTINUE:
161	case  PT_KILL:
162	case  PT_DETACH:
163#ifdef PT_STEP
164	case  PT_STEP:
165#endif
166#ifdef PT_GETREGS
167	case  PT_GETREGS:
168#endif
169#ifdef PT_SETREGS
170	case  PT_SETREGS:
171#endif
172#ifdef PT_GETFPREGS
173	case  PT_GETFPREGS:
174#endif
175#ifdef PT_SETFPREGS
176	case  PT_SETFPREGS:
177#endif
178		/*
179		 * You can't do what you want to the process if:
180		 *	(1) It's not being traced at all,
181		 */
182		if (!ISSET(t->p_flag, P_TRACED))
183			return (EPERM);
184
185		/*
186		 *	(2) it's not being traced by _you_, or
187		 */
188		if (t->p_pptr != p)
189			return (EBUSY);
190
191		/*
192		 *	(3) it's not currently stopped.
193		 */
194		if (t->p_stat != SSTOP || !ISSET(t->p_flag, P_WAITED))
195			return (EBUSY);
196		break;
197
198	default:			/* It was not a legal request. */
199		return (EINVAL);
200	}
201
202	/* Do single-step fixup if needed. */
203	FIX_SSTEP(t);
204
205	/* Now do the operation. */
206	write = 0;
207	*retval = 0;
208
209	switch (SCARG(uap, req)) {
210	case  PT_TRACE_ME:
211		/* Just set the trace flag. */
212		SET(t->p_flag, P_TRACED);
213		t->p_oppid = t->p_pptr->p_pid;
214		return (0);
215
216	case  PT_WRITE_I:		/* XXX no separate I and D spaces */
217	case  PT_WRITE_D:
218		write = 1;
219		temp = SCARG(uap, data);
220	case  PT_READ_I:		/* XXX no separate I and D spaces */
221	case  PT_READ_D:
222		/* write = 0 done above. */
223		iov.iov_base = (caddr_t)&temp;
224		iov.iov_len = sizeof(int);
225		uio.uio_iov = &iov;
226		uio.uio_iovcnt = 1;
227		uio.uio_offset = (off_t)(long)SCARG(uap, addr);
228		uio.uio_resid = sizeof(int);
229		uio.uio_segflg = UIO_SYSSPACE;
230		uio.uio_rw = write ? UIO_WRITE : UIO_READ;
231		uio.uio_procp = p;
232		error = procfs_domem(p, t, NULL, &uio);
233		if (write == 0)
234			*retval = temp;
235		return (error);
236	case  PT_IO:
237		error = copyin(SCARG(uap, addr), &piod, sizeof(piod));
238		if (error)
239			return (error);
240		iov.iov_base = piod.piod_addr;
241		iov.iov_len = piod.piod_len;
242		uio.uio_iov = &iov;
243		uio.uio_iovcnt = 1;
244		uio.uio_offset = (off_t)(long)piod.piod_offs;
245		uio.uio_resid = piod.piod_len;
246		uio.uio_segflg = UIO_USERSPACE;
247		uio.uio_procp = p;
248		switch (piod.piod_op) {
249		case PIOD_OP_READ_DATA:
250		case PIOD_OP_READ_TEXT:
251			uio.uio_rw = UIO_READ;
252			break;
253		case PIOD_OP_WRITE_DATA:
254		case PIOD_OP_WRITE_TEXT:
255			uio.uio_rw = UIO_WRITE;
256			break;
257		default:
258			return (EINVAL);
259		}
260		error = procfs_domem(p, t, NULL, &uio);
261		*retval = piod.piod_len - uio.uio_resid;
262		return (error);
263#ifdef PT_STEP
264	case  PT_STEP:
265		/*
266		 * From the 4.4BSD PRM:
267		 * "Execution continues as in request PT_CONTINUE; however
268		 * as soon as possible after execution of at least one
269		 * instruction, execution stops again. [ ... ]"
270		 */
271#endif
272	case  PT_CONTINUE:
273		/*
274		 * From the 4.4BSD PRM:
275		 * "The data argument is taken as a signal number and the
276		 * child's execution continues at location addr as if it
277		 * incurred that signal.  Normally the signal number will
278		 * be either 0 to indicate that the signal that caused the
279		 * stop should be ignored, or that value fetched out of
280		 * the process's image indicating which signal caused
281		 * the stop.  If addr is (int *)1 then execution continues
282		 * from where it stopped."
283		 */
284
285		/* Check that the data is a valid signal number or zero. */
286		if (SCARG(uap, data) < 0 || SCARG(uap, data) >= NSIG)
287			return (EINVAL);
288
289		PHOLD(t);
290#ifdef PT_STEP
291		/*
292		 * Arrange for a single-step, if that's requested and possible.
293		 */
294		error = process_sstep(t, SCARG(uap, req) == PT_STEP);
295		if (error)
296			goto relebad;
297#endif
298
299		/* If the address paramter is not (int *)1, set the pc. */
300		if ((int *)SCARG(uap, addr) != (int *)1)
301			if ((error = process_set_pc(t, SCARG(uap, addr))) != 0)
302				goto relebad;
303		PRELE(t);
304		goto sendsig;
305
306	case  PT_DETACH:
307		/*
308		 * From the 4.4BSD PRM:
309		 * "The data argument is taken as a signal number and the
310		 * child's execution continues at location addr as if it
311		 * incurred that signal.  Normally the signal number will
312		 * be either 0 to indicate that the signal that caused the
313		 * stop should be ignored, or that value fetched out of
314		 * the process's image indicating which signal caused
315		 * the stop.  If addr is (int *)1 then execution continues
316		 * from where it stopped."
317		 */
318
319		/* Check that the data is a valid signal number or zero. */
320		if (SCARG(uap, data) < 0 || SCARG(uap, data) >= NSIG)
321			return (EINVAL);
322
323		PHOLD(t);
324#ifdef PT_STEP
325		/*
326		 * Arrange for a single-step, if that's requested and possible.
327		 */
328		error = process_sstep(t, SCARG(uap, req) == PT_STEP);
329		if (error)
330			goto relebad;
331#endif
332		PRELE(t);
333
334		/* give process back to original parent or init */
335		if (t->p_oppid != t->p_pptr->p_pid) {
336			struct proc *pp;
337
338			pp = pfind(t->p_oppid);
339			proc_reparent(t, pp ? pp : initproc);
340		}
341
342		/* not being traced any more */
343		t->p_oppid = 0;
344		CLR(t->p_flag, P_TRACED|P_WAITED);
345
346	sendsig:
347		/* Finally, deliver the requested signal (or none). */
348		if (t->p_stat == SSTOP) {
349			t->p_xstat = SCARG(uap, data);
350			setrunnable(t);
351		} else {
352			if (SCARG(uap, data) != 0)
353				psignal(t, SCARG(uap, data));
354		}
355		return (0);
356
357	relebad:
358		PRELE(t);
359		return (error);
360
361	case  PT_KILL:
362		/* just send the process a KILL signal. */
363		SCARG(uap, data) = SIGKILL;
364		goto sendsig;	/* in PT_CONTINUE, above. */
365
366	case  PT_ATTACH:
367		/*
368		 * As done in procfs:
369		 * Go ahead and set the trace flag.
370		 * Save the old parent (it's reset in
371		 *   _DETACH, and also in kern_exit.c:wait4()
372		 * Reparent the process so that the tracing
373		 *   proc gets to see all the action.
374		 * Stop the target.
375		 */
376		SET(t->p_flag, P_TRACED);
377		t->p_oppid = t->p_pptr->p_pid;
378		if (t->p_pptr != p)
379			proc_reparent(t, p);
380		SCARG(uap, data) = SIGSTOP;
381		goto sendsig;
382
383#ifdef PT_SETREGS
384	case  PT_SETREGS:
385		write = 1;
386#endif
387#ifdef PT_GETREGS
388	case  PT_GETREGS:
389		/* write = 0 done above. */
390#endif
391#if defined(PT_SETREGS) || defined(PT_GETREGS)
392		if (!procfs_validregs(t, NULL))
393			return (EINVAL);
394		else {
395			iov.iov_base = SCARG(uap, addr);
396			iov.iov_len = sizeof(struct reg);
397			uio.uio_iov = &iov;
398			uio.uio_iovcnt = 1;
399			uio.uio_offset = 0;
400			uio.uio_resid = sizeof(struct reg);
401			uio.uio_segflg = UIO_USERSPACE;
402			uio.uio_rw = write ? UIO_WRITE : UIO_READ;
403			uio.uio_procp = p;
404			return (procfs_doregs(p, t, NULL, &uio));
405		}
406#endif
407
408#ifdef PT_SETFPREGS
409	case  PT_SETFPREGS:
410		write = 1;
411#endif
412#ifdef PT_GETFPREGS
413	case  PT_GETFPREGS:
414		/* write = 0 done above. */
415#endif
416#if defined(PT_SETFPREGS) || defined(PT_GETFPREGS)
417		if (!procfs_validfpregs(t, NULL))
418			return (EINVAL);
419		else {
420			iov.iov_base = SCARG(uap, addr);
421			iov.iov_len = sizeof(struct fpreg);
422			uio.uio_iov = &iov;
423			uio.uio_iovcnt = 1;
424			uio.uio_offset = 0;
425			uio.uio_resid = sizeof(struct fpreg);
426			uio.uio_segflg = UIO_USERSPACE;
427			uio.uio_rw = write ? UIO_WRITE : UIO_READ;
428			uio.uio_procp = p;
429			return (procfs_dofpregs(p, t, NULL, &uio));
430		}
431#endif
432	}
433
434#ifdef DIAGNOSTIC
435	panic("ptrace: impossible");
436#endif
437	return 0;
438}
439