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