1 /* $NetBSD: sys_process.c,v 1.86.2.1 2006/10/16 17:56:59 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.86.2.1 2006/10/16 17:56:59 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
103 #include <sys/mount.h>
104 #include <sys/sa.h>
105 #include <sys/syscallargs.h>
106
107 #include <uvm/uvm_extern.h>
108
109 #include <machine/reg.h>
110
111 /* Macros to clear/set/test flags. */
112 #define SET(t, f) (t) |= (f)
113 #define CLR(t, f) (t) &= ~(f)
114 #define ISSET(t, f) ((t) & (f))
115
116 /*
117 * Process debugging system call.
118 */
119 int
120 sys_ptrace(l, v, retval)
121 struct lwp *l;
122 void *v;
123 register_t *retval;
124 {
125 struct sys_ptrace_args /* {
126 syscallarg(int) req;
127 syscallarg(pid_t) pid;
128 syscallarg(caddr_t) addr;
129 syscallarg(int) data;
130 } */ *uap = v;
131 struct proc *p = l->l_proc;
132 struct lwp *lt, *lr;
133 struct proc *t; /* target process */
134 struct uio uio;
135 struct iovec iov;
136 struct ptrace_io_desc piod;
137 struct ptrace_lwpinfo pl;
138 int s, error, write, tmp;
139
140 /* "A foolish consistency..." XXX */
141 if (SCARG(uap, req) == PT_TRACE_ME)
142 t = p;
143 else {
144
145 /* Find the process we're supposed to be operating on. */
146 if ((t = pfind(SCARG(uap, pid))) == NULL)
147 return (ESRCH);
148 }
149
150 /* Can't trace a process that's currently exec'ing. */
151 if ((t->p_flag & P_INEXEC) != 0)
152 return EAGAIN;
153
154 /* Make sure we can operate on it. */
155 switch (SCARG(uap, req)) {
156 case PT_TRACE_ME:
157 /* Saying that you're being traced is always legal. */
158 break;
159
160 case PT_ATTACH:
161 case PT_DUMPCORE:
162 /*
163 * You can't attach to a process if:
164 * (1) it's the process that's doing the attaching,
165 */
166 if (t->p_pid == p->p_pid)
167 return (EINVAL);
168
169 /*
170 * (2) it's a system process
171 */
172 if (t->p_flag & P_SYSTEM)
173 return (EPERM);
174
175 /*
176 * (3) it's already being traced, or
177 */
178 if (ISSET(t->p_flag, P_TRACED))
179 return (EBUSY);
180
181 /*
182 * (4) it's not owned by you, or is set-id on exec
183 * (unless you're root), or...
184 */
185 if ((t->p_cred->p_ruid != p->p_cred->p_ruid ||
186 ISSET(t->p_flag, P_SUGID)) &&
187 (error = suser(p->p_ucred, &p->p_acflag)) != 0)
188 return (error);
189
190 /*
191 * (5) ...it's init, which controls the security level
192 * of the entire system, and the system was not
193 * compiled with permanently insecure mode turned on
194 */
195 if (t == initproc && securelevel > -1)
196 return (EPERM);
197
198 /*
199 * (6) the tracer is chrooted, and its root directory is
200 * not at or above the root directory of the tracee
201 */
202
203 if (!proc_isunder(t, p))
204 return EPERM;
205 break;
206
207 case PT_READ_I:
208 case PT_READ_D:
209 case PT_WRITE_I:
210 case PT_WRITE_D:
211 case PT_CONTINUE:
212 case PT_IO:
213 case PT_KILL:
214 case PT_DETACH:
215 case PT_LWPINFO:
216 #ifdef PT_STEP
217 case PT_STEP:
218 #endif
219 #ifdef PT_GETREGS
220 case PT_GETREGS:
221 #endif
222 #ifdef PT_SETREGS
223 case PT_SETREGS:
224 #endif
225 #ifdef PT_GETFPREGS
226 case PT_GETFPREGS:
227 #endif
228 #ifdef PT_SETFPREGS
229 case PT_SETFPREGS:
230 #endif
231
232 #ifdef __HAVE_PTRACE_MACHDEP
233 PTRACE_MACHDEP_REQUEST_CASES
234 #endif
235
236 /*
237 * You can't do what you want to the process if:
238 * (1) It's not being traced at all,
239 */
240 if (!ISSET(t->p_flag, P_TRACED))
241 return (EPERM);
242
243 /*
244 * (2) it's being traced by procfs (which has
245 * different signal delivery semantics),
246 */
247 if (ISSET(t->p_flag, P_FSTRACE))
248 return (EBUSY);
249
250 /*
251 * (3) it's not being traced by _you_, or
252 */
253 if (t->p_pptr != p)
254 return (EBUSY);
255
256 /*
257 * (4) it's not currently stopped.
258 */
259 if (t->p_stat != SSTOP || !ISSET(t->p_flag, P_WAITED))
260 return (EBUSY);
261 break;
262
263 default: /* It was not a legal request. */
264 return (EINVAL);
265 }
266
267 /* Do single-step fixup if needed. */
268 FIX_SSTEP(t);
269
270 /*
271 * XXX NJWLWP
272 *
273 * The entire ptrace interface needs work to be useful to a
274 * process with multiple LWPs. For the moment, we'll kluge
275 * this; memory access will be fine, but register access will
276 * be weird.
277 */
278
279 lt = proc_representative_lwp(t);
280
281 /* Now do the operation. */
282 write = 0;
283 *retval = 0;
284 tmp = 0;
285
286 switch (SCARG(uap, req)) {
287 case PT_TRACE_ME:
288 /* Just set the trace flag. */
289 SET(t->p_flag, P_TRACED);
290 t->p_opptr = t->p_pptr;
291 return (0);
292
293 case PT_WRITE_I: /* XXX no separate I and D spaces */
294 case PT_WRITE_D:
295 #if defined(__HAVE_RAS)
296 /*
297 * Can't write to a RAS
298 */
299 if (!LIST_EMPTY(&t->p_raslist) &&
300 (ras_lookup(t, SCARG(uap, addr)) != (caddr_t)-1)) {
301 return (EACCES);
302 }
303 #endif
304 write = 1;
305 tmp = SCARG(uap, data);
306 case PT_READ_I: /* XXX no separate I and D spaces */
307 case PT_READ_D:
308 /* write = 0 done above. */
309 iov.iov_base = (caddr_t)&tmp;
310 iov.iov_len = sizeof(tmp);
311 uio.uio_iov = &iov;
312 uio.uio_iovcnt = 1;
313 uio.uio_offset = (off_t)(long)SCARG(uap, addr);
314 uio.uio_resid = sizeof(tmp);
315 uio.uio_segflg = UIO_SYSSPACE;
316 uio.uio_rw = write ? UIO_WRITE : UIO_READ;
317 uio.uio_procp = p;
318 error = process_domem(p, t, &uio);
319 if (!write)
320 *retval = tmp;
321 return (error);
322
323 case PT_IO:
324 error = copyin(SCARG(uap, addr), &piod, sizeof(piod));
325 if (error)
326 return (error);
327 iov.iov_base = piod.piod_addr;
328 iov.iov_len = piod.piod_len;
329 uio.uio_iov = &iov;
330 uio.uio_iovcnt = 1;
331 uio.uio_offset = (off_t)(long)piod.piod_offs;
332 uio.uio_resid = piod.piod_len;
333 uio.uio_segflg = UIO_USERSPACE;
334 uio.uio_procp = p;
335 switch (piod.piod_op) {
336 case PIOD_READ_D:
337 case PIOD_READ_I:
338 uio.uio_rw = UIO_READ;
339 break;
340 case PIOD_WRITE_D:
341 case PIOD_WRITE_I:
342 uio.uio_rw = UIO_WRITE;
343 break;
344 default:
345 return (EINVAL);
346 }
347 error = process_domem(p, t, &uio);
348 piod.piod_len -= uio.uio_resid;
349 (void) copyout(&piod, SCARG(uap, addr), sizeof(piod));
350 return (error);
351
352 case PT_DUMPCORE:
353 return coredump(lt);
354
355 #ifdef PT_STEP
356 case PT_STEP:
357 /*
358 * From the 4.4BSD PRM:
359 * "Execution continues as in request PT_CONTINUE; however
360 * as soon as possible after execution of at least one
361 * instruction, execution stops again. [ ... ]"
362 */
363 #endif
364 case PT_CONTINUE:
365 case PT_DETACH:
366 /*
367 * From the 4.4BSD PRM:
368 * "The data argument is taken as a signal number and the
369 * child's execution continues at location addr as if it
370 * incurred that signal. Normally the signal number will
371 * be either 0 to indicate that the signal that caused the
372 * stop should be ignored, or that value fetched out of
373 * the process's image indicating which signal caused
374 * the stop. If addr is (int *)1 then execution continues
375 * from where it stopped."
376 */
377
378 /* Check that the data is a valid signal number or zero. */
379 if (SCARG(uap, data) < 0 || SCARG(uap, data) >= NSIG)
380 return (EINVAL);
381
382 PHOLD(lt);
383
384 /* If the address parameter is not (int *)1, set the pc. */
385 if ((int *)SCARG(uap, addr) != (int *)1)
386 if ((error = process_set_pc(lt, SCARG(uap, addr))) != 0)
387 goto relebad;
388
389 #ifdef PT_STEP
390 /*
391 * Arrange for a single-step, if that's requested and possible.
392 */
393 error = process_sstep(lt, SCARG(uap, req) == PT_STEP);
394 if (error)
395 goto relebad;
396 #endif
397
398 PRELE(lt);
399
400 if (SCARG(uap, req) == PT_DETACH) {
401 /* give process back to original parent or init */
402 if (t->p_opptr != t->p_pptr) {
403 struct proc *pp = t->p_opptr;
404 proc_reparent(t, pp ? pp : initproc);
405 }
406
407 /* not being traced any more */
408 t->p_opptr = NULL;
409 CLR(t->p_flag, P_TRACED|P_WAITED);
410 }
411
412 sendsig:
413 /* Finally, deliver the requested signal (or none). */
414 if (t->p_stat == SSTOP) {
415 t->p_xstat = SCARG(uap, data);
416 SCHED_LOCK(s);
417 lr = proc_unstop(t);
418 /*
419 * If the target needs to take a signal, there
420 * is no running LWP that will see it, and
421 * there is a LWP sleeping interruptably, then
422 * get it moving.
423 */
424 if (lr && (t->p_xstat != 0))
425 setrunnable(lr);
426 SCHED_UNLOCK(s);
427 } else {
428 if (SCARG(uap, data) != 0)
429 psignal(t, SCARG(uap, data));
430 }
431 return (0);
432
433 relebad:
434 PRELE(lt);
435 return (error);
436
437 case PT_KILL:
438 /* just send the process a KILL signal. */
439 SCARG(uap, data) = SIGKILL;
440 goto sendsig; /* in PT_CONTINUE, above. */
441
442 case PT_ATTACH:
443 /*
444 * Go ahead and set the trace flag.
445 * Save the old parent (it's reset in
446 * _DETACH, and also in kern_exit.c:wait4()
447 * Reparent the process so that the tracing
448 * proc gets to see all the action.
449 * Stop the target.
450 */
451 SET(t->p_flag, P_TRACED);
452 t->p_opptr = t->p_pptr;
453 if (t->p_pptr != p) {
454 t->p_pptr->p_flag |= P_CHTRACED;
455 proc_reparent(t, p);
456 }
457 SCARG(uap, data) = SIGSTOP;
458 goto sendsig;
459
460 case PT_LWPINFO:
461 if (SCARG(uap, data) != sizeof(pl))
462 return (EINVAL);
463 error = copyin(SCARG(uap, addr), &pl, sizeof(pl));
464 if (error)
465 return (error);
466 tmp = pl.pl_lwpid;
467 if (tmp == 0)
468 lt = LIST_FIRST(&t->p_lwps);
469 else {
470 LIST_FOREACH(lt, &t->p_lwps, l_sibling)
471 if (lt->l_lid == tmp)
472 break;
473 if (lt == NULL)
474 return (ESRCH);
475 lt = LIST_NEXT(lt, l_sibling);
476 }
477 pl.pl_lwpid = 0;
478 pl.pl_event = 0;
479 if (lt) {
480 pl.pl_lwpid = lt->l_lid;
481 if (lt->l_lid == t->p_sigctx.ps_lwp)
482 pl.pl_event = PL_EVENT_SIGNAL;
483 }
484
485 return copyout(&pl, SCARG(uap, addr), sizeof(pl));
486
487 #ifdef PT_SETREGS
488 case PT_SETREGS:
489 write = 1;
490 #endif
491 #ifdef PT_GETREGS
492 case PT_GETREGS:
493 /* write = 0 done above. */
494 #endif
495 #if defined(PT_SETREGS) || defined(PT_GETREGS)
496 tmp = SCARG(uap, data);
497 if (tmp != 0 && t->p_nlwps > 1) {
498 LIST_FOREACH(lt, &t->p_lwps, l_sibling)
499 if (lt->l_lid == tmp)
500 break;
501 if (lt == NULL)
502 return (ESRCH);
503 }
504 if (!process_validregs(t))
505 return (EINVAL);
506 else {
507 iov.iov_base = SCARG(uap, addr);
508 iov.iov_len = sizeof(struct reg);
509 uio.uio_iov = &iov;
510 uio.uio_iovcnt = 1;
511 uio.uio_offset = 0;
512 uio.uio_resid = sizeof(struct reg);
513 uio.uio_segflg = UIO_USERSPACE;
514 uio.uio_rw = write ? UIO_WRITE : UIO_READ;
515 uio.uio_procp = p;
516 return (process_doregs(p, lt, &uio));
517 }
518 #endif
519
520 #ifdef PT_SETFPREGS
521 case PT_SETFPREGS:
522 write = 1;
523 #endif
524 #ifdef PT_GETFPREGS
525 case PT_GETFPREGS:
526 /* write = 0 done above. */
527 #endif
528 #if defined(PT_SETFPREGS) || defined(PT_GETFPREGS)
529 tmp = SCARG(uap, data);
530 if (tmp != 0 && t->p_nlwps > 1) {
531 LIST_FOREACH(lt, &t->p_lwps, l_sibling)
532 if (lt->l_lid == tmp)
533 break;
534 if (lt == NULL)
535 return (ESRCH);
536 }
537 if (!process_validfpregs(t))
538 return (EINVAL);
539 else {
540 iov.iov_base = SCARG(uap, addr);
541 iov.iov_len = sizeof(struct fpreg);
542 uio.uio_iov = &iov;
543 uio.uio_iovcnt = 1;
544 uio.uio_offset = 0;
545 uio.uio_resid = sizeof(struct fpreg);
546 uio.uio_segflg = UIO_USERSPACE;
547 uio.uio_rw = write ? UIO_WRITE : UIO_READ;
548 uio.uio_procp = p;
549 return (process_dofpregs(p, lt, &uio));
550 }
551 #endif
552
553 #ifdef __HAVE_PTRACE_MACHDEP
554 PTRACE_MACHDEP_REQUEST_CASES
555 return (ptrace_machdep_dorequest(p, lt,
556 SCARG(uap, req), SCARG(uap, addr),
557 SCARG(uap, data)));
558 #endif
559 }
560
561 #ifdef DIAGNOSTIC
562 panic("ptrace: impossible");
563 #endif
564 return 0;
565 }
566
567 int
568 process_doregs(curp, l, uio)
569 struct proc *curp; /* tracer */
570 struct lwp *l; /* traced */
571 struct uio *uio;
572 {
573 #if defined(PT_GETREGS) || defined(PT_SETREGS)
574 int error;
575 struct reg r;
576 char *kv;
577 int kl;
578
579 if ((error = process_checkioperm(curp, l->l_proc)) != 0)
580 return error;
581
582 kl = sizeof(r);
583 kv = (char *) &r;
584
585 kv += uio->uio_offset;
586 kl -= uio->uio_offset;
587 if (kl < 0)
588 return (EINVAL);
589 if ((size_t) kl > uio->uio_resid)
590 kl = uio->uio_resid;
591
592 PHOLD(l);
593
594 error = process_read_regs(l, &r);
595 if (error == 0)
596 error = uiomove(kv, kl, uio);
597 if (error == 0 && uio->uio_rw == UIO_WRITE) {
598 if (l->l_stat != LSSTOP)
599 error = EBUSY;
600 else
601 error = process_write_regs(l, &r);
602 }
603
604 PRELE(l);
605
606 uio->uio_offset = 0;
607 return (error);
608 #else
609 return (EINVAL);
610 #endif
611 }
612
613 int
614 process_validregs(p)
615 struct proc *p;
616 {
617
618 #if defined(PT_SETREGS) || defined(PT_GETREGS)
619 return ((p->p_flag & P_SYSTEM) == 0);
620 #else
621 return (0);
622 #endif
623 }
624
625 int
626 process_dofpregs(curp, l, uio)
627 struct proc *curp; /* tracer */
628 struct lwp *l; /* traced */
629 struct uio *uio;
630 {
631 #if defined(PT_GETFPREGS) || defined(PT_SETFPREGS)
632 int error;
633 struct fpreg r;
634 char *kv;
635 int kl;
636
637 if ((error = process_checkioperm(curp, l->l_proc)) != 0)
638 return (error);
639
640 kl = sizeof(r);
641 kv = (char *) &r;
642
643 kv += uio->uio_offset;
644 kl -= uio->uio_offset;
645 if (kl < 0)
646 return (EINVAL);
647 if ((size_t) kl > uio->uio_resid)
648 kl = uio->uio_resid;
649
650 PHOLD(l);
651
652 error = process_read_fpregs(l, &r);
653 if (error == 0)
654 error = uiomove(kv, kl, uio);
655 if (error == 0 && uio->uio_rw == UIO_WRITE) {
656 if (l->l_stat != LSSTOP)
657 error = EBUSY;
658 else
659 error = process_write_fpregs(l, &r);
660 }
661
662 PRELE(l);
663
664 uio->uio_offset = 0;
665 return (error);
666 #else
667 return (EINVAL);
668 #endif
669 }
670
671 int
672 process_validfpregs(p)
673 struct proc *p;
674 {
675
676 #if defined(PT_SETFPREGS) || defined(PT_GETFPREGS)
677 return ((p->p_flag & P_SYSTEM) == 0);
678 #else
679 return (0);
680 #endif
681 }
682
683 int
684 process_domem(curp, p, uio)
685 struct proc *curp; /* tracer */
686 struct proc *p; /* traced */
687 struct uio *uio;
688 {
689 int error;
690
691 size_t len;
692 #ifdef PMAP_NEED_PROCWR
693 vaddr_t addr;
694 #endif
695
696 len = uio->uio_resid;
697
698 if (len == 0)
699 return (0);
700
701 #ifdef PMAP_NEED_PROCWR
702 addr = uio->uio_offset;
703 #endif
704
705 if ((error = process_checkioperm(curp, p)) != 0)
706 return (error);
707
708 /* XXXCDC: how should locking work here? */
709 if ((p->p_flag & P_WEXIT) || (p->p_vmspace->vm_refcnt < 1))
710 return(EFAULT);
711 p->p_vmspace->vm_refcnt++; /* XXX */
712 error = uvm_io(&p->p_vmspace->vm_map, uio);
713 uvmspace_free(p->p_vmspace);
714
715 #ifdef PMAP_NEED_PROCWR
716 if (error == 0 && uio->uio_rw == UIO_WRITE)
717 pmap_procwr(p, addr, len);
718 #endif
719 return (error);
720 }
721
722 /*
723 * Ensure that a process has permission to perform I/O on another.
724 * Arguments:
725 * p The process wishing to do the I/O (the tracer).
726 * t The process who's memory/registers will be read/written.
727 */
728 int
729 process_checkioperm(p, t)
730 struct proc *p, *t;
731 {
732 int error;
733
734 /*
735 * You cannot attach to a processes mem/regs if:
736 *
737 * (1) It is currently exec'ing
738 */
739 if (ISSET(t->p_flag, P_INEXEC))
740 return (EAGAIN);
741
742 /*
743 * (2) it's not owned by you, or is set-id on exec
744 * (unless you're root), or...
745 */
746 if ((t->p_cred->p_ruid != p->p_cred->p_ruid ||
747 ISSET(t->p_flag, P_SUGID)) &&
748 (error = suser(p->p_ucred, &p->p_acflag)) != 0)
749 return (error);
750
751 /*
752 * (3) ...it's init, which controls the security level
753 * of the entire system, and the system was not
754 * compiled with permanetly insecure mode turned on.
755 */
756 if (t == initproc && securelevel > -1)
757 return (EPERM);
758
759 /*
760 * (4) the tracer is chrooted, and its root directory is
761 * not at or above the root directory of the tracee
762 */
763 if (!proc_isunder(t, p))
764 return (EPERM);
765
766 return (0);
767 }
Cache object: 51d37d9412f902bda8536b41d3790b52
|