1. Remove a rather strangely gratuitous bit of profanity
[unix-history] / sys / kern / sys_process.c
CommitLineData
15637ed4
RG
1/*
2 * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
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 the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 * from: @(#)sys_process.c 7.22 (Berkeley) 5/11/91
0750b35e 34 * $Id: sys_process.c,v 1.10 1994/02/26 07:17:53 davidg Exp $
15637ed4
RG
35 */
36
15637ed4 37#include "param.h"
4c45483e 38#include "systm.h"
15637ed4
RG
39#include "proc.h"
40#include "vnode.h"
41#include "buf.h"
42#include "ptrace.h"
43
44#include "machine/reg.h"
45#include "machine/psl.h"
46#include "vm/vm.h"
47#include "vm/vm_page.h"
047f13c9 48#include "vm/vm_kern.h"
15637ed4
RG
49
50#include "user.h"
51
52/*
53 * NOTES.
54 *
55 * The following ptrace calls have been defined in addition to
56 * the standard ones found in original <sys/ptrace.h>:
57 *
58 * PT_ATTACH - attach to running process
59 * PT_DETACH - detach from running process
60 * PT_SYSCALL - trace system calls
61 * PT_GETREG - get register file
62 * PT_SETREG - set register file
63 * PT_BREAD_[IDU] - block read from process (not yet implemented)
64 * PT_BWRITE_[IDU] - block write " "
65 * PT_INHERIT - make forked processes inherit trace flags
66 *
67 */
68
69/* Define to prevent extraneous clutter in source */
70#ifndef SSTRC
71#define SSTRC 0
72#endif
73#ifndef SFTRC
74#define SFTRC 0
75#endif
76
047f13c9
DG
77int
78pread (struct proc *procp, unsigned int addr, unsigned int *retval) {
79 int rv;
80 vm_map_t map, tmap;
81 vm_object_t object;
b9466c20 82 vm_offset_t kva = 0;
047f13c9
DG
83 int page_offset; /* offset into page */
84 vm_offset_t pageno; /* page number */
85 vm_map_entry_t out_entry;
86 vm_prot_t out_prot;
87 boolean_t wired, single_use;
88 vm_offset_t off;
89
90 /* Map page into kernel space */
91
92 map = &procp->p_vmspace->vm_map;
93
94 page_offset = addr - trunc_page(addr);
95 pageno = trunc_page(addr);
96
97 tmap = map;
98 rv = vm_map_lookup (&tmap, pageno, VM_PROT_READ, &out_entry,
99 &object, &off, &out_prot, &wired, &single_use);
100
101 if (rv != KERN_SUCCESS)
102 return EINVAL;
103
104 vm_map_lookup_done (tmap, out_entry);
105
106 /* Find space in kernel_map for the page we're interested in */
107 rv = vm_map_find (kernel_map, object, off, &kva, PAGE_SIZE, 1);
108
109 if (!rv) {
110 vm_object_reference (object);
111
112 rv = vm_map_pageable (kernel_map, kva, kva + PAGE_SIZE, 0);
113 if (!rv) {
114 *retval = 0;
4c45483e
GW
115 bcopy ((caddr_t)(kva + page_offset), retval,
116 sizeof *retval);
047f13c9
DG
117 }
118 vm_map_remove (kernel_map, kva, kva + PAGE_SIZE);
119 }
15637ed4 120
047f13c9
DG
121 return rv;
122}
123
124int
125pwrite (struct proc *procp, unsigned int addr, unsigned int datum) {
126 int rv;
127 vm_map_t map, tmap;
128 vm_object_t object;
b9466c20 129 vm_offset_t kva = 0;
047f13c9
DG
130 int page_offset; /* offset into page */
131 vm_offset_t pageno; /* page number */
132 vm_map_entry_t out_entry;
133 vm_prot_t out_prot;
134 boolean_t wired, single_use;
135 vm_offset_t off;
136 boolean_t fix_prot = 0;
137
138 /* Map page into kernel space */
139
140 map = &procp->p_vmspace->vm_map;
141
142 page_offset = addr - trunc_page(addr);
143 pageno = trunc_page(addr);
144
145 /*
146 * Check the permissions for the area we're interested in.
147 */
148
149 if (vm_map_check_protection (map, pageno, pageno + PAGE_SIZE,
150 VM_PROT_WRITE) == FALSE) {
151 /*
152 * If the page was not writable, we make it so.
153 * XXX It is possible a page may *not* be read/executable,
154 * if a process changes that!
155 */
156 fix_prot = 1;
157 /* The page isn't writable, so let's try making it so... */
158 if ((rv = vm_map_protect (map, pageno, pageno + PAGE_SIZE,
159 VM_PROT_ALL, 0)) != KERN_SUCCESS)
160 return EFAULT; /* I guess... */
161 }
162
163 /*
164 * Now we need to get the page. out_entry, out_prot, wired, and
165 * single_use aren't used. One would think the vm code would be
166 * a *bit* nicer... We use tmap because vm_map_lookup() can
167 * change the map argument.
168 */
169
170 tmap = map;
171 rv = vm_map_lookup (&tmap, pageno, VM_PROT_WRITE, &out_entry,
172 &object, &off, &out_prot, &wired, &single_use);
173 if (rv != KERN_SUCCESS) {
174 return EINVAL;
175 }
176
177 /*
178 * Okay, we've got the page. Let's release tmap.
179 */
180
181 vm_map_lookup_done (tmap, out_entry);
182
e2c47b5a
DG
183 /*
184 * Fault the page-table-page in...
185 */
186 vm_map_pageable(map, trunc_page(vtopte(pageno)),
187 trunc_page(vtopte(pageno)) + NBPG, FALSE);
047f13c9
DG
188 /*
189 * Fault the page in...
190 */
191
192 rv = vm_fault (map, pageno, VM_PROT_WRITE, FALSE);
e2c47b5a
DG
193 if (rv != KERN_SUCCESS) {
194 /*
195 * release the page table page
196 */
197 vm_map_pageable(map, trunc_page(vtopte(pageno)),
198 trunc_page(vtopte(pageno)) + NBPG, TRUE);
047f13c9 199 return EFAULT;
e2c47b5a 200 }
047f13c9
DG
201
202 /*
203 * The page may need to be faulted in again, it seems.
204 * This covers COW pages, I believe.
205 */
206
207 if (!rv)
208 rv = vm_fault (map, pageno, VM_PROT_WRITE, 0);
209
210 /* Find space in kernel_map for the page we're interested in */
fde1aeb2
GW
211 rv = vm_map_find (kernel_map, object, off, (vm_offset_t *)&kva,
212 PAGE_SIZE, 1);
047f13c9
DG
213
214 if (!rv) {
215 vm_object_reference (object);
216
e2c47b5a 217 rv = vm_map_pageable (kernel_map, kva, kva + PAGE_SIZE, FALSE);
047f13c9 218 if (!rv) {
4c45483e 219 bcopy (&datum, (caddr_t)(kva + page_offset), sizeof datum);
047f13c9
DG
220 }
221 vm_map_remove (kernel_map, kva, kva + PAGE_SIZE);
222 }
223
224 if (fix_prot)
225 vm_map_protect (map, pageno, pageno + PAGE_SIZE,
226 VM_PROT_READ|VM_PROT_EXECUTE, 0);
e2c47b5a
DG
227
228 /*
229 * release the page table page
230 */
231 vm_map_pageable(map, trunc_page(vtopte(pageno)),
232 trunc_page(vtopte(pageno)) + NBPG, TRUE);
233
047f13c9
DG
234 return rv;
235}
3c7eb27c
DG
236
237struct ptrace_args {
238 int req;
239 int pid;
240 int *addr;
241 int data;
242};
243
047f13c9
DG
244/*
245 * Process debugging system call.
246 */
4c45483e 247int
15637ed4
RG
248ptrace(curp, uap, retval)
249 struct proc *curp;
3c7eb27c 250 register struct ptrace_args *uap;
15637ed4
RG
251 int *retval;
252{
253 struct proc *p;
254 int s, error = 0;
255
256 *retval = 0;
257 if (uap->req == PT_TRACE_ME) {
258 curp->p_flag |= STRC;
15637ed4
RG
259 return 0;
260 }
261 if ((p = pfind(uap->pid)) == NULL) {
262 return ESRCH;
263 }
264
047f13c9 265#ifdef PT_ATTACH
15637ed4
RG
266 if (uap->req != PT_ATTACH && (
267 (p->p_flag & STRC) == 0 ||
268 (p->p_tptr && curp != p->p_tptr) ||
269 (!p->p_tptr && curp != p->p_pptr)))
270
271 return ESRCH;
272#endif
15637ed4 273#ifdef PT_ATTACH
047f13c9
DG
274 if (uap->req != PT_ATTACH) {
275#endif
276 if ((p->p_flag & STRC) == 0)
277 return EPERM;
278 if (p->p_stat != SSTOP || (p->p_flag & SWTED) == 0)
279 return EBUSY;
280#ifdef PT_ATTACH
281 }
282#endif
283 /*
284 * XXX The PT_ATTACH code is completely broken. It will
285 * be obsoleted by a /proc filesystem, so is it worth it
286 * to fix it? (Answer, probably. So that'll be next,
287 * I guess.)
288 */
289
15637ed4 290 switch (uap->req) {
047f13c9 291#ifdef PT_ATTACH
15637ed4
RG
292 case PT_ATTACH:
293 if (curp->p_ucred->cr_uid != 0 && (
294 curp->p_ucred->cr_uid != p->p_ucred->cr_uid ||
295 curp->p_ucred->cr_uid != p->p_cred->p_svuid))
296 return EACCES;
297
298 p->p_tptr = curp;
299 p->p_flag |= STRC;
047f13c9 300 psignal(p, SIGSTOP);
15637ed4
RG
301 return 0;
302
303 case PT_DETACH:
304 if ((unsigned)uap->data >= NSIG)
305 return EINVAL;
306 p->p_flag &= ~(STRC|SSTRC|SFTRC);
307 p->p_tptr = NULL;
308 psignal(p->p_pptr, SIGCHLD);
309 wakeup((caddr_t)p->p_pptr);
310 s = splhigh();
311 if (p->p_stat == SSTOP) {
312 p->p_xstat = uap->data;
313 setrun(p);
314 } else if (uap->data) {
315 psignal(p, uap->data);
316 }
317 splx(s);
318 return 0;
319
047f13c9 320# ifdef PT_INHERIT
15637ed4
RG
321 case PT_INHERIT:
322 if ((p->p_flag & STRC) == 0)
323 return ESRCH;
324 p->p_flag |= SFTRC;
325 return 0;
047f13c9
DG
326# endif /* PT_INHERIT */
327#endif /* PT_ATTACH */
15637ed4 328
15637ed4
RG
329 case PT_READ_I:
330 case PT_READ_D:
047f13c9
DG
331 if (error = pread (p, (unsigned int)uap->addr, retval))
332 return error;
333 return 0;
15637ed4 334 case PT_WRITE_I:
047f13c9
DG
335 case PT_WRITE_D:
336 if (error = pwrite (p, (unsigned int)uap->addr,
337 (unsigned int)uap->data))
338 return error;
339 return 0;
340 case PT_STEP:
341 if (error = ptrace_single_step (p))
342 return error;
343 /* fallthrough */
344 case PT_CONTINUE:
dd18dc33 345 /*
047f13c9
DG
346 * Continue at addr uap->addr with signal
347 * uap->data; if uap->addr is 1, then we just
348 * let the chips fall where they may.
349 *
350 * The only check I'll make right now is for
351 * uap->data to be larger than NSIG; if so, we return
352 * EINVAL.
dd18dc33 353 */
047f13c9
DG
354 if (uap->data >= NSIG)
355 return EINVAL;
15637ed4 356
047f13c9
DG
357 if (uap->addr != (int*)1) {
358 fill_eproc (p, &p->p_addr->u_kproc.kp_eproc);
359 if (error = ptrace_set_pc (p, uap->addr))
360 return error;
15637ed4 361 }
15637ed4 362
047f13c9 363 p->p_xstat = uap->data;
15637ed4 364
047f13c9
DG
365/* if (p->p_stat == SSTOP) */
366 setrun (p);
367 return 0;
368 case PT_READ_U:
369 if ((u_int)uap->addr > (UPAGES * NBPG - sizeof(int))) {
370 return EFAULT;
15637ed4 371 }
047f13c9
DG
372 p->p_addr->u_kproc.kp_proc = *p;
373 fill_eproc (p, &p->p_addr->u_kproc.kp_eproc);
374 *retval = *(int*)((u_int)p->p_addr + (u_int)uap->addr);
375 return 0;
376 case PT_WRITE_U:
377 if ((u_int)uap->addr > (UPAGES * NBPG - sizeof(int))) {
378 return EFAULT;
15637ed4 379 }
047f13c9
DG
380 p->p_addr->u_kproc.kp_proc = *p;
381 fill_eproc (p, &p->p_addr->u_kproc.kp_eproc);
382 *(int*)((u_int)p->p_addr + (u_int)uap->addr) = uap->data;
383 return 0;
384 case PT_KILL:
385 p->p_xstat = SIGKILL;
386 setrun(p);
387 return 0;
15637ed4
RG
388#ifdef PT_GETREGS
389 case PT_GETREGS:
047f13c9
DG
390 /*
391 * copyout the registers into addr. There's no
392 * size constraint!!! *GRRR*
393 */
394 return ptrace_getregs(p, uap->addr);
15637ed4 395 case PT_SETREGS:
047f13c9
DG
396 /*
397 * copyin the registers from addr. Again, no
398 * size constraint!!! *GRRRR*
399 */
400 return ptrace_setregs (p, uap->addr);
401#endif /* PT_GETREGS */
15637ed4 402 default:
047f13c9 403 break;
15637ed4 404 }
15637ed4 405
047f13c9
DG
406 return 0;
407}
15637ed4 408
4c45483e 409int
047f13c9
DG
410procxmt(p)
411 register struct proc *p;
412{
413 return 1;
15637ed4
RG
414}
415
416/*
417 * Enable process profiling system call.
418 */
3c7eb27c
DG
419
420struct profil_args {
421 short *bufbase; /* base of data buffer */
422 unsigned bufsize; /* size of data buffer */
423 unsigned pcoffset; /* pc offset (for subtraction) */
424 unsigned pcscale; /* scaling factor for offset pc */
425};
426
15637ed4 427/* ARGSUSED */
4c45483e 428int
15637ed4
RG
429profil(p, uap, retval)
430 struct proc *p;
3c7eb27c 431 register struct profil_args *uap;
15637ed4
RG
432 int *retval;
433{
434 /* from looking at man pages, and include files, looks like
435 * this just sets up the fields of p->p_stats->p_prof...
436 * and those fields come straight from the args.
437 * only thing *we* have to do is check the args for validity...
438 *
439 * cgd
440 */
441
442 /* check to make sure that the buffer is OK. addupc (in locore)
443 * checks for faults, but would one be generated, say, writing to
444 * kernel space? probably not -- it just uses "movl"...
445 *
446 * so we've gotta check to make sure that the info set up for
447 * addupc is set right... it's gotta be writable by the user...
0750b35e
JH
448 *
449 * Add a little extra sanity checking so that end profil requests
450 * don't generate spurious faults. -jkh
15637ed4
RG
451 */
452
0750b35e
JH
453 if (uap->bufbase && uap->bufsize &&
454 useracc((caddr_t)uap->bufbase, uap->bufsize * sizeof(short),
fde1aeb2 455 B_WRITE) == 0)
15637ed4
RG
456 return EFAULT;
457
458 p->p_stats->p_prof.pr_base = uap->bufbase;
459 p->p_stats->p_prof.pr_size = uap->bufsize;
460 p->p_stats->p_prof.pr_off = uap->pcoffset;
461 p->p_stats->p_prof.pr_scale = uap->pcscale;
462
463 return 0;
464}