1 /* $NetBSD: sys_process.c,v 1.95.2.3 2006/11/11 21:40:19 bouyer Exp $ */
2
3 /*-
4 * Copyright (c) 1982, 1986, 1989, 1993
5 * The Regents of the University of California. All rights reserved.
6 * (c) UNIX System Laboratories, Inc.
7 * All or some portions of this file are derived from material licensed
8 * to the University of California by American Telephone and Telegraph
9 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
10 * the permission of UNIX System Laboratories, Inc.
11 *
12 * This code is derived from software contributed to Berkeley by
13 * Jan-Simon Pendry.
14 *
15 * Redistribution and use in source and binary forms, with or without
16 * modification, are permitted provided that the following conditions
17 * are met:
18 * 1. Redistributions of source code must retain the above copyright
19 * notice, this list of conditions and the following disclaimer.
20 * 2. Redistributions in binary form must reproduce the above copyright
21 * notice, this list of conditions and the following disclaimer in the
22 * documentation and/or other materials provided with the distribution.
23 * 3. Neither the name of the University nor the names of its contributors
24 * may be used to endorse or promote products derived from this software
25 * without specific prior written permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 * SUCH DAMAGE.
38 *
39 * from: @(#)sys_process.c 8.1 (Berkeley) 6/10/93
40 */
41
42 /*-
43 * Copyright (c) 1993 Jan-Simon Pendry.
44 * Copyright (c) 1994 Christopher G. Demetriou. All rights reserved.
45 *
46 * This code is derived from software contributed to Berkeley by
47 * Jan-Simon Pendry.
48 *
49 * Redistribution and use in source and binary forms, with or without
50 * modification, are permitted provided that the following conditions
51 * are met:
52 * 1. Redistributions of source code must retain the above copyright
53 * notice, this list of conditions and the following disclaimer.
54 * 2. Redistributions in binary form must reproduce the above copyright
55 * notice, this list of conditions and the following disclaimer in the
56 * documentation and/or other materials provided with the distribution.
57 * 3. All advertising materials mentioning features or use of this software
58 * must display the following acknowledgement:
59 * This product includes software developed by the University of
60 * California, Berkeley and its contributors.
61 * 4. Neither the name of the University nor the names of its contributors
62 * may be used to endorse or promote products derived from this software
63 * without specific prior written permission.
64 *
65 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
66 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
67 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
68 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
69 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
70 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
71 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
72 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
73 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
74 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
75 * SUCH DAMAGE.
76 *
77 * from: @(#)sys_process.c 8.1 (Berkeley) 6/10/93
78 */
79
80 /*
81 * References:
82 * (1) Bach's "The Design of the UNIX Operating System",
83 * (2) sys/miscfs/procfs from UCB's 4.4BSD-Lite distribution,
84 * (3) the "4.4BSD Programmer's Reference Manual" published
85 * by USENIX and O'Reilly & Associates.
86 * The 4.4BSD PRM does a reasonably good job of documenting what the various
87 * ptrace() requests should actually do, and its text is quoted several times
88 * in this file.
89 */
90
91 #include <sys/cdefs.h>
92 __KERNEL_RCSID(0, "$NetBSD: sys_process.c,v 1.95.2.3 2006/11/11 21:40:19 bouyer Exp $");
93
94 #include <sys/param.h>
95 #include <sys/systm.h>
96 #include <sys/proc.h>
97 #include <sys/errno.h>
98 #include <sys/ptrace.h>
99 #include <sys/uio.h>
100 #include <sys/user.h>
101 #include <sys/ras.h>
102 #include <sys/malloc.h>
103
104 #include <sys/mount.h>
105 #include <sys/sa.h>
106 #include <sys/syscallargs.h>
107
108 #include <uvm/uvm_extern.h>
109
110 #include <machine/reg.h>
111
112 /* Macros to clear/set/test flags. */
113 #define SET(t, f) (t) |= (f)
114 #define CLR(t, f) (t) &= ~(f)
115 #define ISSET(t, f) ((t) & (f))
116
117 /*
118 * Process debugging system call.
119 */
120 int
121 sys_ptrace(l, v, retval)
122 struct lwp *l;
123 void *v;
124 register_t *retval;
125 {
126 struct sys_ptrace_args /* {
127 syscallarg(int) req;
128 syscallarg(pid_t) pid;
129 syscallarg(caddr_t) addr;
130 syscallarg(int) data;
131 } */ *uap = v;
132 struct proc *p = l->l_proc;
133 struct lwp *lt, *lr;
134 struct proc *t; /* target process */
135 struct uio uio;
136 struct iovec iov;
137 struct ptrace_io_desc piod;
138 struct ptrace_lwpinfo pl;
139 int s, error, write, tmp;
140 char *path;
141
142 /* "A foolish consistency..." XXX */
143 if (SCARG(uap, req) == PT_TRACE_ME)
144 t = p;
145 else {
146
147 /* Find the process we're supposed to be operating on. */
148 if ((t = pfind(SCARG(uap, pid))) == NULL)
149 return (ESRCH);
150 }
151
152 /* Can't trace a process that's currently exec'ing. */
153 if ((t->p_flag & P_INEXEC) != 0)
154 return EAGAIN;
155
156 /* Make sure we can operate on it. */
157 switch (SCARG(uap, req)) {
158 case PT_TRACE_ME:
159 /* Saying that you're being traced is always legal. */
160 break;
161
162 case PT_ATTACH:
163 case PT_DUMPCORE:
164 /*
165 * You can't attach to a process if:
166 * (1) it's the process that's doing the attaching,
167 */
168 if (t->p_pid == p->p_pid)
169 return (EINVAL);
170
171 /*
172 * (2) it's a system process
173 */
174 if (t->p_flag & P_SYSTEM)
175 return (EPERM);
176
177 /*
178 * (3) it's already being traced, or
179 */
180 if (ISSET(t->p_flag, P_TRACED))
181 return (EBUSY);
182
183 /*
184 * (4) it's not owned by you, or is set-id on exec
185 * (unless you're root), or...
186 */
187 if ((t->p_cred->p_ruid != p->p_cred->p_ruid ||
188 ISSET(t->p_flag, P_SUGID)) &&
189 (error = suser(p->p_ucred, &p->p_acflag)) != 0)
190 return (error);
191
192 /*
193 * (5) ...it's init, which controls the security level
194 * of the entire system, and the system was not
195 * compiled with permanently insecure mode turned on
196 */
197 if (t == initproc && securelevel > -1)
198 return (EPERM);
199
200 /*
201 * (6) the tracer is chrooted, and its root directory is
202 * not at or above the root directory of the tracee
203 */
204
205 if (!proc_isunder(t, p))
206 return EPERM;
207 break;
208
209 case PT_READ_I:
210 case PT_READ_D:
211 case PT_WRITE_I:
212 case PT_WRITE_D:
213 case PT_CONTINUE:
214 case PT_IO:
215 case PT_KILL:
216 case PT_DETACH:
217 case PT_LWPINFO:
218 #ifdef PT_STEP
219 case PT_STEP:
220 #endif
221 #ifdef PT_GETREGS
222 case PT_GETREGS:
223 #endif
224 #ifdef PT_SETREGS
225 case PT_SETREGS:
226 #endif
227 #ifdef PT_GETFPREGS
228 case PT_GETFPREGS:
229 #endif
230 #ifdef PT_SETFPREGS
231 case PT_SETFPREGS:
232 #endif
233
234 #ifdef __HAVE_PTRACE_MACHDEP
235 PTRACE_MACHDEP_REQUEST_CASES
236 #endif
237
238 /*
239 * You can't do what you want to the process if:
240 * (1) It's not being traced at all,
241 */
242 if (!ISSET(t->p_flag, P_TRACED))
243 return (EPERM);
244
245 /*
246 * (2) it's being traced by procfs (which has
247 * different signal delivery semantics),
248 */
249 if (ISSET(t->p_flag, P_FSTRACE))
250 return (EBUSY);
251
252 /*
253 * (3) it's not being traced by _you_, or
254 */
255 if (t->p_pptr != p)
256 return (EBUSY);
257
258 /*
259 * (4) it's not currently stopped.
260 */
261 if (t->p_stat != SSTOP || !ISSET(t->p_flag, P_WAITED))
262 return (EBUSY);
263 break;
264
265 default: /* It was not a legal request. */
266 return (EINVAL);
267 }
268
269 /* Do single-step fixup if needed. */
270 FIX_SSTEP(t);
271
272 /*
273 * XXX NJWLWP
274 *
275 * The entire ptrace interface needs work to be useful to a
276 * process with multiple LWPs. For the moment, we'll kluge
277 * this; memory access will be fine, but register access will
278 * be weird.
279 */
280
281 lt = proc_representative_lwp(t);
282
283 /* Now do the operation. */
284 write = 0;
285 *retval = 0;
286 tmp = 0;
287
288 switch (SCARG(uap, req)) {
289 case PT_TRACE_ME:
290 /* Just set the trace flag. */
291 SET(t->p_flag, P_TRACED);
292 t->p_opptr = t->p_pptr;
293 return (0);
294
295 case PT_WRITE_I: /* XXX no separate I and D spaces */
296 case PT_WRITE_D:
297 #if defined(__HAVE_RAS)
298 /*
299 * Can't write to a RAS
300 */
301 if (!LIST_EMPTY(&t->p_raslist) &&
302 (ras_lookup(t, SCARG(uap, addr)) != (caddr_t)-1)) {
303 return (EACCES);
304 }
305 #endif
306 write = 1;
307 tmp = SCARG(uap, data);
308 case PT_READ_I: /* XXX no separate I and D spaces */
309 case PT_READ_D:
310 /* write = 0 done above. */
311 iov.iov_base = (caddr_t)&tmp;
312 iov.iov_len = sizeof(tmp);
313 uio.uio_iov = &iov;
314 uio.uio_iovcnt = 1;
315 uio.uio_offset = (off_t)(unsigned long)SCARG(uap, addr);
316 uio.uio_resid = sizeof(tmp);
317 uio.uio_segflg = UIO_SYSSPACE;
318 uio.uio_rw = write ? UIO_WRITE : UIO_READ;
319 uio.uio_procp = NULL;
320 error = process_domem(p, t, &uio);
321 if (!write)
322 *retval = tmp;
323 return (error);
324
325 case PT_IO:
326 error = copyin(SCARG(uap, addr), &piod, sizeof(piod));
327 if (error)
328 return (error);
329 iov.iov_base = piod.piod_addr;
330 iov.iov_len = piod.piod_len;
331 uio.uio_iov = &iov;
332 uio.uio_iovcnt = 1;
333 uio.uio_offset = (off_t)(unsigned long)piod.piod_offs;
334 uio.uio_resid = piod.piod_len;
335 uio.uio_segflg = UIO_USERSPACE;
336 uio.uio_procp = p;
337 switch (piod.piod_op) {
338 case PIOD_READ_D:
339 case PIOD_READ_I:
340 uio.uio_rw = UIO_READ;
341 break;
342 case PIOD_WRITE_D:
343 case PIOD_WRITE_I:
344 uio.uio_rw = UIO_WRITE;
345 break;
346 default:
347 return (EINVAL);
348 }
349 error = process_domem(p, t, &uio);
350 piod.piod_len -= uio.uio_resid;
351 (void) copyout(&piod, SCARG(uap, addr), sizeof(piod));
352 return (error);
353
354 case PT_DUMPCORE:
355 if ((path = SCARG(uap, addr)) != NULL) {
356 char *dst;
357 int len = SCARG(uap, data);
358 if (len < 0 || len >= MAXPATHLEN)
359 return EINVAL;
360 dst = malloc(len + 1, M_TEMP, M_WAITOK);
361 if ((error = copyin(path, dst, len)) != 0) {
362 free(dst, M_TEMP);
363 return error;
364 }
365 path = dst;
366 path[len] = '\0';
367 }
368 error = coredump(lt, path);
369 if (path)
370 free(path, M_TEMP);
371 return error;
372
373 #ifdef PT_STEP
374 case PT_STEP:
375 /*
376 * From the 4.4BSD PRM:
377 * "Execution continues as in request PT_CONTINUE; however
378 * as soon as possible after execution of at least one
379 * instruction, execution stops again. [ ... ]"
380 */
381 #endif
382 case PT_CONTINUE:
383 case PT_DETACH:
384 /*
385 * From the 4.4BSD PRM:
386 * "The data argument is taken as a signal number and the
387 * child's execution continues at location addr as if it
388 * incurred that signal. Normally the signal number will
389 * be either 0 to indicate that the signal that caused the
390 * stop should be ignored, or that value fetched out of
391 * the process's image indicating which signal caused
392 * the stop. If addr is (int *)1 then execution continues
393 * from where it stopped."
394 */
395
396 /* Check that the data is a valid signal number or zero. */
397 if (SCARG(uap, data) < 0 || SCARG(uap, data) >= NSIG)
398 return (EINVAL);
399
400 PHOLD(lt);
401
402 /* If the address parameter is not (int *)1, set the pc. */
403 if ((int *)SCARG(uap, addr) != (int *)1)
404 if ((error = process_set_pc(lt, SCARG(uap, addr))) != 0)
405 goto relebad;
406
407 #ifdef PT_STEP
408 /*
409 * Arrange for a single-step, if that's requested and possible.
410 */
411 error = process_sstep(lt, SCARG(uap, req) == PT_STEP);
412 if (error)
413 goto relebad;
414 #endif
415
416 PRELE(lt);
417
418 if (SCARG(uap, req) == PT_DETACH) {
419 /* give process back to original parent or init */
420 s = proclist_lock_write();
421 if (t->p_opptr != t->p_pptr) {
422 struct proc *pp = t->p_opptr;
423 proc_reparent(t, pp ? pp : initproc);
424 }
425
426 /* not being traced any more */
427 t->p_opptr = NULL;
428 proclist_unlock_write(s);
429 CLR(t->p_flag, P_TRACED|P_WAITED);
430 }
431
432 sendsig:
433 /* Finally, deliver the requested signal (or none). */
434 if (t->p_stat == SSTOP) {
435 t->p_xstat = SCARG(uap, data);
436 SCHED_LOCK(s);
437 lr = proc_unstop(t);
438 /*
439 * If the target needs to take a signal, there
440 * is no running LWP that will see it, and
441 * there is a LWP sleeping interruptably, then
442 * get it moving.
443 */
444 if (lr && (t->p_xstat != 0))
445 setrunnable(lr);
446 SCHED_UNLOCK(s);
447 } else {
448 if (SCARG(uap, data) != 0)
449 psignal(t, SCARG(uap, data));
450 }
451 return (0);
452
453 relebad:
454 PRELE(lt);
455 return (error);
456
457 case PT_KILL:
458 /* just send the process a KILL signal. */
459 SCARG(uap, data) = SIGKILL;
460 goto sendsig; /* in PT_CONTINUE, above. */
461
462 case PT_ATTACH:
463 /*
464 * Go ahead and set the trace flag.
465 * Save the old parent (it's reset in
466 * _DETACH, and also in kern_exit.c:wait4()
467 * Reparent the process so that the tracing
468 * proc gets to see all the action.
469 * Stop the target.
470 */
471 SET(t->p_flag, P_TRACED);
472 s = proclist_lock_write();
473 t->p_opptr = t->p_pptr;
474 if (t->p_pptr != p) {
475 t->p_pptr->p_flag |= P_CHTRACED;
476 proc_reparent(t, p);
477 }
478 proclist_unlock_write(s);
479 SCARG(uap, data) = SIGSTOP;
480 goto sendsig;
481
482 case PT_LWPINFO:
483 if (SCARG(uap, data) != sizeof(pl))
484 return (EINVAL);
485 error = copyin(SCARG(uap, addr), &pl, sizeof(pl));
486 if (error)
487 return (error);
488 tmp = pl.pl_lwpid;
489 if (tmp == 0)
490 lt = LIST_FIRST(&t->p_lwps);
491 else {
492 LIST_FOREACH(lt, &t->p_lwps, l_sibling)
493 if (lt->l_lid == tmp)
494 break;
495 if (lt == NULL)
496 return (ESRCH);
497 lt = LIST_NEXT(lt, l_sibling);
498 }
499 pl.pl_lwpid = 0;
500 pl.pl_event = 0;
501 if (lt) {
502 pl.pl_lwpid = lt->l_lid;
503 if (lt->l_lid == t->p_sigctx.ps_lwp)
504 pl.pl_event = PL_EVENT_SIGNAL;
505 }
506
507 return copyout(&pl, SCARG(uap, addr), sizeof(pl));
508
509 #ifdef PT_SETREGS
510 case PT_SETREGS:
511 write = 1;
512 #endif
513 #ifdef PT_GETREGS
514 case PT_GETREGS:
515 /* write = 0 done above. */
516 #endif
517 #if defined(PT_SETREGS) || defined(PT_GETREGS)
518 tmp = SCARG(uap, data);
519 if (tmp != 0 && t->p_nlwps > 1) {
520 LIST_FOREACH(lt, &t->p_lwps, l_sibling)
521 if (lt->l_lid == tmp)
522 break;
523 if (lt == NULL)
524 return (ESRCH);
525 }
526 if (!process_validregs(t))
527 return (EINVAL);
528 else {
529 iov.iov_base = SCARG(uap, addr);
530 iov.iov_len = sizeof(struct reg);
531 uio.uio_iov = &iov;
532 uio.uio_iovcnt = 1;
533 uio.uio_offset = 0;
534 uio.uio_resid = sizeof(struct reg);
535 uio.uio_segflg = UIO_USERSPACE;
536 uio.uio_rw = write ? UIO_WRITE : UIO_READ;
537 uio.uio_procp = p;
538 return (process_doregs(p, lt, &uio));
539 }
540 #endif
541
542 #ifdef PT_SETFPREGS
543 case PT_SETFPREGS:
544 write = 1;
545 #endif
546 #ifdef PT_GETFPREGS
547 case PT_GETFPREGS:
548 /* write = 0 done above. */
549 #endif
550 #if defined(PT_SETFPREGS) || defined(PT_GETFPREGS)
551 tmp = SCARG(uap, data);
552 if (tmp != 0 && t->p_nlwps > 1) {
553 LIST_FOREACH(lt, &t->p_lwps, l_sibling)
554 if (lt->l_lid == tmp)
555 break;
556 if (lt == NULL)
557 return (ESRCH);
558 }
559 if (!process_validfpregs(t))
560 return (EINVAL);
561 else {
562 iov.iov_base = SCARG(uap, addr);
563 iov.iov_len = sizeof(struct fpreg);
564 uio.uio_iov = &iov;
565 uio.uio_iovcnt = 1;
566 uio.uio_offset = 0;
567 uio.uio_resid = sizeof(struct fpreg);
568 uio.uio_segflg = UIO_USERSPACE;
569 uio.uio_rw = write ? UIO_WRITE : UIO_READ;
570 uio.uio_procp = p;
571 return (process_dofpregs(p, lt, &uio));
572 }
573 #endif
574
575 #ifdef __HAVE_PTRACE_MACHDEP
576 PTRACE_MACHDEP_REQUEST_CASES
577 return (ptrace_machdep_dorequest(p, lt,
578 SCARG(uap, req), SCARG(uap, addr),
579 SCARG(uap, data)));
580 #endif
581 }
582
583 #ifdef DIAGNOSTIC
584 panic("ptrace: impossible");
585 #endif
586 return 0;
587 }
588
589 int
590 process_doregs(curp, l, uio)
591 struct proc *curp; /* tracer */
592 struct lwp *l; /* traced */
593 struct uio *uio;
594 {
595 #if defined(PT_GETREGS) || defined(PT_SETREGS)
596 int error;
597 struct reg r;
598 char *kv;
599 int kl;
600
601 if (uio->uio_offset < 0 || uio->uio_offset > (off_t)sizeof(r))
602 return EINVAL;
603
604 if ((error = process_checkioperm(curp, l->l_proc)) != 0)
605 return error;
606
607 kl = sizeof(r);
608 kv = (char *)&r;
609
610 kv += uio->uio_offset;
611 kl -= uio->uio_offset;
612 if ((size_t)kl > uio->uio_resid)
613 kl = uio->uio_resid;
614
615 PHOLD(l);
616
617 error = process_read_regs(l, &r);
618 if (error == 0)
619 error = uiomove(kv, kl, uio);
620 if (error == 0 && uio->uio_rw == UIO_WRITE) {
621 if (l->l_stat != LSSTOP)
622 error = EBUSY;
623 else
624 error = process_write_regs(l, &r);
625 }
626
627 PRELE(l);
628
629 uio->uio_offset = 0;
630 return (error);
631 #else
632 return (EINVAL);
633 #endif
634 }
635
636 int
637 process_validregs(p)
638 struct proc *p;
639 {
640
641 #if defined(PT_SETREGS) || defined(PT_GETREGS)
642 return ((p->p_flag & P_SYSTEM) == 0);
643 #else
644 return (0);
645 #endif
646 }
647
648 int
649 process_dofpregs(curp, l, uio)
650 struct proc *curp; /* tracer */
651 struct lwp *l; /* traced */
652 struct uio *uio;
653 {
654 #if defined(PT_GETFPREGS) || defined(PT_SETFPREGS)
655 int error;
656 struct fpreg r;
657 char *kv;
658 int kl;
659
660 if (uio->uio_offset < 0 || uio->uio_offset > (off_t)sizeof(r))
661 return EINVAL;
662
663 if ((error = process_checkioperm(curp, l->l_proc)) != 0)
664 return (error);
665
666 kl = sizeof(r);
667 kv = (char *)&r;
668
669 kv += uio->uio_offset;
670 kl -= uio->uio_offset;
671 if ((size_t)kl > uio->uio_resid)
672 kl = uio->uio_resid;
673
674 PHOLD(l);
675
676 error = process_read_fpregs(l, &r);
677 if (error == 0)
678 error = uiomove(kv, kl, uio);
679 if (error == 0 && uio->uio_rw == UIO_WRITE) {
680 if (l->l_stat != LSSTOP)
681 error = EBUSY;
682 else
683 error = process_write_fpregs(l, &r);
684 }
685
686 PRELE(l);
687
688 uio->uio_offset = 0;
689 return (error);
690 #else
691 return (EINVAL);
692 #endif
693 }
694
695 int
696 process_validfpregs(p)
697 struct proc *p;
698 {
699
700 #if defined(PT_SETFPREGS) || defined(PT_GETFPREGS)
701 return ((p->p_flag & P_SYSTEM) == 0);
702 #else
703 return (0);
704 #endif
705 }
706
707 int
708 process_domem(curp, p, uio)
709 struct proc *curp; /* tracer */
710 struct proc *p; /* traced */
711 struct uio *uio;
712 {
713 struct vmspace *vm;
714 int error;
715
716 size_t len;
717 #ifdef PMAP_NEED_PROCWR
718 vaddr_t addr;
719 #endif
720
721 len = uio->uio_resid;
722
723 if (len == 0)
724 return (0);
725
726 #ifdef PMAP_NEED_PROCWR
727 addr = uio->uio_offset;
728 #endif
729
730 if ((error = process_checkioperm(curp, p)) != 0)
731 return (error);
732
733 vm = p->p_vmspace;
734
735 simple_lock(&vm->vm_map.ref_lock);
736 if ((p->p_flag & P_WEXIT) || vm->vm_refcnt < 1)
737 error = EFAULT;
738 if (error == 0)
739 p->p_vmspace->vm_refcnt++; /* XXX */
740 simple_unlock(&vm->vm_map.ref_lock);
741 if (error != 0)
742 return (error);
743 error = uvm_io(&vm->vm_map, uio);
744 uvmspace_free(vm);
745
746 #ifdef PMAP_NEED_PROCWR
747 if (error == 0 && uio->uio_rw == UIO_WRITE)
748 pmap_procwr(p, addr, len);
749 #endif
750 return (error);
751 }
752
753 /*
754 * Ensure that a process has permission to perform I/O on another.
755 * Arguments:
756 * p The process wishing to do the I/O (the tracer).
757 * t The process who's memory/registers will be read/written.
758 */
759 int
760 process_checkioperm(p, t)
761 struct proc *p, *t;
762 {
763 int error;
764
765 /*
766 * You cannot attach to a processes mem/regs if:
767 *
768 * (1) It is currently exec'ing
769 */
770 if (ISSET(t->p_flag, P_INEXEC))
771 return (EAGAIN);
772
773 /*
774 * (2) it's not owned by you, or is set-id on exec
775 * (unless you're root), or...
776 */
777 if ((t->p_cred->p_ruid != p->p_cred->p_ruid ||
778 ISSET(t->p_flag, P_SUGID)) &&
779 (error = suser(p->p_ucred, &p->p_acflag)) != 0)
780 return (error);
781
782 /*
783 * (3) ...it's init, which controls the security level
784 * of the entire system, and the system was not
785 * compiled with permanetly insecure mode turned on.
786 */
787 if (t == initproc && securelevel > -1)
788 return (EPERM);
789
790 /*
791 * (4) the tracer is chrooted, and its root directory is
792 * not at or above the root directory of the tracee
793 */
794 if (!proc_isunder(t, p))
795 return (EPERM);
796
797 return (0);
798 }
Cache object: da0af582a6fb7f8ba4fed05a997513be
|