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/compat/linux/linux_ptrace.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  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (c) 2017 Edward Tomasz Napierala <trasz@FreeBSD.org>
    5  *
    6  * This software was developed by SRI International and the University of
    7  * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
    8  * ("CTSRD"), as part of the DARPA CRASH research programme.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  *
   19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   29  * SUCH DAMAGE.
   30  */
   31 
   32 #include <sys/cdefs.h>
   33 __FBSDID("$FreeBSD$");
   34 
   35 #include <sys/param.h>
   36 #include <sys/lock.h>
   37 #include <sys/proc.h>
   38 #include <sys/ptrace.h>
   39 #include <sys/sx.h>
   40 #include <sys/syscallsubr.h>
   41 
   42 #include <machine/../linux/linux.h>
   43 #include <machine/../linux/linux_proto.h>
   44 #include <compat/linux/linux_emul.h>
   45 #include <compat/linux/linux_errno.h>
   46 #include <compat/linux/linux_misc.h>
   47 #include <compat/linux/linux_signal.h>
   48 #include <compat/linux/linux_util.h>
   49 
   50 #define LINUX_PTRACE_TRACEME            0
   51 #define LINUX_PTRACE_PEEKTEXT           1
   52 #define LINUX_PTRACE_PEEKDATA           2
   53 #define LINUX_PTRACE_PEEKUSER           3
   54 #define LINUX_PTRACE_POKETEXT           4
   55 #define LINUX_PTRACE_POKEDATA           5
   56 #define LINUX_PTRACE_POKEUSER           6
   57 #define LINUX_PTRACE_CONT               7
   58 #define LINUX_PTRACE_KILL               8
   59 #define LINUX_PTRACE_SINGLESTEP         9
   60 #define LINUX_PTRACE_GETREGS            12
   61 #define LINUX_PTRACE_SETREGS            13
   62 #define LINUX_PTRACE_GETFPREGS          14
   63 #define LINUX_PTRACE_SETFPREGS          15
   64 #define LINUX_PTRACE_ATTACH             16
   65 #define LINUX_PTRACE_DETACH             17
   66 #define LINUX_PTRACE_SYSCALL            24
   67 #define LINUX_PTRACE_SETOPTIONS         0x4200
   68 #define LINUX_PTRACE_GETEVENTMSG        0x4201
   69 #define LINUX_PTRACE_GETSIGINFO         0x4202
   70 #define LINUX_PTRACE_GETREGSET          0x4204
   71 #define LINUX_PTRACE_SEIZE              0x4206
   72 #define LINUX_PTRACE_GET_SYSCALL_INFO   0x420e
   73 
   74 #define LINUX_PTRACE_EVENT_EXEC         4
   75 #define LINUX_PTRACE_EVENT_EXIT         6
   76 
   77 #define LINUX_PTRACE_O_TRACESYSGOOD     1
   78 #define LINUX_PTRACE_O_TRACEFORK        2
   79 #define LINUX_PTRACE_O_TRACEVFORK       4
   80 #define LINUX_PTRACE_O_TRACECLONE       8
   81 #define LINUX_PTRACE_O_TRACEEXEC        16
   82 #define LINUX_PTRACE_O_TRACEVFORKDONE   32
   83 #define LINUX_PTRACE_O_TRACEEXIT        64
   84 #define LINUX_PTRACE_O_TRACESECCOMP     128
   85 #define LINUX_PTRACE_O_EXITKILL         1048576
   86 #define LINUX_PTRACE_O_SUSPEND_SECCOMP  2097152
   87 
   88 #define LINUX_NT_PRSTATUS               0x1
   89 #define LINUX_NT_PRFPREG                0x2
   90 #define LINUX_NT_X86_XSTATE             0x202
   91 
   92 #define LINUX_PTRACE_O_MASK     (LINUX_PTRACE_O_TRACESYSGOOD |  \
   93     LINUX_PTRACE_O_TRACEFORK | LINUX_PTRACE_O_TRACEVFORK |      \
   94     LINUX_PTRACE_O_TRACECLONE | LINUX_PTRACE_O_TRACEEXEC |      \
   95     LINUX_PTRACE_O_TRACEVFORKDONE | LINUX_PTRACE_O_TRACEEXIT |  \
   96     LINUX_PTRACE_O_TRACESECCOMP | LINUX_PTRACE_O_EXITKILL |     \
   97     LINUX_PTRACE_O_SUSPEND_SECCOMP)
   98 
   99 #define LINUX_PTRACE_SYSCALL_INFO_NONE  0
  100 #define LINUX_PTRACE_SYSCALL_INFO_ENTRY 1
  101 #define LINUX_PTRACE_SYSCALL_INFO_EXIT  2
  102 
  103 #define LINUX_PTRACE_PEEKUSER_ORIG_RAX  120
  104 #define LINUX_PTRACE_PEEKUSER_RIP       128
  105 #define LINUX_PTRACE_PEEKUSER_CS        136
  106 #define LINUX_PTRACE_PEEKUSER_DS        184
  107 
  108 static int
  109 map_signum(int lsig, int *bsigp)
  110 {
  111         int bsig;
  112 
  113         if (lsig == 0) {
  114                 *bsigp = 0;
  115                 return (0);
  116         }
  117 
  118         if (lsig < 0 || lsig > LINUX_SIGRTMAX)
  119                 return (EINVAL);
  120 
  121         bsig = linux_to_bsd_signal(lsig);
  122         if (bsig == SIGSTOP)
  123                 bsig = 0;
  124 
  125         *bsigp = bsig;
  126         return (0);
  127 }
  128 
  129 int
  130 linux_ptrace_status(struct thread *td, pid_t pid, int status)
  131 {
  132         struct ptrace_lwpinfo lwpinfo;
  133         struct linux_pemuldata *pem;
  134         register_t saved_retval;
  135         int error;
  136 
  137         saved_retval = td->td_retval[0];
  138         error = kern_ptrace(td, PT_LWPINFO, pid, &lwpinfo, sizeof(lwpinfo));
  139         td->td_retval[0] = saved_retval;
  140         if (error != 0) {
  141                 linux_msg(td, "PT_LWPINFO failed with error %d", error);
  142                 return (status);
  143         }
  144 
  145         pem = pem_find(td->td_proc);
  146         KASSERT(pem != NULL, ("%s: proc emuldata not found.\n", __func__));
  147 
  148         LINUX_PEM_SLOCK(pem);
  149         if ((pem->ptrace_flags & LINUX_PTRACE_O_TRACESYSGOOD) &&
  150             lwpinfo.pl_flags & PL_FLAG_SCE)
  151                 status |= (LINUX_SIGTRAP | 0x80) << 8;
  152         if ((pem->ptrace_flags & LINUX_PTRACE_O_TRACESYSGOOD) &&
  153             lwpinfo.pl_flags & PL_FLAG_SCX) {
  154                 if (lwpinfo.pl_flags & PL_FLAG_EXEC)
  155                         status |= (LINUX_SIGTRAP | LINUX_PTRACE_EVENT_EXEC << 8) << 8;
  156                 else
  157                         status |= (LINUX_SIGTRAP | 0x80) << 8;
  158         }
  159         if ((pem->ptrace_flags & LINUX_PTRACE_O_TRACEEXIT) &&
  160             lwpinfo.pl_flags & PL_FLAG_EXITED)
  161                 status |= (LINUX_SIGTRAP | LINUX_PTRACE_EVENT_EXIT << 8) << 8;
  162         LINUX_PEM_SUNLOCK(pem);
  163 
  164         return (status);
  165 }
  166 
  167 static int
  168 linux_ptrace_peek(struct thread *td, pid_t pid, void *addr, void *data)
  169 {
  170         int error;
  171 
  172         error = kern_ptrace(td, PT_READ_I, pid, addr, 0);
  173         if (error == 0)
  174                 error = copyout(td->td_retval, data, sizeof(l_int));
  175         else if (error == ENOMEM)
  176                 error = EIO;
  177         td->td_retval[0] = error;
  178 
  179         return (error);
  180 }
  181 
  182 static int
  183 linux_ptrace_peekuser(struct thread *td, pid_t pid, void *addr, void *data)
  184 {
  185         struct reg b_reg;
  186         uint64_t val;
  187         int error;
  188 
  189         error = kern_ptrace(td, PT_GETREGS, pid, &b_reg, 0);
  190         if (error != 0)
  191                 return (error);
  192 
  193         switch ((uintptr_t)addr) {
  194 #ifdef __amd64__
  195         case LINUX_PTRACE_PEEKUSER_ORIG_RAX:
  196                 val = b_reg.r_rax;
  197                 break;
  198         case LINUX_PTRACE_PEEKUSER_RIP:
  199                 val = b_reg.r_rip;
  200                 break;
  201         case LINUX_PTRACE_PEEKUSER_CS:
  202                 val = b_reg.r_cs;
  203                 break;
  204         case LINUX_PTRACE_PEEKUSER_DS:
  205                 val = b_reg.r_ds;
  206                 break;
  207 #endif /* __amd64__ */
  208         default:
  209                 linux_msg(td, "PTRACE_PEEKUSER offset %ld not implemented; "
  210                     "returning EINVAL", (uintptr_t)addr);
  211                 return (EINVAL);
  212         }
  213 
  214         error = copyout(&val, data, sizeof(val));
  215         td->td_retval[0] = error;
  216 
  217         return (error);
  218 }
  219 
  220 static int
  221 linux_ptrace_pokeuser(struct thread *td, pid_t pid, void *addr, void *data)
  222 {
  223 
  224         linux_msg(td, "PTRACE_POKEUSER not implemented; returning EINVAL");
  225         return (EINVAL);
  226 }
  227 
  228 static int
  229 linux_ptrace_setoptions(struct thread *td, pid_t pid, l_ulong data)
  230 {
  231         struct linux_pemuldata *pem;
  232         int mask;
  233 
  234         mask = 0;
  235 
  236         if (data & ~LINUX_PTRACE_O_MASK) {
  237                 linux_msg(td, "unknown ptrace option %lx set; "
  238                     "returning EINVAL",
  239                     data & ~LINUX_PTRACE_O_MASK);
  240                 return (EINVAL);
  241         }
  242 
  243         pem = pem_find(td->td_proc);
  244         KASSERT(pem != NULL, ("%s: proc emuldata not found.\n", __func__));
  245 
  246         /*
  247          * PTRACE_O_EXITKILL is ignored, we do that by default.
  248          */
  249 
  250         LINUX_PEM_XLOCK(pem);
  251         if (data & LINUX_PTRACE_O_TRACESYSGOOD) {
  252                 pem->ptrace_flags |= LINUX_PTRACE_O_TRACESYSGOOD;
  253         } else {
  254                 pem->ptrace_flags &= ~LINUX_PTRACE_O_TRACESYSGOOD;
  255         }
  256         LINUX_PEM_XUNLOCK(pem);
  257 
  258         if (data & LINUX_PTRACE_O_TRACEFORK)
  259                 mask |= PTRACE_FORK;
  260 
  261         if (data & LINUX_PTRACE_O_TRACEVFORK)
  262                 mask |= PTRACE_VFORK;
  263 
  264         if (data & LINUX_PTRACE_O_TRACECLONE)
  265                 mask |= PTRACE_VFORK;
  266 
  267         if (data & LINUX_PTRACE_O_TRACEEXEC)
  268                 mask |= PTRACE_EXEC;
  269 
  270         if (data & LINUX_PTRACE_O_TRACEVFORKDONE)
  271                 mask |= PTRACE_VFORK; /* XXX: Close enough? */
  272 
  273         if (data & LINUX_PTRACE_O_TRACEEXIT) {
  274                 pem->ptrace_flags |= LINUX_PTRACE_O_TRACEEXIT;
  275         } else {
  276                 pem->ptrace_flags &= ~LINUX_PTRACE_O_TRACEEXIT;
  277         }
  278 
  279         return (kern_ptrace(td, PT_SET_EVENT_MASK, pid, &mask, sizeof(mask)));
  280 }
  281 
  282 static int
  283 linux_ptrace_geteventmsg(struct thread *td, pid_t pid, l_ulong data)
  284 {
  285 
  286         linux_msg(td, "PTRACE_GETEVENTMSG not implemented; returning EINVAL");
  287         return (EINVAL);
  288 }
  289 
  290 static int
  291 linux_ptrace_getsiginfo(struct thread *td, pid_t pid, l_ulong data)
  292 {
  293         struct ptrace_lwpinfo lwpinfo;
  294         l_siginfo_t l_siginfo;
  295         int error, sig;
  296 
  297         error = kern_ptrace(td, PT_LWPINFO, pid, &lwpinfo, sizeof(lwpinfo));
  298         if (error != 0) {
  299                 linux_msg(td, "PT_LWPINFO failed with error %d", error);
  300                 return (error);
  301         }
  302 
  303         if ((lwpinfo.pl_flags & PL_FLAG_SI) == 0) {
  304                 error = EINVAL;
  305                 linux_msg(td, "no PL_FLAG_SI, returning %d", error);
  306                 return (error);
  307         }
  308 
  309         sig = bsd_to_linux_signal(lwpinfo.pl_siginfo.si_signo);
  310         memset(&l_siginfo, 0, sizeof(l_siginfo));
  311         siginfo_to_lsiginfo(&lwpinfo.pl_siginfo, &l_siginfo, sig);
  312         error = copyout(&l_siginfo, (void *)data, sizeof(l_siginfo));
  313         return (error);
  314 }
  315 
  316 static int
  317 linux_ptrace_getregs(struct thread *td, pid_t pid, void *data)
  318 {
  319         struct reg b_reg;
  320         struct linux_pt_regset l_regset;
  321         int error;
  322 
  323         error = kern_ptrace(td, PT_GETREGS, pid, &b_reg, 0);
  324         if (error != 0)
  325                 return (error);
  326 
  327         bsd_to_linux_regset(&b_reg, &l_regset);
  328         error = linux_ptrace_getregs_machdep(td, pid, &l_regset);
  329         if (error != 0)
  330                 return (error);
  331 
  332         error = copyout(&l_regset, (void *)data, sizeof(l_regset));
  333         return (error);
  334 }
  335 
  336 static int
  337 linux_ptrace_setregs(struct thread *td, pid_t pid, void *data)
  338 {
  339         struct reg b_reg;
  340         struct linux_pt_regset l_regset;
  341         int error;
  342 
  343         error = copyin(data, &l_regset, sizeof(l_regset));
  344         if (error != 0)
  345                 return (error);
  346         linux_to_bsd_regset(&b_reg, &l_regset);
  347         error = kern_ptrace(td, PT_SETREGS, pid, &b_reg, 0);
  348         return (error);
  349 }
  350 
  351 static int
  352 linux_ptrace_getregset_prstatus(struct thread *td, pid_t pid, l_ulong data)
  353 {
  354         struct reg b_reg;
  355         struct linux_pt_regset l_regset;
  356         struct iovec iov;
  357         size_t len;
  358         int error;
  359 
  360         error = copyin((const void *)data, &iov, sizeof(iov));
  361         if (error != 0) {
  362                 linux_msg(td, "copyin error %d", error);
  363                 return (error);
  364         }
  365 
  366         error = kern_ptrace(td, PT_GETREGS, pid, &b_reg, 0);
  367         if (error != 0)
  368                 return (error);
  369 
  370         bsd_to_linux_regset(&b_reg, &l_regset);
  371         error = linux_ptrace_getregs_machdep(td, pid, &l_regset);
  372         if (error != 0)
  373                 return (error);
  374 
  375         len = MIN(iov.iov_len, sizeof(l_regset));
  376         error = copyout(&l_regset, (void *)iov.iov_base, len);
  377         if (error != 0) {
  378                 linux_msg(td, "copyout error %d", error);
  379                 return (error);
  380         }
  381 
  382         iov.iov_len = len;
  383         error = copyout(&iov, (void *)data, sizeof(iov));
  384         if (error != 0) {
  385                 linux_msg(td, "iov copyout error %d", error);
  386                 return (error);
  387         }
  388 
  389         return (error);
  390 }
  391 
  392 static int
  393 linux_ptrace_getregset(struct thread *td, pid_t pid, l_ulong addr, l_ulong data)
  394 {
  395 
  396         switch (addr) {
  397         case LINUX_NT_PRSTATUS:
  398                 return (linux_ptrace_getregset_prstatus(td, pid, data));
  399         case LINUX_NT_PRFPREG:
  400                 linux_msg(td, "PTRAGE_GETREGSET NT_PRFPREG not implemented; "
  401                     "returning EINVAL");
  402                 return (EINVAL);
  403         case LINUX_NT_X86_XSTATE:
  404                 linux_msg(td, "PTRAGE_GETREGSET NT_X86_XSTATE not implemented; "
  405                     "returning EINVAL");
  406                 return (EINVAL);
  407         default:
  408                 linux_msg(td, "PTRACE_GETREGSET request %#lx not implemented; "
  409                     "returning EINVAL", addr);
  410                 return (EINVAL);
  411         }
  412 }
  413 
  414 static int
  415 linux_ptrace_seize(struct thread *td, pid_t pid, l_ulong addr, l_ulong data)
  416 {
  417 
  418         linux_msg(td, "PTRACE_SEIZE not implemented; returning EINVAL");
  419         return (EINVAL);
  420 }
  421 
  422 static int
  423 linux_ptrace_get_syscall_info(struct thread *td, pid_t pid,
  424     l_ulong len, l_ulong data)
  425 {
  426         struct ptrace_lwpinfo lwpinfo;
  427         struct ptrace_sc_ret sr;
  428         struct reg b_reg;
  429         struct syscall_info si;
  430         int error;
  431 
  432         error = kern_ptrace(td, PT_LWPINFO, pid, &lwpinfo, sizeof(lwpinfo));
  433         if (error != 0) {
  434                 linux_msg(td, "PT_LWPINFO failed with error %d", error);
  435                 return (error);
  436         }
  437 
  438         memset(&si, 0, sizeof(si));
  439 
  440         if (lwpinfo.pl_flags & PL_FLAG_SCE) {
  441                 si.op = LINUX_PTRACE_SYSCALL_INFO_ENTRY;
  442                 si.entry.nr = lwpinfo.pl_syscall_code;
  443                 /*
  444                  * The use of PT_GET_SC_ARGS there is special,
  445                  * implementation of PT_GET_SC_ARGS for Linux-ABI
  446                  * callers emulates Linux bug which strace(1) depends
  447                  * on: at initialization it tests whether ptrace works
  448                  * by calling close(2), or some other single-argument
  449                  * syscall, _with six arguments_, and then verifies
  450                  * whether it can fetch them all using this API;
  451                  * otherwise it bails out.
  452                  */
  453                 error = kern_ptrace(td, PT_GET_SC_ARGS, pid,
  454                     &si.entry.args, sizeof(si.entry.args));
  455                 if (error != 0) {
  456                         linux_msg(td, "PT_GET_SC_ARGS failed with error %d",
  457                             error);
  458                         return (error);
  459                 }
  460         } else if (lwpinfo.pl_flags & PL_FLAG_SCX) {
  461                 si.op = LINUX_PTRACE_SYSCALL_INFO_EXIT;
  462                 error = kern_ptrace(td, PT_GET_SC_RET, pid, &sr, sizeof(sr));
  463 
  464                 if (error != 0) {
  465                         linux_msg(td, "PT_GET_SC_RET failed with error %d",
  466                             error);
  467                         return (error);
  468                 }
  469 
  470                 if (sr.sr_error == 0) {
  471                         si.exit.rval = sr.sr_retval[0];
  472                         si.exit.is_error = 0;
  473                 } else if (sr.sr_error == EJUSTRETURN) {
  474                         /*
  475                          * EJUSTRETURN means the actual value to return
  476                          * has already been put into td_frame; instead
  477                          * of extracting it and trying to determine whether
  478                          * it's an error or not just bail out and let
  479                          * the ptracing process fall back to another method.
  480                          */
  481                         si.op = LINUX_PTRACE_SYSCALL_INFO_NONE;
  482                 } else if (sr.sr_error == ERESTART) {
  483                         si.exit.rval = -LINUX_ERESTARTSYS;
  484                         si.exit.is_error = 1;
  485                 } else {
  486                         si.exit.rval = bsd_to_linux_errno(sr.sr_error);
  487                         si.exit.is_error = 1;
  488                 }
  489         } else {
  490                 si.op = LINUX_PTRACE_SYSCALL_INFO_NONE;
  491         }
  492 
  493         error = kern_ptrace(td, PT_GETREGS, pid, &b_reg, 0);
  494         if (error != 0)
  495                 return (error);
  496 
  497         linux_ptrace_get_syscall_info_machdep(&b_reg, &si);
  498 
  499         len = MIN(len, sizeof(si));
  500         error = copyout(&si, (void *)data, len);
  501         if (error == 0)
  502                 td->td_retval[0] = sizeof(si);
  503 
  504         return (error);
  505 }
  506 
  507 int
  508 linux_ptrace(struct thread *td, struct linux_ptrace_args *uap)
  509 {
  510         void *addr;
  511         pid_t pid;
  512         int error, sig;
  513 
  514         if (!allow_ptrace)
  515                 return (ENOSYS);
  516 
  517         pid  = (pid_t)uap->pid;
  518         addr = (void *)uap->addr;
  519 
  520         switch (uap->req) {
  521         case LINUX_PTRACE_TRACEME:
  522                 error = kern_ptrace(td, PT_TRACE_ME, 0, 0, 0);
  523                 break;
  524         case LINUX_PTRACE_PEEKTEXT:
  525         case LINUX_PTRACE_PEEKDATA:
  526                 error = linux_ptrace_peek(td, pid, addr, (void *)uap->data);
  527                 if (error != 0)
  528                         goto out;
  529                 /*
  530                  * Linux expects this syscall to read 64 bits, not 32.
  531                  */
  532                 error = linux_ptrace_peek(td, pid,
  533                     (void *)(uap->addr + 4), (void *)(uap->data + 4));
  534                 break;
  535         case LINUX_PTRACE_PEEKUSER:
  536                 error = linux_ptrace_peekuser(td, pid, addr, (void *)uap->data);
  537                 break;
  538         case LINUX_PTRACE_POKETEXT:
  539         case LINUX_PTRACE_POKEDATA:
  540                 error = kern_ptrace(td, PT_WRITE_D, pid, addr, uap->data);
  541                 if (error != 0)
  542                         goto out;
  543                 /*
  544                  * Linux expects this syscall to write 64 bits, not 32.
  545                  */
  546                 error = kern_ptrace(td, PT_WRITE_D, pid,
  547                     (void *)(uap->addr + 4), uap->data >> 32);
  548                 break;
  549         case LINUX_PTRACE_POKEUSER:
  550                 error = linux_ptrace_pokeuser(td, pid, addr, (void *)uap->data);
  551                 break;
  552         case LINUX_PTRACE_CONT:
  553                 error = map_signum(uap->data, &sig);
  554                 if (error != 0)
  555                         break;
  556                 error = kern_ptrace(td, PT_CONTINUE, pid, (void *)1, sig);
  557                 break;
  558         case LINUX_PTRACE_KILL:
  559                 error = kern_ptrace(td, PT_KILL, pid, addr, uap->data);
  560                 break;
  561         case LINUX_PTRACE_SINGLESTEP:
  562                 error = map_signum(uap->data, &sig);
  563                 if (error != 0)
  564                         break;
  565                 error = kern_ptrace(td, PT_STEP, pid, (void *)1, sig);
  566                 break;
  567         case LINUX_PTRACE_GETREGS:
  568                 error = linux_ptrace_getregs(td, pid, (void *)uap->data);
  569                 break;
  570         case LINUX_PTRACE_SETREGS:
  571                 error = linux_ptrace_setregs(td, pid, (void *)uap->data);
  572                 break;
  573         case LINUX_PTRACE_ATTACH:
  574                 error = kern_ptrace(td, PT_ATTACH, pid, addr, uap->data);
  575                 break;
  576         case LINUX_PTRACE_DETACH:
  577                 error = map_signum(uap->data, &sig);
  578                 if (error != 0)
  579                         break;
  580                 error = kern_ptrace(td, PT_DETACH, pid, (void *)1, sig);
  581                 break;
  582         case LINUX_PTRACE_SYSCALL:
  583                 error = map_signum(uap->data, &sig);
  584                 if (error != 0)
  585                         break;
  586                 error = kern_ptrace(td, PT_SYSCALL, pid, (void *)1, sig);
  587                 break;
  588         case LINUX_PTRACE_SETOPTIONS:
  589                 error = linux_ptrace_setoptions(td, pid, uap->data);
  590                 break;
  591         case LINUX_PTRACE_GETEVENTMSG:
  592                 error = linux_ptrace_geteventmsg(td, pid, uap->data);
  593                 break;
  594         case LINUX_PTRACE_GETSIGINFO:
  595                 error = linux_ptrace_getsiginfo(td, pid, uap->data);
  596                 break;
  597         case LINUX_PTRACE_GETREGSET:
  598                 error = linux_ptrace_getregset(td, pid, uap->addr, uap->data);
  599                 break;
  600         case LINUX_PTRACE_SEIZE:
  601                 error = linux_ptrace_seize(td, pid, uap->addr, uap->data);
  602                 break;
  603         case LINUX_PTRACE_GET_SYSCALL_INFO:
  604                 error = linux_ptrace_get_syscall_info(td, pid, uap->addr, uap->data);
  605                 break;
  606         default:
  607                 linux_msg(td, "ptrace(%ld, ...) not implemented; "
  608                     "returning EINVAL", uap->req);
  609                 error = EINVAL;
  610                 break;
  611         }
  612 
  613 out:
  614         if (error == EBUSY)
  615                 error = ESRCH;
  616 
  617         return (error);
  618 }

Cache object: 7de8ecf282cef339918166879f49b48c


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