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/bsd/kern/mach_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 /*
    2  * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved.
    3  *
    4  * @APPLE_LICENSE_HEADER_START@
    5  * 
    6  * Copyright (c) 1999-2003 Apple Computer, Inc.  All Rights Reserved.
    7  * 
    8  * This file contains Original Code and/or Modifications of Original Code
    9  * as defined in and that are subject to the Apple Public Source License
   10  * Version 2.0 (the 'License'). You may not use this file except in
   11  * compliance with the License. Please obtain a copy of the License at
   12  * http://www.opensource.apple.com/apsl/ and read it before using this
   13  * file.
   14  * 
   15  * The Original Code and all software distributed under the License are
   16  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
   17  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
   18  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
   19  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
   20  * Please see the License for the specific language governing rights and
   21  * limitations under the License.
   22  * 
   23  * @APPLE_LICENSE_HEADER_END@
   24  */
   25 /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
   26 /*-
   27  * Copyright (c) 1982, 1986, 1989, 1993
   28  *      The Regents of the University of California.  All rights reserved.
   29  * (c) UNIX System Laboratories, Inc.
   30  * All or some portions of this file are derived from material licensed
   31  * to the University of California by American Telephone and Telegraph
   32  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
   33  * the permission of UNIX System Laboratories, Inc.
   34  *
   35  * Redistribution and use in source and binary forms, with or without
   36  * modification, are permitted provided that the following conditions
   37  * are met:
   38  * 1. Redistributions of source code must retain the above copyright
   39  *    notice, this list of conditions and the following disclaimer.
   40  * 2. Redistributions in binary form must reproduce the above copyright
   41  *    notice, this list of conditions and the following disclaimer in the
   42  *    documentation and/or other materials provided with the distribution.
   43  * 3. All advertising materials mentioning features or use of this software
   44  *    must display the following acknowledgement:
   45  *      This product includes software developed by the University of
   46  *      California, Berkeley and its contributors.
   47  * 4. Neither the name of the University nor the names of its contributors
   48  *    may be used to endorse or promote products derived from this software
   49  *    without specific prior written permission.
   50  *
   51  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   52  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   53  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   54  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   55  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   56  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   57  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   58  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   59  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   60  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   61  * SUCH DAMAGE.
   62  *
   63  *      from: @(#)sys_process.c 8.1 (Berkeley) 6/10/93
   64  */
   65 
   66 #include <machine/reg.h>
   67 #include <machine/psl.h>
   68 
   69 #include <sys/param.h>
   70 #include <sys/systm.h>
   71 #include <sys/proc.h>
   72 #include <sys/errno.h>
   73 #include <sys/ptrace.h>
   74 #include <sys/uio.h>
   75 #include <sys/user.h>
   76 #include <sys/sysctl.h>
   77 #include <sys/wait.h>
   78 
   79 #include <sys/mount.h>
   80 
   81 #include <kern/task.h>
   82 #include <kern/thread.h>
   83 #include <mach/machine/thread_status.h>
   84 
   85 /* Macros to clear/set/test flags. */
   86 #define SET(t, f)       (t) |= (f)
   87 #define CLR(t, f)       (t) &= ~(f)
   88 #define ISSET(t, f)     ((t) & (f))
   89 
   90 void psignal_lock __P((struct proc *, int, int));
   91 int isinferior __P((struct proc *, struct proc *));
   92 
   93 /*
   94  * sys-trace system call.
   95  */
   96 struct ptrace_args {
   97         int     req;
   98         pid_t pid;
   99         caddr_t addr;
  100         int     data;
  101 };
  102 
  103 int
  104 ptrace(p, uap, retval)
  105         struct proc *p;
  106         struct ptrace_args *uap;
  107         register_t *retval;
  108 {
  109         struct proc *t = current_proc();        /* target process */
  110         vm_offset_t     start_addr, end_addr,
  111                         kern_addr, offset;
  112         vm_size_t       size;
  113         task_t          task;
  114         thread_t        thread;
  115         thread_act_t    th_act;
  116         struct uthread  *ut;
  117         int             *locr0;
  118         int error = 0;
  119 #if defined(ppc)
  120         struct ppc_thread_state64 statep;
  121 #elif   defined(i386)
  122         struct i386_saved_state statep;
  123 #else
  124 #error architecture not supported
  125 #endif
  126         unsigned long state_count;
  127         int tr_sigexc = 0;
  128 
  129 
  130         if (uap->req == PT_DENY_ATTACH) {
  131                 if (ISSET(p->p_flag, P_TRACED)) {
  132                                 exit1(p, W_EXITCODE(ENOTSUP, 0), retval);
  133                                 /* drop funnel before we return */
  134                                 thread_funnel_set(kernel_flock, FALSE);
  135                                 thread_exception_return();
  136                                 /* NOTREACHED */
  137                         }
  138                 SET(p->p_flag, P_NOATTACH);
  139 
  140                 return(0);
  141         }
  142 
  143         if (uap->req == PT_FORCEQUOTA) {
  144                 if (is_suser()) {
  145                         SET(t->p_flag, P_FORCEQUOTA);
  146                         return (0);
  147                 } else
  148                         return (EPERM);
  149         }
  150 
  151         /*
  152          *      Intercept and deal with "please trace me" request.
  153          */      
  154         if (uap->req == PT_TRACE_ME) {
  155                 SET(p->p_flag, P_TRACED);
  156                 /* Non-attached case, our tracer is our parent. */
  157                 t->p_oppid = t->p_pptr->p_pid;
  158                 return(0);
  159         }
  160         if (uap->req == PT_SIGEXC) {
  161                 if (ISSET(p->p_flag, P_TRACED)) {
  162                         SET(p->p_flag, P_SIGEXC);
  163                         return(0);
  164                 } else
  165                         return(EINVAL);
  166         }
  167 
  168         /*
  169          *      Locate victim, and make sure it is traceable.
  170          */
  171         if ((t = pfind(uap->pid)) == NULL)
  172                         return (ESRCH);
  173 
  174 
  175         /* We do not want ptrace to do anything with kernel, init 
  176          * and mach_init
  177          */
  178         if (uap->pid <=2 )
  179                 return (EPERM);
  180 
  181         task = t->task;
  182         if (uap->req == PT_ATTACHEXC) {
  183                 uap->req = PT_ATTACH;
  184                 tr_sigexc = 1;
  185         }
  186         if (uap->req == PT_ATTACH) {
  187 
  188                 /*
  189                  * You can't attach to a process if:
  190                  *      (1) it's the process that's doing the attaching,
  191                  */
  192                 if (t->p_pid == p->p_pid)
  193                         return (EINVAL);
  194 
  195                 /*
  196                  *      (2) it's already being traced, or
  197                  */
  198                 if (ISSET(t->p_flag, P_TRACED))
  199                         return (EBUSY);
  200 
  201                 /*
  202                  *      (3) it's not owned by you, or is set-id on exec
  203                  *          (unless you're root).
  204                  */
  205                 if ((t->p_cred->p_ruid != p->p_cred->p_ruid ||
  206                         ISSET(t->p_flag, P_SUGID)) &&
  207                     (error = suser(p->p_ucred, &p->p_acflag)) != 0)
  208                         return (error);
  209 
  210                 if ((p->p_flag & P_TRACED) && isinferior(p, t))
  211                         return(EPERM);
  212 
  213                 if (ISSET(t->p_flag, P_NOATTACH)) {
  214                         psignal(p, SIGSEGV);
  215                         return (EBUSY);
  216                 }
  217                 SET(t->p_flag, P_TRACED);
  218                 if (tr_sigexc) 
  219                         SET(t->p_flag, P_SIGEXC);
  220 
  221                 t->p_oppid = t->p_pptr->p_pid;
  222                 if (t->p_pptr != p)
  223                         proc_reparent(t, p);
  224 
  225                 if (get_task_userstop(task) == 0 ) {
  226                         t->p_xstat = 0;
  227                         psignal(t, SIGSTOP);
  228                 } else {
  229                         t->p_xstat = SIGSTOP; 
  230                         task_resume(task);       
  231                 }
  232                 return(0);
  233         }
  234 
  235         /*
  236          * You can't do what you want to the process if:
  237          *      (1) It's not being traced at all,
  238          */
  239         if (!ISSET(t->p_flag, P_TRACED))
  240                 return (EPERM);
  241 
  242         /*
  243          *      (2) it's not being traced by _you_, or
  244          */
  245         if (t->p_pptr != p)
  246                 return (EBUSY);
  247 
  248         /*
  249          *      (3) it's not currently stopped.
  250          */
  251         if (t->p_stat != SSTOP)
  252                 return (EBUSY);
  253 
  254         /*
  255          *      Mach version of ptrace executes request directly here,
  256          *      thus simplifying the interaction of ptrace and signals.
  257          */
  258         switch (uap->req) {
  259 
  260         case PT_DETACH:
  261                 if (t->p_oppid != t->p_pptr->p_pid) {
  262                         struct proc *pp;
  263 
  264                         pp = pfind(t->p_oppid);
  265                         proc_reparent(t, pp ? pp : initproc);
  266                 }
  267 
  268                 t->p_oppid = 0;
  269                 CLR(t->p_flag, P_TRACED);
  270                 CLR(t->p_flag, P_SIGEXC);
  271                 goto resume;
  272                 
  273         case PT_KILL:
  274                 /*
  275                  *      Tell child process to kill itself after it
  276                  *      is resumed by adding NSIG to p_cursig. [see issig]
  277                  */
  278                 psignal_lock(t, SIGKILL, 0);
  279                 goto resume;
  280 
  281         case PT_STEP:                   /* single step the child */
  282         case PT_CONTINUE:               /* continue the child */
  283                 th_act = (thread_act_t)get_firstthread(task);
  284                 if (th_act == THR_ACT_NULL)
  285                         goto errorLabel;
  286                 ut = (uthread_t)get_bsdthread_info(th_act);
  287                 locr0 = ut->uu_ar0;
  288 #if defined(i386)
  289                 state_count = i386_NEW_THREAD_STATE_COUNT;
  290                 if (thread_getstatus(th_act, i386_NEW_THREAD_STATE, &statep, &state_count)  != KERN_SUCCESS) {
  291                         goto errorLabel;
  292                 }       
  293 #elif defined(ppc)
  294                 state_count = PPC_THREAD_STATE64_COUNT;
  295                 if (thread_getstatus(th_act, PPC_THREAD_STATE64, &statep, &state_count)  != KERN_SUCCESS) {
  296                         goto errorLabel;
  297                 }       
  298 #else
  299 #error architecture not supported
  300 #endif
  301                 if ((int)uap->addr != 1) {
  302 #if     defined(i386)
  303                         locr0[PC] = (int)uap->addr;
  304 #elif   defined(ppc)
  305 #define ALIGNED(addr,size)      (((unsigned)(addr)&((size)-1))==0)
  306                 if (!ALIGNED((int)uap->addr, sizeof(int)))
  307                         return (ERESTART);
  308 
  309                 statep.srr0 = (uint64_t)((uint32_t)uap->addr);
  310                 state_count = PPC_THREAD_STATE64_COUNT;
  311                 if (thread_setstatus(th_act, PPC_THREAD_STATE64, &statep, &state_count)  != KERN_SUCCESS) {
  312                         goto errorLabel;
  313                 }       
  314 #undef  ALIGNED
  315 #else
  316 #error architecture not implemented!
  317 #endif
  318                 } /* (int)uap->addr != 1 */
  319 
  320                 if ((unsigned)uap->data < 0 || (unsigned)uap->data >= NSIG)
  321                         goto errorLabel;
  322 
  323                 if (uap->data != 0) {
  324                         psignal_lock(t, uap->data, 0);
  325                 }
  326 #if defined(ppc)
  327                 state_count = PPC_THREAD_STATE64_COUNT;
  328                 if (thread_getstatus(th_act, PPC_THREAD_STATE64, &statep, &state_count)  != KERN_SUCCESS) {
  329                         goto errorLabel;
  330                 }       
  331 #endif
  332 
  333 #define MSR_SE_BIT      21
  334 
  335                 if (uap->req == PT_STEP) {
  336 #if     defined(i386)
  337                         locr0[PS] |= PSL_T;
  338 #elif   defined(ppc)
  339                         statep.srr1 |= MASK(MSR_SE);
  340 #else
  341 #error architecture not implemented!
  342 #endif
  343                 } /* uap->req == PT_STEP */
  344                 else {  /* PT_CONTINUE - clear trace bit if set */
  345 #if defined(i386)
  346                         locr0[PS] &= ~PSL_T;
  347 #elif defined(ppc)
  348                         statep.srr1 &= ~MASK(MSR_SE);
  349 #endif
  350                 }
  351 #if defined (ppc)
  352                 state_count = PPC_THREAD_STATE64_COUNT;
  353                 if (thread_setstatus(th_act, PPC_THREAD_STATE64, &statep, &state_count)  != KERN_SUCCESS) {
  354                         goto errorLabel;
  355                 }       
  356 #endif
  357         resume:
  358                 t->p_xstat = uap->data;
  359                 t->p_stat = SRUN;
  360                 if (t->sigwait) {
  361                         wakeup((caddr_t)&(t->sigwait));
  362                         if ((t->p_flag & P_SIGEXC) == 0)
  363                                 task_release(task);
  364                 }
  365                 break;
  366                 
  367         case PT_THUPDATE:  {
  368                 thread_act_t target_act;
  369 
  370                 if ((unsigned)uap->data >= NSIG)
  371                         goto errorLabel;
  372                 th_act = (thread_act_t)port_name_to_act((void *)uap->addr);
  373                 if (th_act == THR_ACT_NULL)
  374                         return (ESRCH);
  375                 ut = (uthread_t)get_bsdthread_info(th_act);
  376                 if (uap->data)
  377                         ut->uu_siglist |= sigmask(uap->data);
  378                 t->p_xstat = uap->data;
  379                 t->p_stat = SRUN;
  380                 act_deallocate(th_act);
  381                 return(0);
  382                 }
  383                 break;
  384 errorLabel:
  385         default:
  386                 return(EINVAL);
  387         }
  388 
  389         return(0);
  390 }
  391 

Cache object: d01e2497036c191427a99280000340d2


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