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 /*      $OpenBSD: sys_process.c,v 1.93 2023/01/24 00:12:03 deraadt Exp $        */
    2 /*      $NetBSD: sys_process.c,v 1.55 1996/05/15 06:17:47 tls Exp $     */
    3 
    4 /*-
    5  * Copyright (c) 1994 Christopher G. Demetriou.  All rights reserved.
    6  * Copyright (c) 1982, 1986, 1989, 1993
    7  *      The Regents of the University of California.  All rights reserved.
    8  * (c) UNIX System Laboratories, Inc.
    9  * All or some portions of this file are derived from material licensed
   10  * to the University of California by American Telephone and Telegraph
   11  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
   12  * the permission of UNIX System Laboratories, Inc.
   13  *
   14  * Redistribution and use in source and binary forms, with or without
   15  * modification, are permitted provided that the following conditions
   16  * are met:
   17  * 1. Redistributions of source code must retain the above copyright
   18  *    notice, this list of conditions and the following disclaimer.
   19  * 2. Redistributions in binary form must reproduce the above copyright
   20  *    notice, this list of conditions and the following disclaimer in the
   21  *    documentation and/or other materials provided with the distribution.
   22  * 3. Neither the name of the University nor the names of its contributors
   23  *    may be used to endorse or promote products derived from this software
   24  *    without specific prior written permission.
   25  *
   26  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   27  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   28  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   29  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   30  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   31  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   32  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   33  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   35  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   36  * SUCH DAMAGE.
   37  *
   38  *      from: @(#)sys_process.c 8.1 (Berkeley) 6/10/93
   39  */
   40 
   41 /*
   42  * References:
   43  *      (1) Bach's "The Design of the UNIX Operating System",
   44  *      (2) sys/miscfs/procfs from UCB's 4.4BSD-Lite distribution,
   45  *      (3) the "4.4BSD Programmer's Reference Manual" published
   46  *              by USENIX and O'Reilly & Associates.
   47  * The 4.4BSD PRM does a reasonably good job of documenting what the various
   48  * ptrace() requests should actually do, and its text is quoted several times
   49  * in this file.
   50  */
   51 
   52 #include <sys/param.h>
   53 #include <sys/systm.h>
   54 #include <sys/exec.h>
   55 #include <sys/proc.h>
   56 #include <sys/signalvar.h>
   57 #include <sys/errno.h>
   58 #include <sys/malloc.h>
   59 #include <sys/ptrace.h>
   60 #include <sys/uio.h>
   61 #include <sys/sched.h>
   62 #include <sys/exec_elf.h>
   63 
   64 #include <sys/mount.h>
   65 #include <sys/syscallargs.h>
   66 
   67 #include <uvm/uvm_extern.h>
   68 
   69 #include <machine/reg.h>
   70 
   71 #ifdef PTRACE
   72 
   73 static inline int       process_checktracestate(struct process *_curpr,
   74                             struct process *_tr, struct proc *_t);
   75 static inline struct process *process_tprfind(pid_t _tpid, struct proc **_tp);
   76 
   77 int     ptrace_ctrl(struct proc *, int, pid_t, caddr_t, int);
   78 int     ptrace_ustate(struct proc *, int, pid_t, void *, int, register_t *);
   79 int     ptrace_kstate(struct proc *, int, pid_t, void *);
   80 
   81 int     global_ptrace;  /* permit tracing of not children */
   82 
   83 
   84 /*
   85  * Process debugging system call.
   86  */
   87 int
   88 sys_ptrace(struct proc *p, void *v, register_t *retval)
   89 {
   90         struct sys_ptrace_args /* {
   91                 syscallarg(int) req;
   92                 syscallarg(pid_t) pid;
   93                 syscallarg(caddr_t) addr;
   94                 syscallarg(int) data;
   95         } */ *uap = v;
   96         int req = SCARG(uap, req);
   97         pid_t pid = SCARG(uap, pid);
   98         caddr_t uaddr = SCARG(uap, addr);       /* userspace */
   99         void *kaddr = NULL;                     /* kernelspace */
  100         int data = SCARG(uap, data);
  101         union {
  102                 struct ptrace_thread_state u_pts;
  103                 struct ptrace_io_desc u_piod;
  104                 struct ptrace_event u_pe;
  105                 struct ptrace_state u_ps;
  106                 register_t u_wcookie;
  107         } u;
  108         int size = 0;
  109         enum { NONE, IN, IN_ALLOC, OUT, OUT_ALLOC, IN_OUT } mode;
  110         int kstate = 0;
  111         int error;
  112 
  113         *retval = 0;
  114 
  115         /* Figure out what sort of copyin/out operations we'll do */
  116         switch (req) {
  117         case PT_TRACE_ME:
  118         case PT_CONTINUE:
  119         case PT_KILL:
  120         case PT_ATTACH:
  121         case PT_DETACH:
  122 #ifdef PT_STEP
  123         case PT_STEP:
  124 #endif
  125                 /* control operations do no copyin/out; dispatch directly */
  126                 return ptrace_ctrl(p, req, pid, uaddr, data);
  127 
  128         case PT_READ_I:
  129         case PT_READ_D:
  130         case PT_WRITE_I:
  131         case PT_WRITE_D:
  132                 mode = NONE;
  133                 break;
  134         case PT_IO:
  135                 mode = IN_OUT;
  136                 size = sizeof u.u_piod;
  137                 data = size;    /* suppress the data == size check */
  138                 break;
  139         case PT_GET_THREAD_FIRST:
  140                 mode = OUT;
  141                 size = sizeof u.u_pts;
  142                 kstate = 1;
  143                 break;
  144         case PT_GET_THREAD_NEXT:
  145                 mode = IN_OUT;
  146                 size = sizeof u.u_pts;
  147                 kstate = 1;
  148                 break;
  149         case PT_GET_EVENT_MASK:
  150                 mode = OUT;
  151                 size = sizeof u.u_pe;
  152                 kstate = 1;
  153                 break;
  154         case PT_SET_EVENT_MASK:
  155                 mode = IN;
  156                 size = sizeof u.u_pe;
  157                 kstate = 1;
  158                 break;
  159         case PT_GET_PROCESS_STATE:
  160                 mode = OUT;
  161                 size = sizeof u.u_ps;
  162                 kstate = 1;
  163                 break;
  164         case PT_GETREGS:
  165                 mode = OUT_ALLOC;
  166                 size = sizeof(struct reg);
  167                 break;
  168         case PT_SETREGS:
  169                 mode = IN_ALLOC;
  170                 size = sizeof(struct reg);
  171                 break;
  172 #ifdef PT_GETFPREGS
  173         case PT_GETFPREGS:
  174                 mode = OUT_ALLOC;
  175                 size = sizeof(struct fpreg);
  176                 break;
  177 #endif
  178 #ifdef PT_SETFPREGS
  179         case PT_SETFPREGS:
  180                 mode = IN_ALLOC;
  181                 size = sizeof(struct fpreg);
  182                 break;
  183 #endif
  184 #ifdef PT_GETXMMREGS
  185         case PT_GETXMMREGS:
  186                 mode = OUT_ALLOC;
  187                 size = sizeof(struct xmmregs);
  188                 break;
  189 #endif
  190 #ifdef PT_SETXMMREGS
  191         case PT_SETXMMREGS:
  192                 mode = IN_ALLOC;
  193                 size = sizeof(struct xmmregs);
  194                 break;
  195 #endif
  196 #ifdef PT_WCOOKIE
  197         case PT_WCOOKIE:
  198                 mode = OUT;
  199                 size = sizeof u.u_wcookie;
  200                 data = size;    /* suppress the data == size check */
  201                 break;
  202 #endif
  203         default:
  204                 return EINVAL;
  205         }
  206 
  207 
  208         /* Now do any copyin()s and allocations in a consistent manner */
  209         switch (mode) {
  210         case NONE:
  211                 kaddr = uaddr;
  212                 break;
  213         case IN:
  214         case IN_OUT:
  215         case OUT:
  216                 KASSERT(size <= sizeof u);
  217                 if (data != size)
  218                         return EINVAL;
  219                 if (mode == OUT)
  220                         memset(&u, 0, size);
  221                 else { /* IN or IN_OUT */
  222                         if ((error = copyin(uaddr, &u, size)))
  223                                 return error;
  224                 }
  225                 kaddr = &u;
  226                 break;
  227         case IN_ALLOC:
  228                 kaddr = malloc(size, M_TEMP, M_WAITOK);
  229                 if ((error = copyin(uaddr, kaddr, size))) {
  230                         free(kaddr, M_TEMP, size);
  231                         return error;
  232                 }
  233                 break;
  234         case OUT_ALLOC:
  235                 kaddr = malloc(size, M_TEMP, M_WAITOK | M_ZERO);
  236                 break;
  237         }
  238 
  239         if (kstate)
  240                 error = ptrace_kstate(p, req, pid, kaddr);
  241         else
  242                 error = ptrace_ustate(p, req, pid, kaddr, data, retval);
  243 
  244         /* Do any copyout()s and frees */
  245         if (error == 0) {
  246                 switch (mode) {
  247                 case NONE:
  248                 case IN:
  249                 case IN_ALLOC:
  250                         break;
  251                 case IN_OUT:
  252                 case OUT:
  253                         error = copyout(&u, uaddr, size);
  254                         if (req == PT_IO) {
  255                                 /* historically, errors here are ignored */
  256                                 error = 0;
  257                         }
  258                         break;
  259                 case OUT_ALLOC:
  260                         error = copyout(kaddr, uaddr, size);
  261                         break;
  262                 }
  263         }
  264 
  265         if (mode == IN_ALLOC || mode == OUT_ALLOC)
  266                 free(kaddr, M_TEMP, size);
  267         return error;
  268 }
  269 
  270 /*
  271  * ptrace control requests: attach, detach, continue, kill, single-step, etc
  272  */
  273 int
  274 ptrace_ctrl(struct proc *p, int req, pid_t pid, caddr_t addr, int data)
  275 {
  276         struct proc *t;                         /* target thread */
  277         struct process *tr;                     /* target process */
  278         int error = 0;
  279         int s;
  280 
  281         switch (req) {
  282         case PT_TRACE_ME:
  283                 /* Just set the trace flag. */
  284                 tr = p->p_p;
  285                 if (ISSET(tr->ps_flags, PS_TRACED))
  286                         return EBUSY;
  287                 atomic_setbits_int(&tr->ps_flags, PS_TRACED);
  288                 tr->ps_oppid = tr->ps_pptr->ps_pid;
  289                 if (tr->ps_ptstat == NULL)
  290                         tr->ps_ptstat = malloc(sizeof(*tr->ps_ptstat),
  291                             M_SUBPROC, M_WAITOK);
  292                 memset(tr->ps_ptstat, 0, sizeof(*tr->ps_ptstat));
  293                 return 0;
  294 
  295         /* calls that only operate on the PID */
  296         case PT_KILL:
  297         case PT_ATTACH:
  298         case PT_DETACH:
  299                 /* Find the process we're supposed to be operating on. */
  300                 if ((tr = prfind(pid)) == NULL) {
  301                         error = ESRCH;
  302                         goto fail;
  303                 }
  304                 t = TAILQ_FIRST(&tr->ps_threads);
  305                 break;
  306 
  307         /* calls that accept a PID or a thread ID */
  308         case PT_CONTINUE:
  309 #ifdef PT_STEP
  310         case PT_STEP:
  311 #endif
  312                 if ((tr = process_tprfind(pid, &t)) == NULL) {
  313                         error = ESRCH;
  314                         goto fail;
  315                 }
  316                 break;
  317         }
  318 
  319         /* Check permissions/state */
  320         if (req != PT_ATTACH) {
  321                 /* Check that the data is a valid signal number or zero. */
  322                 if (req != PT_KILL && (data < 0 || data >= NSIG)) {
  323                         error = EINVAL;
  324                         goto fail;
  325                 }
  326 
  327                 /* Most operations require the target to already be traced */
  328                 if ((error = process_checktracestate(p->p_p, tr, t)))
  329                         goto fail;
  330 
  331                 /* Do single-step fixup if needed. */
  332                 FIX_SSTEP(t);
  333         } else {
  334                 /*
  335                  * PT_ATTACH is the opposite; you can't attach to a process if:
  336                  *      (1) it's the process that's doing the attaching,
  337                  */
  338                 if (tr == p->p_p) {
  339                         error = EINVAL;
  340                         goto fail;
  341                 }
  342 
  343                 /*
  344                  *      (2) it's a system process
  345                  */
  346                 if (ISSET(tr->ps_flags, PS_SYSTEM)) {
  347                         error = EPERM;
  348                         goto fail;
  349                 }
  350 
  351                 /*
  352                  *      (3) it's already being traced, or
  353                  */
  354                 if (ISSET(tr->ps_flags, PS_TRACED)) {
  355                         error = EBUSY;
  356                         goto fail;
  357                 }
  358 
  359                 /*
  360                  *      (4) it's in the middle of execve(2)
  361                  */
  362                 if (ISSET(tr->ps_flags, PS_INEXEC)) {
  363                         error = EAGAIN;
  364                         goto fail;
  365                 }
  366 
  367                 /*
  368                  *      (5) it's not owned by you, or the last exec
  369                  *          gave us setuid/setgid privs (unless
  370                  *          you're root), or...
  371                  * 
  372                  *      [Note: once PS_SUGID or PS_SUGIDEXEC gets set in
  373                  *      execve(), they stay set until the process does
  374                  *      another execve().  Hence this prevents a setuid
  375                  *      process which revokes its special privileges using
  376                  *      setuid() from being traced.  This is good security.]
  377                  */
  378                 if ((tr->ps_ucred->cr_ruid != p->p_ucred->cr_ruid ||
  379                     ISSET(tr->ps_flags, PS_SUGIDEXEC | PS_SUGID)) &&
  380                     (error = suser(p)) != 0)
  381                         goto fail;
  382 
  383                 /*
  384                  *      (5.5) it's not a child of the tracing process.
  385                  */
  386                 if (global_ptrace == 0 && !inferior(tr, p->p_p) &&
  387                     (error = suser(p)) != 0)
  388                         goto fail;
  389 
  390                 /*
  391                  *      (6) ...it's init, which controls the security level
  392                  *          of the entire system, and the system was not
  393                  *          compiled with permanently insecure mode turned
  394                  *          on.
  395                  */
  396                 if ((tr->ps_pid == 1) && (securelevel > -1)) {
  397                         error = EPERM;
  398                         goto fail;
  399                 }
  400 
  401                 /*
  402                  *      (7) it's an ancestor of the current process and
  403                  *          not init (because that would create a loop in
  404                  *          the process graph).
  405                  */
  406                 if (tr->ps_pid != 1 && inferior(p->p_p, tr)) {
  407                         error = EINVAL;
  408                         goto fail;
  409                 }
  410         }
  411 
  412         switch (req) {
  413 
  414 #ifdef PT_STEP
  415         case PT_STEP:
  416                 /*
  417                  * From the 4.4BSD PRM:
  418                  * "Execution continues as in request PT_CONTINUE; however
  419                  * as soon as possible after execution of at least one
  420                  * instruction, execution stops again. [ ... ]"
  421                  */
  422 #endif
  423         case PT_CONTINUE:
  424                 /*
  425                  * From the 4.4BSD PRM:
  426                  * "The data argument is taken as a signal number and the
  427                  * child's execution continues at location addr as if it
  428                  * incurred that signal.  Normally the signal number will
  429                  * be either 0 to indicate that the signal that caused the
  430                  * stop should be ignored, or that value fetched out of
  431                  * the process's image indicating which signal caused
  432                  * the stop.  If addr is (int *)1 then execution continues
  433                  * from where it stopped."
  434                  */
  435 
  436                 if (pid < THREAD_PID_OFFSET && tr->ps_single)
  437                         t = tr->ps_single;
  438 
  439                 /* If the address parameter is not (int *)1, set the pc. */
  440                 if ((int *)addr != (int *)1)
  441                         if ((error = process_set_pc(t, addr)) != 0)
  442                                 goto fail;
  443 
  444 #ifdef PT_STEP
  445                 /*
  446                  * Arrange for a single-step, if that's requested and possible.
  447                  */
  448                 error = process_sstep(t, req == PT_STEP);
  449                 if (error)
  450                         goto fail;
  451 #endif
  452                 goto sendsig;
  453 
  454         case PT_DETACH:
  455                 /*
  456                  * From the 4.4BSD PRM:
  457                  * "The data argument is taken as a signal number and the
  458                  * child's execution continues at location addr as if it
  459                  * incurred that signal.  Normally the signal number will
  460                  * be either 0 to indicate that the signal that caused the
  461                  * stop should be ignored, or that value fetched out of
  462                  * the process's image indicating which signal caused
  463                  * the stop.  If addr is (int *)1 then execution continues
  464                  * from where it stopped."
  465                  */
  466 
  467                 if (pid < THREAD_PID_OFFSET && tr->ps_single)
  468                         t = tr->ps_single;
  469 
  470 #ifdef PT_STEP
  471                 /*
  472                  * Stop single stepping.
  473                  */
  474                 error = process_sstep(t, 0);
  475                 if (error)
  476                         goto fail;
  477 #endif
  478 
  479                 process_untrace(tr);
  480                 atomic_clearbits_int(&tr->ps_flags, PS_WAITED);
  481 
  482         sendsig:
  483                 memset(tr->ps_ptstat, 0, sizeof(*tr->ps_ptstat));
  484 
  485                 /* Finally, deliver the requested signal (or none). */
  486                 if (t->p_stat == SSTOP) {
  487                         tr->ps_xsig = data;
  488                         SCHED_LOCK(s);
  489                         setrunnable(t);
  490                         SCHED_UNLOCK(s);
  491                 } else {
  492                         if (data != 0)
  493                                 psignal(t, data);
  494                 }
  495                 break;
  496 
  497         case PT_KILL:
  498                 if (pid < THREAD_PID_OFFSET && tr->ps_single)
  499                         t = tr->ps_single;
  500 
  501                 /* just send the process a KILL signal. */
  502                 data = SIGKILL;
  503                 goto sendsig;   /* in PT_CONTINUE, above. */
  504 
  505         case PT_ATTACH:
  506                 /*
  507                  * As was done in procfs:
  508                  * Go ahead and set the trace flag.
  509                  * Save the old parent (it's reset in
  510                  *   _DETACH, and also in kern_exit.c:wait4()
  511                  * Reparent the process so that the tracing
  512                  *   proc gets to see all the action.
  513                  * Stop the target.
  514                  */
  515                 atomic_setbits_int(&tr->ps_flags, PS_TRACED);
  516                 tr->ps_oppid = tr->ps_pptr->ps_pid;
  517                 process_reparent(tr, p->p_p);
  518                 if (tr->ps_ptstat == NULL)
  519                         tr->ps_ptstat = malloc(sizeof(*tr->ps_ptstat),
  520                             M_SUBPROC, M_WAITOK);
  521                 data = SIGSTOP;
  522                 goto sendsig;
  523         default:
  524                 KASSERTMSG(0, "%s: unhandled request %d", __func__, req);
  525                 break;
  526         }
  527 
  528 fail:
  529         return error;
  530 }
  531 
  532 /*
  533  * ptrace kernel-state requests: thread list, event mask, process state
  534  */
  535 int
  536 ptrace_kstate(struct proc *p, int req, pid_t pid, void *addr)
  537 {
  538         struct process *tr;                     /* target process */
  539         struct ptrace_event *pe = addr;
  540         int error;
  541 
  542         KASSERT((p->p_flag & P_SYSTEM) == 0);
  543 
  544         /* Find the process we're supposed to be operating on. */
  545         if ((tr = prfind(pid)) == NULL)
  546                 return ESRCH;
  547 
  548         if ((error = process_checktracestate(p->p_p, tr, NULL)))
  549                 return error;
  550 
  551         switch (req) {
  552         case PT_GET_THREAD_FIRST:
  553         case PT_GET_THREAD_NEXT:
  554               {
  555                 struct ptrace_thread_state *pts = addr;
  556                 struct proc *t;
  557 
  558                 if (req == PT_GET_THREAD_NEXT) {
  559                         t = tfind_user(pts->pts_tid, tr);
  560                         if (t == NULL || ISSET(t->p_flag, P_WEXIT))
  561                                 return ESRCH;
  562                         t = TAILQ_NEXT(t, p_thr_link);
  563                 } else {
  564                         t = TAILQ_FIRST(&tr->ps_threads);
  565                 }
  566 
  567                 if (t == NULL)
  568                         pts->pts_tid = -1;
  569                 else
  570                         pts->pts_tid = t->p_tid + THREAD_PID_OFFSET;
  571                 return 0;
  572               }
  573         }
  574 
  575         switch (req) {
  576         case PT_GET_EVENT_MASK:
  577                 pe->pe_set_event = tr->ps_ptmask;
  578                 break;
  579         case PT_SET_EVENT_MASK:
  580                 tr->ps_ptmask = pe->pe_set_event;
  581                 break;
  582         case PT_GET_PROCESS_STATE:
  583                 if (tr->ps_single)
  584                         tr->ps_ptstat->pe_tid =
  585                             tr->ps_single->p_tid + THREAD_PID_OFFSET;
  586                 memcpy(addr, tr->ps_ptstat, sizeof *tr->ps_ptstat);
  587                 break;
  588         default:
  589                 KASSERTMSG(0, "%s: unhandled request %d", __func__, req);
  590                 break;
  591         }
  592 
  593         return 0;
  594 }
  595 
  596 /*
  597  * ptrace user-state requests: memory access, registers, stack cookie
  598  */
  599 int
  600 ptrace_ustate(struct proc *p, int req, pid_t pid, void *addr, int data,
  601     register_t *retval)
  602 {
  603         struct proc *t;                         /* target thread */
  604         struct process *tr;                     /* target process */
  605         struct uio uio;
  606         struct iovec iov;
  607         int error, write;
  608         int temp = 0;
  609 
  610         KASSERT((p->p_flag & P_SYSTEM) == 0);
  611 
  612         /* Accept either PID or TID */
  613         if ((tr = process_tprfind(pid, &t)) == NULL)
  614                 return ESRCH;
  615 
  616         if ((error = process_checktracestate(p->p_p, tr, t)))
  617                 return error;
  618 
  619         FIX_SSTEP(t);
  620 
  621         /* Now do the operation. */
  622         write = 0;
  623 
  624         if ((error = process_checkioperm(p, tr)) != 0)
  625                 return error;
  626 
  627         switch (req) {
  628         case PT_WRITE_I:                /* XXX no separate I and D spaces */
  629         case PT_WRITE_D:
  630                 write = 1;
  631                 temp = data;
  632         case PT_READ_I:         /* XXX no separate I and D spaces */
  633         case PT_READ_D:
  634                 /* write = 0 done above. */
  635                 iov.iov_base = (caddr_t)&temp;
  636                 iov.iov_len = sizeof(int);
  637                 uio.uio_iov = &iov;
  638                 uio.uio_iovcnt = 1;
  639                 uio.uio_offset = (off_t)(vaddr_t)addr;
  640                 uio.uio_resid = sizeof(int);
  641                 uio.uio_segflg = UIO_SYSSPACE;
  642                 uio.uio_rw = write ? UIO_WRITE : UIO_READ;
  643                 uio.uio_procp = p;
  644                 error = process_domem(p, tr, &uio, write ? PT_WRITE_I :
  645                                 PT_READ_I);
  646                 if (write == 0)
  647                         *retval = temp;
  648                 return error;
  649 
  650         case PT_IO:
  651               {
  652                 struct ptrace_io_desc *piod = addr;
  653 
  654                 iov.iov_base = piod->piod_addr;
  655                 iov.iov_len = piod->piod_len;
  656                 uio.uio_iov = &iov;
  657                 uio.uio_iovcnt = 1;
  658                 uio.uio_offset = (off_t)(vaddr_t)piod->piod_offs;
  659                 uio.uio_resid = piod->piod_len;
  660                 uio.uio_segflg = UIO_USERSPACE;
  661                 uio.uio_procp = p;
  662                 switch (piod->piod_op) {
  663                 case PIOD_READ_I:
  664                         req = PT_READ_I;
  665                         uio.uio_rw = UIO_READ;
  666                         break;
  667                 case PIOD_READ_D:
  668                         req = PT_READ_D;
  669                         uio.uio_rw = UIO_READ;
  670                         break;
  671                 case PIOD_WRITE_I:
  672                         req = PT_WRITE_I;
  673                         uio.uio_rw = UIO_WRITE;
  674                         break;
  675                 case PIOD_WRITE_D:
  676                         req = PT_WRITE_D;
  677                         uio.uio_rw = UIO_WRITE;
  678                         break;
  679                 case PIOD_READ_AUXV:
  680                         req = PT_READ_D;
  681                         uio.uio_rw = UIO_READ;
  682                         temp = ELF_AUX_WORDS * sizeof(char *);
  683                         if (uio.uio_offset > temp)
  684                                 return EIO;
  685                         if (uio.uio_resid > temp - uio.uio_offset)
  686                                 uio.uio_resid = temp - uio.uio_offset;
  687                         piod->piod_len = iov.iov_len = uio.uio_resid;
  688                         uio.uio_offset += tr->ps_auxinfo;
  689 #ifdef MACHINE_STACK_GROWS_UP
  690                         if (uio.uio_offset < (off_t)tr->ps_strings)
  691                                 return EIO;
  692 #else
  693                         if (uio.uio_offset > (off_t)tr->ps_strings)
  694                                 return EIO;
  695                         if ((uio.uio_offset + uio.uio_resid) >
  696                             (off_t)tr->ps_strings)
  697                                 uio.uio_resid = (off_t)tr->ps_strings -
  698                                     uio.uio_offset;
  699 #endif
  700                         break;
  701                 default:
  702                         return EINVAL;
  703                 }
  704                 error = process_domem(p, tr, &uio, req);
  705                 piod->piod_len -= uio.uio_resid;
  706                 return error;
  707               }
  708 
  709         case PT_SETREGS:
  710                 return process_write_regs(t, addr);
  711         case PT_GETREGS:
  712                 return process_read_regs(t, addr);
  713 
  714 #ifdef PT_SETFPREGS
  715         case PT_SETFPREGS:
  716                 return process_write_fpregs(t, addr);
  717 #endif
  718 #ifdef PT_SETFPREGS
  719         case PT_GETFPREGS:
  720                 return process_read_fpregs(t, addr);
  721 #endif
  722 #ifdef PT_SETXMMREGS
  723         case PT_SETXMMREGS:
  724                 return process_write_xmmregs(t, addr);
  725 #endif
  726 #ifdef PT_SETXMMREGS
  727         case PT_GETXMMREGS:
  728                 return process_read_xmmregs(t, addr);
  729 #endif
  730 #ifdef PT_WCOOKIE
  731         case PT_WCOOKIE:
  732                 *(register_t *)addr = process_get_wcookie(t);
  733                 return 0;
  734 #endif
  735         default:
  736                 KASSERTMSG(0, "%s: unhandled request %d", __func__, req);
  737                 break;
  738         }
  739 
  740         return 0;
  741 }
  742 
  743 
  744 /*
  745  * Helper for doing "it could be a PID or TID" lookup.  On failure
  746  * returns NULL; on success returns the selected process and sets *tp
  747  * to an appropriate thread in that process.
  748  */
  749 static inline struct process *
  750 process_tprfind(pid_t tpid, struct proc **tp)
  751 {
  752         if (tpid > THREAD_PID_OFFSET) {
  753                 struct proc *t = tfind(tpid - THREAD_PID_OFFSET);
  754 
  755                 if (t == NULL)
  756                         return NULL;
  757                 *tp = t;
  758                 return t->p_p;
  759         } else {
  760                 struct process *tr = prfind(tpid);
  761 
  762                 if (tr == NULL)
  763                         return NULL;
  764                 *tp = TAILQ_FIRST(&tr->ps_threads);
  765                 return tr;
  766         }
  767 }
  768 
  769 
  770 /*
  771  * Check whether 'tr' is currently traced by 'curpr' and in a state
  772  * to be manipulated.  If 't' is supplied then it must be stopped and
  773  * waited for.
  774  */
  775 static inline int
  776 process_checktracestate(struct process *curpr, struct process *tr,
  777     struct proc *t)
  778 {
  779         /*
  780          * You can't do what you want to the process if:
  781          *      (1) It's not being traced at all,
  782          */
  783         if (!ISSET(tr->ps_flags, PS_TRACED))
  784                 return EPERM;
  785 
  786         /*
  787          *      (2) it's not being traced by _you_, or
  788          */
  789         if (tr->ps_pptr != curpr)
  790                 return EBUSY;
  791 
  792         /*
  793          *      (3) it's in the middle of execve(2)
  794          */
  795         if (ISSET(tr->ps_flags, PS_INEXEC))
  796                 return EAGAIN;
  797 
  798         /*
  799          *      (4) if a thread was specified and it's not currently stopped.
  800          */
  801         if (t != NULL &&
  802             (t->p_stat != SSTOP || !ISSET(tr->ps_flags, PS_WAITED)))
  803                 return EBUSY;
  804 
  805         return 0;
  806 }
  807 
  808 
  809 /*
  810  * Check if a process is allowed to fiddle with the memory of another.
  811  *
  812  * p = tracer
  813  * tr = tracee
  814  *
  815  * 1.  You can't attach to a process not owned by you or one that has raised
  816  *     its privileges.
  817  * 1a. ...unless you are root.
  818  *
  819  * 2.  init is always off-limits because it can control the securelevel.
  820  * 2a. ...unless securelevel is permanently set to insecure.
  821  *
  822  * 3.  Processes that are in the process of doing an exec() are always
  823  *     off-limits because of the can of worms they are. Just wait a
  824  *     second.
  825  */
  826 int
  827 process_checkioperm(struct proc *p, struct process *tr)
  828 {
  829         int error;
  830 
  831         if ((tr->ps_ucred->cr_ruid != p->p_ucred->cr_ruid ||
  832             ISSET(tr->ps_flags, PS_SUGIDEXEC | PS_SUGID)) &&
  833             (error = suser(p)) != 0)
  834                 return (error);
  835 
  836         if ((tr->ps_pid == 1) && (securelevel > -1))
  837                 return (EPERM);
  838 
  839         if (ISSET(tr->ps_flags, PS_INEXEC))
  840                 return (EAGAIN);
  841 
  842         return (0);
  843 }
  844 
  845 int
  846 process_domem(struct proc *curp, struct process *tr, struct uio *uio, int req)
  847 {
  848         struct vmspace *vm;
  849         int error;
  850         vaddr_t addr;
  851         vsize_t len;
  852 
  853         len = uio->uio_resid;
  854         if (len == 0)
  855                 return 0;
  856 
  857         if ((error = process_checkioperm(curp, tr)) != 0)
  858                 return error;
  859 
  860         vm = tr->ps_vmspace;
  861         if ((tr->ps_flags & PS_EXITING) || (vm->vm_refcnt < 1))
  862                 return EFAULT;
  863         addr = uio->uio_offset;
  864 
  865         uvmspace_addref(vm);
  866 
  867         error = uvm_io(&vm->vm_map, uio, UVM_IO_FIXPROT);
  868 
  869         uvmspace_free(vm);
  870 
  871         if (error == 0 && req == PT_WRITE_I)
  872                 pmap_proc_iflush(tr, addr, len);
  873 
  874         return error;
  875 }
  876 #endif

Cache object: 19599501808276658b5d055ac0a7371d


[ 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.