The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/kern/sys_process.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.