xref: /freebsd/sys/kern/sys_process.c (revision 0c43d89a0d8e976ca494d4837f4c1f3734d2c300)
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.5 1994/08/13 03:50:25 wollman Exp $
32  */
33 
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/proc.h>
37 #include <sys/vnode.h>
38 #include <sys/ptrace.h>
39 #include <sys/errno.h>
40 
41 #include <machine/reg.h>
42 #include <machine/psl.h>
43 #include <vm/vm.h>
44 #include <vm/vm_page.h>
45 #include <vm/vm_kern.h>
46 
47 #include <sys/user.h>
48 
49 int
50 pread (struct proc *procp, unsigned int addr, unsigned int *retval) {
51 	int		rv;
52 	vm_map_t	map, tmap;
53 	vm_object_t	object;
54 	vm_offset_t	kva = 0;
55 	int		page_offset;	/* offset into page */
56 	vm_offset_t	pageno;		/* page number */
57 	vm_map_entry_t	out_entry;
58 	vm_prot_t	out_prot;
59 	boolean_t	wired, single_use;
60 	vm_offset_t	off;
61 
62 	/* Map page into kernel space */
63 
64 	map = &procp->p_vmspace->vm_map;
65 
66 	page_offset = addr - trunc_page(addr);
67 	pageno = trunc_page(addr);
68 
69 	tmap = map;
70 	rv = vm_map_lookup (&tmap, pageno, VM_PROT_READ, &out_entry,
71 		&object, &off, &out_prot, &wired, &single_use);
72 
73 	if (rv != KERN_SUCCESS)
74 		return EINVAL;
75 
76 	vm_map_lookup_done (tmap, out_entry);
77 
78 	/* Find space in kernel_map for the page we're interested in */
79 	rv = vm_map_find (kernel_map, object, off, &kva, PAGE_SIZE, 1);
80 
81 	if (!rv) {
82 		vm_object_reference (object);
83 
84 		rv = vm_map_pageable (kernel_map, kva, kva + PAGE_SIZE, 0);
85 		if (!rv) {
86 			*retval = 0;
87 			bcopy ((caddr_t)kva + page_offset,
88 			       retval, sizeof *retval);
89 		}
90 		vm_map_remove (kernel_map, kva, kva + PAGE_SIZE);
91 	}
92 
93 	return rv;
94 }
95 
96 int
97 pwrite (struct proc *procp, unsigned int addr, unsigned int datum) {
98 	int		rv;
99 	vm_map_t	map, tmap;
100 	vm_object_t	object;
101 	vm_offset_t	kva = 0;
102 	int		page_offset;	/* offset into page */
103 	vm_offset_t	pageno;		/* page number */
104 	vm_map_entry_t	out_entry;
105 	vm_prot_t	out_prot;
106 	boolean_t	wired, single_use;
107 	vm_offset_t	off;
108 	boolean_t	fix_prot = 0;
109 
110 	/* Map page into kernel space */
111 
112 	map = &procp->p_vmspace->vm_map;
113 
114 	page_offset = addr - trunc_page(addr);
115 	pageno = trunc_page(addr);
116 
117 	/*
118 	 * Check the permissions for the area we're interested in.
119 	 */
120 
121 	if (vm_map_check_protection (map, pageno, pageno + PAGE_SIZE,
122 		VM_PROT_WRITE) == FALSE) {
123 		/*
124 		 * If the page was not writable, we make it so.
125 		 * XXX It is possible a page may *not* be read/executable,
126 		 * if a process changes that!
127 		 */
128 		fix_prot = 1;
129 		/* The page isn't writable, so let's try making it so... */
130 		if ((rv = vm_map_protect (map, pageno, pageno + PAGE_SIZE,
131 			VM_PROT_ALL, 0)) != KERN_SUCCESS)
132 		  return EFAULT;	/* I guess... */
133 	}
134 
135 	/*
136 	 * Now we need to get the page.  out_entry, out_prot, wired, and
137 	 * single_use aren't used.  One would think the vm code would be
138 	 * a *bit* nicer...  We use tmap because vm_map_lookup() can
139 	 * change the map argument.
140 	 */
141 
142 	tmap = map;
143 	rv = vm_map_lookup (&tmap, pageno, VM_PROT_WRITE, &out_entry,
144 		&object, &off, &out_prot, &wired, &single_use);
145 	if (rv != KERN_SUCCESS) {
146 		return EINVAL;
147 	}
148 
149 	/*
150 	 * Okay, we've got the page.  Let's release tmap.
151 	 */
152 
153 	vm_map_lookup_done (tmap, out_entry);
154 
155 	/*
156 	 * Fault the page in...
157 	 */
158 
159 	rv = vm_fault (map, pageno, VM_PROT_WRITE, FALSE);
160 	if (rv != KERN_SUCCESS)
161 		return EFAULT;
162 
163 	/*
164 	 * The page may need to be faulted in again, it seems.
165 	 * This covers COW pages, I believe.
166 	 */
167 
168 	if (!rv)
169 		rv = vm_fault (map, pageno, VM_PROT_WRITE, 0);
170 
171 	/* Find space in kernel_map for the page we're interested in */
172 	rv = vm_map_find (kernel_map, object, off, &kva, PAGE_SIZE, 1);
173 
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 
190 /*
191  * Process debugging system call.
192  */
193 struct ptrace_args {
194 	int	req;
195 	pid_t	pid;
196 	caddr_t	addr;
197 	int	data;
198 };
199 
200 int
201 ptrace(curp, uap, retval)
202 	struct proc *curp;
203 	struct ptrace_args *uap;
204 	int *retval;
205 {
206 	struct proc *p;
207 	int s, error = 0;
208 
209 	*retval = 0;
210 	if (uap->req == PT_TRACE_ME) {
211 		curp->p_flag |= P_TRACED;
212 		return 0;
213 	}
214 	if ((p = pfind(uap->pid)) == NULL) {
215 		return ESRCH;
216 	}
217 
218 #ifdef PT_ATTACH
219 	if (uap->req != PT_ATTACH && (
220 			(p->p_flag & P_TRACED) == 0 ||
221 			(p->p_tptr && curp != p->p_tptr) ||
222 			(!p->p_tptr && curp != p->p_pptr)))
223 
224 		return ESRCH;
225 #endif
226 #ifdef PT_ATTACH
227 	if (uap->req != PT_ATTACH) {
228 #endif
229 		if ((p->p_flag & P_TRACED) == 0)
230 			return EPERM;
231 		if (p->p_stat != SSTOP || (p->p_flag & P_WAITED) == 0)
232 			return EBUSY;
233 #ifdef PT_ATTACH
234 	}
235 #endif
236 	/*
237 	 * XXX The PT_ATTACH code is completely broken.  It will
238 	 * be obsoleted by a /proc filesystem, so is it worth it
239 	 * to fix it?  (Answer, probably.  So that'll be next,
240 	 * I guess.)
241 	 */
242 
243 	switch (uap->req) {
244 #ifdef PT_ATTACH
245 	case PT_ATTACH:
246 		if (curp->p_ucred->cr_uid != 0 && (
247 			curp->p_ucred->cr_uid != p->p_ucred->cr_uid ||
248 			curp->p_ucred->cr_uid != p->p_cred->p_svuid))
249 			return EACCES;
250 
251 		p->p_tptr = curp;
252 		p->p_flag |= P_TRACED;
253 		psignal(p, SIGSTOP);
254 		return 0;
255 
256 	case PT_DETACH:
257 		if ((unsigned)uap->data >= NSIG)
258 			return EINVAL;
259 		p->p_flag &= ~P_TRACED;
260 		p->p_tptr = NULL;
261 		psignal(p->p_pptr, SIGCHLD);
262 		wakeup((caddr_t)p->p_pptr);
263 		s = splhigh();
264 		if (p->p_stat == SSTOP) {
265 			p->p_xstat = uap->data;
266 			setrunnable(p);
267 		} else if (uap->data) {
268 			psignal(p, uap->data);
269 		}
270 		splx(s);
271 		return 0;
272 
273 # ifdef PT_INHERIT
274 	case PT_INHERIT:
275 		if ((p->p_flag & P_TRACED) == 0)
276 			return ESRCH;
277 		return 0;
278 # endif	/* PT_INHERIT */
279 #endif	/* PT_ATTACH */
280 
281 	case PT_READ_I:
282 	case PT_READ_D:
283 		if (error = pread (p, (unsigned int)uap->addr, retval))
284 			return error;
285 		return 0;
286 	case PT_WRITE_I:
287 	case PT_WRITE_D:
288 		if (error = pwrite (p, (unsigned int)uap->addr,
289 				    (unsigned int)uap->data))
290 			return error;
291 		return 0;
292 	case PT_STEP:
293 		if (error = ptrace_single_step (p))
294 			return error;
295 		/* fallthrough */
296 	case PT_CONTINUE:
297 		/*
298 		 * Continue at addr uap->addr with signal
299 		 * uap->data; if uap->addr is 1, then we just
300 		 * let the chips fall where they may.
301 		 *
302 		 * The only check I'll make right now is for
303 		 * uap->data to be larger than NSIG; if so, we return
304 		 * EINVAL.
305 		 */
306 		if (uap->data >= NSIG)
307 			return EINVAL;
308 
309 		if (uap->addr != (caddr_t)1) {
310 			fill_eproc (p, &p->p_addr->u_kproc.kp_eproc);
311 			if (error = ptrace_set_pc (p, uap->addr))
312 				return error;
313 		}
314 
315 		p->p_xstat = uap->data;
316 
317 /*		if (p->p_stat == SSTOP) */
318 		setrunnable (p);
319 		return 0;
320 	case PT_READ_U:
321 		if ((u_int)uap->addr > (UPAGES * NBPG - sizeof(int))) {
322 			return EFAULT;
323 		}
324 		p->p_addr->u_kproc.kp_proc = *p;
325 		fill_eproc (p, &p->p_addr->u_kproc.kp_eproc);
326 		*retval = *(int*)((u_int)p->p_addr + (u_int)uap->addr);
327 		return 0;
328 	case PT_WRITE_U:
329 		if ((u_int)uap->addr > (UPAGES * NBPG - sizeof(int))) {
330 			return EFAULT;
331 		}
332 		p->p_addr->u_kproc.kp_proc = *p;
333 		fill_eproc (p, &p->p_addr->u_kproc.kp_eproc);
334 		*(int*)((u_int)p->p_addr + (u_int)uap->addr) = uap->data;
335 		return 0;
336 	case PT_KILL:
337 		p->p_xstat = SIGKILL;
338 		setrunnable(p);
339 		return 0;
340 #ifdef PT_GETREGS
341 	case PT_GETREGS:
342 		/*
343 		 * copyout the registers into addr.  There's no
344 		 * size constraint!!! *GRRR*
345 		 */
346 		return ptrace_getregs(p, uap->addr);
347 	case PT_SETREGS:
348 		/*
349 		 * copyin the registers from addr.  Again, no
350 		 * size constraint!!! *GRRRR*
351 		 */
352 		return ptrace_setregs (p, uap->addr);
353 #endif /* PT_GETREGS */
354 	default:
355 		break;
356 	}
357 
358 	return 0;
359 }
360 
361 int
362 trace_req(p)
363 	struct proc *p;
364 {
365 	return 1;
366 }
367