kern_procctl.c revision 46112
1/*
2 * Copyright (c) 1994, Sean Eric Fagan
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
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 *    must display the following acknowledgement:
15 *	This product includes software developed by Sean Eric Fagan.
16 * 4. The name of the author may not be used to endorse or promote products
17 *    derived from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 *
31 *	$Id: sys_process.c,v 1.43 1999/03/29 08:29:22 dfr Exp $
32 */
33
34#include <sys/param.h>
35#include <sys/systm.h>
36#include <sys/sysproto.h>
37#include <sys/proc.h>
38#include <sys/vnode.h>
39#include <sys/ptrace.h>
40
41#include <machine/reg.h>
42#include <vm/vm.h>
43#include <vm/vm_prot.h>
44#include <sys/lock.h>
45#include <vm/pmap.h>
46#include <vm/vm_map.h>
47#include <vm/vm_page.h>
48#include <vm/vm_extern.h>
49
50#include <sys/user.h>
51#include <miscfs/procfs/procfs.h>
52
53/* use the equivalent procfs code */
54#if 0
55static int
56pread (struct proc *procp, unsigned int addr, unsigned int *retval) {
57	int		rv;
58	vm_map_t	map, tmap;
59	vm_object_t	object;
60	vm_offset_t	kva = 0;
61	int		page_offset;	/* offset into page */
62	vm_offset_t	pageno;		/* page number */
63	vm_map_entry_t	out_entry;
64	vm_prot_t	out_prot;
65	boolean_t	wired;
66	vm_pindex_t	pindex;
67
68	/* Map page into kernel space */
69
70	map = &procp->p_vmspace->vm_map;
71
72	page_offset = addr - trunc_page(addr);
73	pageno = trunc_page(addr);
74
75	tmap = map;
76	rv = vm_map_lookup (&tmap, pageno, VM_PROT_READ, &out_entry,
77		&object, &pindex, &out_prot, &wired);
78
79	if (rv != KERN_SUCCESS)
80		return EINVAL;
81
82	vm_map_lookup_done (tmap, out_entry);
83
84	/* Find space in kernel_map for the page we're interested in */
85	rv = vm_map_find (kernel_map, object, IDX_TO_OFF(pindex),
86		&kva, PAGE_SIZE, 0, VM_PROT_ALL, VM_PROT_ALL, 0);
87
88	if (!rv) {
89		vm_object_reference (object);
90
91		rv = vm_map_pageable (kernel_map, kva, kva + PAGE_SIZE, 0);
92		if (!rv) {
93			*retval = 0;
94			bcopy ((caddr_t)kva + page_offset,
95			       retval, sizeof *retval);
96		}
97		vm_map_remove (kernel_map, kva, kva + PAGE_SIZE);
98	}
99
100	return rv;
101}
102
103static int
104pwrite (struct proc *procp, unsigned int addr, unsigned int datum) {
105	int		rv;
106	vm_map_t	map, tmap;
107	vm_object_t	object;
108	vm_offset_t	kva = 0;
109	int		page_offset;	/* offset into page */
110	vm_offset_t	pageno;		/* page number */
111	vm_map_entry_t	out_entry;
112	vm_prot_t	out_prot;
113	boolean_t	wired;
114	vm_pindex_t	pindex;
115	boolean_t	fix_prot = 0;
116
117	/* Map page into kernel space */
118
119	map = &procp->p_vmspace->vm_map;
120
121	page_offset = addr - trunc_page(addr);
122	pageno = trunc_page(addr);
123
124	/*
125	 * Check the permissions for the area we're interested in.
126	 */
127
128	if (vm_map_check_protection (map, pageno, pageno + PAGE_SIZE,
129		VM_PROT_WRITE) == FALSE) {
130		/*
131		 * If the page was not writable, we make it so.
132		 * XXX It is possible a page may *not* be read/executable,
133		 * if a process changes that!
134		 */
135		fix_prot = 1;
136		/* The page isn't writable, so let's try making it so... */
137		if ((rv = vm_map_protect (map, pageno, pageno + PAGE_SIZE,
138			VM_PROT_ALL, 0)) != KERN_SUCCESS)
139		  return EFAULT;	/* I guess... */
140	}
141
142	/*
143	 * Now we need to get the page.  out_entry, out_prot, wired, and
144	 * single_use aren't used.  One would think the vm code would be
145	 * a *bit* nicer...  We use tmap because vm_map_lookup() can
146	 * change the map argument.
147	 */
148
149	tmap = map;
150	rv = vm_map_lookup (&tmap, pageno, VM_PROT_WRITE, &out_entry,
151		&object, &pindex, &out_prot, &wired);
152	if (rv != KERN_SUCCESS) {
153		return EINVAL;
154	}
155
156	/*
157	 * Okay, we've got the page.  Let's release tmap.
158	 */
159
160	vm_map_lookup_done (tmap, out_entry);
161
162	/*
163	 * Fault the page in...
164	 */
165
166	rv = vm_fault(map, pageno, VM_PROT_WRITE|VM_PROT_READ, FALSE);
167	if (rv != KERN_SUCCESS)
168		return EFAULT;
169
170	/* Find space in kernel_map for the page we're interested in */
171	rv = vm_map_find (kernel_map, object, IDX_TO_OFF(pindex),
172		&kva, PAGE_SIZE, 0,
173		VM_PROT_ALL, VM_PROT_ALL, 0);
174	if (!rv) {
175		vm_object_reference (object);
176
177		rv = vm_map_pageable (kernel_map, kva, kva + PAGE_SIZE, 0);
178		if (!rv) {
179		  bcopy (&datum, (caddr_t)kva + page_offset, sizeof datum);
180		}
181		vm_map_remove (kernel_map, kva, kva + PAGE_SIZE);
182	}
183
184	if (fix_prot)
185		vm_map_protect (map, pageno, pageno + PAGE_SIZE,
186			VM_PROT_READ|VM_PROT_EXECUTE, 0);
187	return rv;
188}
189#endif
190
191/*
192 * Process debugging system call.
193 */
194#ifndef _SYS_SYSPROTO_H_
195struct ptrace_args {
196	int	req;
197	pid_t	pid;
198	caddr_t	addr;
199	int	data;
200};
201#endif
202
203int
204ptrace(curp, uap)
205	struct proc *curp;
206	struct ptrace_args *uap;
207{
208	struct proc *p;
209	struct iovec iov;
210	struct uio uio;
211	int error = 0;
212	int write;
213	int s;
214
215	if (uap->req == PT_TRACE_ME)
216		p = curp;
217	else {
218		if ((p = pfind(uap->pid)) == NULL)
219			return ESRCH;
220	}
221
222	/*
223	 * Permissions check
224	 */
225	switch (uap->req) {
226	case PT_TRACE_ME:
227		/* Always legal. */
228		break;
229
230	case PT_ATTACH:
231		/* Self */
232		if (p->p_pid == curp->p_pid)
233			return EINVAL;
234
235		/* Already traced */
236		if (p->p_flag & P_TRACED)
237			return EBUSY;
238
239		/* not owned by you, has done setuid (unless you're root) */
240		if ((p->p_cred->p_ruid != curp->p_cred->p_ruid) ||
241		     (p->p_flag & P_SUGID)) {
242			if ((error = suser(curp)) != 0)
243				return error;
244		}
245
246		/* can't trace init when securelevel > 0 */
247		if (securelevel > 0 && p->p_pid == 1)
248			return EPERM;
249
250		/* OK */
251		break;
252
253	case PT_READ_I:
254	case PT_READ_D:
255	case PT_READ_U:
256	case PT_WRITE_I:
257	case PT_WRITE_D:
258	case PT_WRITE_U:
259	case PT_CONTINUE:
260	case PT_KILL:
261	case PT_STEP:
262	case PT_DETACH:
263#ifdef PT_GETREGS
264	case PT_GETREGS:
265#endif
266#ifdef PT_SETREGS
267	case PT_SETREGS:
268#endif
269#ifdef PT_GETFPREGS
270	case PT_GETFPREGS:
271#endif
272#ifdef PT_SETFPREGS
273	case PT_SETFPREGS:
274#endif
275		/* not being traced... */
276		if ((p->p_flag & P_TRACED) == 0)
277			return EPERM;
278
279		/* not being traced by YOU */
280		if (p->p_pptr != curp)
281			return EBUSY;
282
283		/* not currently stopped */
284		if (p->p_stat != SSTOP || (p->p_flag & P_WAITED) == 0)
285			return EBUSY;
286
287		/* OK */
288		break;
289
290	default:
291		return EINVAL;
292	}
293
294#ifdef FIX_SSTEP
295	/*
296	 * Single step fixup ala procfs
297	 */
298	FIX_SSTEP(p);
299#endif
300
301	/*
302	 * Actually do the requests
303	 */
304
305	write = 0;
306	curp->p_retval[0] = 0;
307
308	switch (uap->req) {
309	case PT_TRACE_ME:
310		/* set my trace flag and "owner" so it can read/write me */
311		p->p_flag |= P_TRACED;
312		p->p_oppid = p->p_pptr->p_pid;
313		return 0;
314
315	case PT_ATTACH:
316		/* security check done above */
317		p->p_flag |= P_TRACED;
318		p->p_oppid = p->p_pptr->p_pid;
319		if (p->p_pptr != curp)
320			proc_reparent(p, curp);
321		uap->data = SIGSTOP;
322		goto sendsig;	/* in PT_CONTINUE below */
323
324	case PT_STEP:
325	case PT_CONTINUE:
326	case PT_DETACH:
327		if ((unsigned)uap->data >= NSIG)
328			return EINVAL;
329
330		PHOLD(p);
331
332		if (uap->req == PT_STEP) {
333			if ((error = ptrace_single_step (p))) {
334				PRELE(p);
335				return error;
336			}
337		}
338
339		if (uap->addr != (caddr_t)1) {
340			fill_eproc (p, &p->p_addr->u_kproc.kp_eproc);
341			if ((error = ptrace_set_pc (p,
342			    (u_long)(uintfptr_t)uap->addr))) {
343				PRELE(p);
344				return error;
345			}
346		}
347		PRELE(p);
348
349		if (uap->req == PT_DETACH) {
350			/* reset process parent */
351			if (p->p_oppid != p->p_pptr->p_pid) {
352				struct proc *pp;
353
354				pp = pfind(p->p_oppid);
355				proc_reparent(p, pp ? pp : initproc);
356			}
357
358			p->p_flag &= ~(P_TRACED | P_WAITED);
359			p->p_oppid = 0;
360
361			/* should we send SIGCHLD? */
362
363		}
364
365	sendsig:
366		/* deliver or queue signal */
367		s = splhigh();
368		if (p->p_stat == SSTOP) {
369			p->p_xstat = uap->data;
370			setrunnable(p);
371		} else if (uap->data) {
372			psignal(p, uap->data);
373		}
374		splx(s);
375		return 0;
376
377	case PT_WRITE_I:
378	case PT_WRITE_D:
379		write = 1;
380		/* fallthrough */
381	case PT_READ_I:
382	case PT_READ_D:
383		/* write = 0 set above */
384		iov.iov_base = write ? (caddr_t)&uap->data : (caddr_t)curp->p_retval;
385		iov.iov_len = sizeof(int);
386		uio.uio_iov = &iov;
387		uio.uio_iovcnt = 1;
388		uio.uio_offset = (off_t)(uintptr_t)uap->addr;
389		uio.uio_resid = sizeof(int);
390		uio.uio_segflg = UIO_SYSSPACE;	/* ie: the uap */
391		uio.uio_rw = write ? UIO_WRITE : UIO_READ;
392		uio.uio_procp = p;
393		error = procfs_domem(curp, p, NULL, &uio);
394		if (uio.uio_resid != 0) {
395			/*
396			 * XXX procfs_domem() doesn't currently return ENOSPC,
397			 * so I think write() can bogusly return 0.
398			 * XXX what happens for short writes?  We don't want
399			 * to write partial data.
400			 * XXX procfs_domem() returns EPERM for other invalid
401			 * addresses.  Convert this to EINVAL.  Does this
402			 * clobber returns of EPERM for other reasons?
403			 */
404			if (error == 0 || error == ENOSPC || error == EPERM)
405				error = EINVAL;	/* EOF */
406		}
407		return (error);
408
409	case PT_READ_U:
410		if ((uintptr_t)uap->addr > UPAGES * PAGE_SIZE - sizeof(int)) {
411			return EFAULT;
412		}
413		if ((uintptr_t)uap->addr & (sizeof(int) - 1)) {
414			return EFAULT;
415		}
416		if (ptrace_read_u_check(p,(vm_offset_t) uap->addr,
417					sizeof(int)) &&
418		    !procfs_kmemaccess(curp)) {
419			return EFAULT;
420		}
421		error = 0;
422		PHOLD(p);	/* user had damn well better be incore! */
423		if (p->p_flag & P_INMEM) {
424			p->p_addr->u_kproc.kp_proc = *p;
425			fill_eproc (p, &p->p_addr->u_kproc.kp_eproc);
426			curp->p_retval[0] = *(int *)
427			    ((uintptr_t)p->p_addr + (uintptr_t)uap->addr);
428		} else {
429			curp->p_retval[0] = 0;
430			error = EFAULT;
431		}
432		PRELE(p);
433		return error;
434
435	case PT_WRITE_U:
436		PHOLD(p);	/* user had damn well better be incore! */
437		if (p->p_flag & P_INMEM) {
438			p->p_addr->u_kproc.kp_proc = *p;
439			fill_eproc (p, &p->p_addr->u_kproc.kp_eproc);
440			error = ptrace_write_u(p, (vm_offset_t)uap->addr, uap->data);
441		} else {
442			error = EFAULT;
443		}
444		PRELE(p);
445		return error;
446
447	case PT_KILL:
448		uap->data = SIGKILL;
449		goto sendsig;	/* in PT_CONTINUE above */
450
451#ifdef PT_SETREGS
452	case PT_SETREGS:
453		write = 1;
454		/* fallthrough */
455#endif /* PT_SETREGS */
456#ifdef PT_GETREGS
457	case PT_GETREGS:
458		/* write = 0 above */
459#endif /* PT_SETREGS */
460#if defined(PT_SETREGS) || defined(PT_GETREGS)
461		if (!procfs_validregs(p))	/* no P_SYSTEM procs please */
462			return EINVAL;
463		else {
464			iov.iov_base = uap->addr;
465			iov.iov_len = sizeof(struct reg);
466			uio.uio_iov = &iov;
467			uio.uio_iovcnt = 1;
468			uio.uio_offset = 0;
469			uio.uio_resid = sizeof(struct reg);
470			uio.uio_segflg = UIO_USERSPACE;
471			uio.uio_rw = write ? UIO_WRITE : UIO_READ;
472			uio.uio_procp = curp;
473			return (procfs_doregs(curp, p, NULL, &uio));
474		}
475#endif /* defined(PT_SETREGS) || defined(PT_GETREGS) */
476
477#ifdef PT_SETFPREGS
478	case PT_SETFPREGS:
479		write = 1;
480		/* fallthrough */
481#endif /* PT_SETFPREGS */
482#ifdef PT_GETFPREGS
483	case PT_GETFPREGS:
484		/* write = 0 above */
485#endif /* PT_SETFPREGS */
486#if defined(PT_SETFPREGS) || defined(PT_GETFPREGS)
487		if (!procfs_validfpregs(p))	/* no P_SYSTEM procs please */
488			return EINVAL;
489		else {
490			iov.iov_base = uap->addr;
491			iov.iov_len = sizeof(struct fpreg);
492			uio.uio_iov = &iov;
493			uio.uio_iovcnt = 1;
494			uio.uio_offset = 0;
495			uio.uio_resid = sizeof(struct fpreg);
496			uio.uio_segflg = UIO_USERSPACE;
497			uio.uio_rw = write ? UIO_WRITE : UIO_READ;
498			uio.uio_procp = curp;
499			return (procfs_dofpregs(curp, p, NULL, &uio));
500		}
501#endif /* defined(PT_SETFPREGS) || defined(PT_GETFPREGS) */
502
503	default:
504		break;
505	}
506
507	return 0;
508}
509
510int
511trace_req(p)
512	struct proc *p;
513{
514	return 1;
515}
516
517/*
518 * stopevent()
519 * Stop a process because of a procfs event;
520 * stay stopped until p->p_step is cleared
521 * (cleared by PIOCCONT in procfs).
522 */
523
524void
525stopevent(struct proc *p, unsigned int event, unsigned int val) {
526	p->p_step = 1;
527
528	do {
529		p->p_xstat = val;
530		p->p_stype = event;	/* Which event caused the stop? */
531		wakeup(&p->p_stype);	/* Wake up any PIOCWAIT'ing procs */
532		tsleep(&p->p_step, PWAIT, "stopevent", 0);
533	} while (p->p_step);
534}
535