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_lwpstatus.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_lwpstatus.c,v 1.4 2022/07/10 17:47:58 riastradh Exp $      */
    2 
    3 /*-
    4  * Copyright (c) 2019 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  *
   16  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   17  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   18  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   19  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   20  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   26  * POSSIBILITY OF SUCH DAMAGE.
   27  */
   28 
   29 #include <sys/cdefs.h>
   30 __KERNEL_RCSID(0, "$NetBSD: sys_process_lwpstatus.c,v 1.4 2022/07/10 17:47:58 riastradh Exp $");
   31 
   32 #ifdef _KERNEL_OPT
   33 #include "opt_ptrace.h"
   34 #include "opt_ktrace.h"
   35 #include "opt_pax.h"
   36 #include "opt_compat_netbsd32.h"
   37 #endif
   38 
   39 #if defined(__HAVE_COMPAT_NETBSD32) && !defined(COMPAT_NETBSD32) \
   40     && !defined(_RUMPKERNEL)
   41 #define COMPAT_NETBSD32
   42 #endif
   43 
   44 #include <sys/param.h>
   45 #include <sys/systm.h>
   46 #include <sys/errno.h>
   47 #include <sys/lwp.h>
   48 #include <sys/proc.h>
   49 #include <sys/ptrace.h>
   50 
   51 #ifndef PTRACE_REGS_ALIGN
   52 #define PTRACE_REGS_ALIGN /* nothing */
   53 #endif
   54 
   55 void
   56 ptrace_read_lwpstatus(struct lwp *l, struct ptrace_lwpstatus *pls)
   57 {
   58 
   59         pls->pl_lwpid = l->l_lid;
   60         memcpy(&pls->pl_sigmask, &l->l_sigmask, sizeof(pls->pl_sigmask));
   61         memcpy(&pls->pl_sigpend, &l->l_sigpend.sp_set, sizeof(pls->pl_sigpend));
   62 
   63         if (l->l_name == NULL)
   64                 memset(&pls->pl_name, 0, PL_LNAMELEN);
   65         else {
   66                 KASSERT(strlen(l->l_name) < PL_LNAMELEN);
   67                 strncpy(pls->pl_name, l->l_name, PL_LNAMELEN);
   68         }
   69 
   70 #ifdef PTRACE_LWP_GETPRIVATE
   71         pls->pl_private = (void *)(intptr_t)PTRACE_LWP_GETPRIVATE(l);
   72 #else
   73         pls->pl_private = l->l_private;
   74 #endif
   75 }
   76 
   77 void
   78 process_read_lwpstatus(struct lwp *l, struct ptrace_lwpstatus *pls)
   79 {
   80 
   81         ptrace_read_lwpstatus(l, pls);
   82 }
   83 
   84 int
   85 ptrace_update_lwp(struct proc *t, struct lwp **lt, lwpid_t lid)
   86 {
   87         if (lid == 0 || lid == (*lt)->l_lid || t->p_nlwps == 1)
   88                 return 0;
   89 
   90         mutex_enter(t->p_lock);
   91         lwp_delref2(*lt);
   92 
   93         *lt = lwp_find(t, lid);
   94         if (*lt == NULL) {
   95                 mutex_exit(t->p_lock);
   96                 return ESRCH;
   97         }
   98 
   99         if ((*lt)->l_flag & LW_SYSTEM) {
  100                 mutex_exit(t->p_lock);
  101                 *lt = NULL;
  102                 return EINVAL;
  103         }
  104 
  105         lwp_addref(*lt);
  106         mutex_exit(t->p_lock);
  107 
  108         return 0;
  109 }
  110 
  111 int
  112 process_validfpregs(struct lwp *l)
  113 {
  114 
  115 #if defined(PT_SETFPREGS) || defined(PT_GETFPREGS)
  116         return (l->l_flag & LW_SYSTEM) == 0;
  117 #else
  118         return 0;
  119 #endif
  120 }
  121 
  122 int
  123 process_validregs(struct lwp *l)
  124 {
  125 
  126 #if defined(PT_SETREGS) || defined(PT_GETREGS)
  127         return (l->l_flag & LW_SYSTEM) == 0;
  128 #else
  129         return 0;
  130 #endif
  131 }
  132 
  133 int
  134 process_validdbregs(struct lwp *l)
  135 {
  136 
  137 #if defined(PT_SETDBREGS) || defined(PT_GETDBREGS)
  138         return (l->l_flag & LW_SYSTEM) == 0;
  139 #else
  140         return 0;
  141 #endif
  142 }
  143 
  144 #ifdef PT_REGISTERS
  145 static int
  146 proc_regio(struct lwp *l, struct uio *uio, size_t ks, ptrace_regrfunc_t r,
  147     ptrace_regwfunc_t w)
  148 {
  149         char buf[1024] PTRACE_REGS_ALIGN;
  150         int error;
  151         char *kv;
  152         size_t kl;
  153 
  154         if (ks > sizeof(buf))
  155                 return E2BIG;
  156 
  157         if (uio->uio_offset < 0 || uio->uio_offset > (off_t)ks)
  158                 return EINVAL;
  159 
  160         kv = buf + uio->uio_offset;
  161         kl = ks - uio->uio_offset;
  162 
  163         if (kl > uio->uio_resid)
  164                 kl = uio->uio_resid;
  165 
  166         error = (*r)(l, buf, &ks);
  167         if (error == 0)
  168                 error = uiomove(kv, kl, uio);
  169         if (error == 0 && uio->uio_rw == UIO_WRITE) {
  170                 if (l->l_stat != LSSTOP)
  171                         error = EBUSY;
  172                 else
  173                         error = (*w)(l, buf, ks);
  174         }
  175 
  176         uio->uio_offset = 0;
  177         return error;
  178 }
  179 #endif
  180 
  181 int
  182 process_doregs(struct lwp *curl /*tracer*/,
  183     struct lwp *l /*traced*/,
  184     struct uio *uio)
  185 {
  186 #if defined(PT_GETREGS) || defined(PT_SETREGS)
  187         size_t s;
  188         ptrace_regrfunc_t r;
  189         ptrace_regwfunc_t w;
  190 
  191 #ifdef COMPAT_NETBSD32
  192         const bool pk32 = (curl->l_proc->p_flag & PK_32) != 0;
  193 
  194         if (__predict_false(pk32)) {
  195                 if ((l->l_proc->p_flag & PK_32) == 0) {
  196                         // 32 bit tracer can't trace 64 bit process
  197                         return EINVAL;
  198                 }
  199                 s = sizeof(process_reg32);
  200                 r = __FPTRCAST(ptrace_regrfunc_t, process_read_regs32);
  201                 w = __FPTRCAST(ptrace_regwfunc_t, process_write_regs32);
  202         } else
  203 #endif
  204         {
  205                 s = sizeof(struct reg);
  206                 r = __FPTRCAST(ptrace_regrfunc_t, process_read_regs);
  207                 w = __FPTRCAST(ptrace_regwfunc_t, process_write_regs);
  208         }
  209         return proc_regio(l, uio, s, r, w);
  210 #else
  211         return EINVAL;
  212 #endif
  213 }
  214 
  215 int
  216 process_dofpregs(struct lwp *curl /*tracer*/,
  217     struct lwp *l /*traced*/,
  218     struct uio *uio)
  219 {
  220 #if defined(PT_GETFPREGS) || defined(PT_SETFPREGS)
  221         size_t s;
  222         ptrace_regrfunc_t r;
  223         ptrace_regwfunc_t w;
  224 
  225 #ifdef COMPAT_NETBSD32
  226         const bool pk32 = (curl->l_proc->p_flag & PK_32) != 0;
  227 
  228         if (__predict_false(pk32)) {
  229                 if ((l->l_proc->p_flag & PK_32) == 0) {
  230                         // 32 bit tracer can't trace 64 bit process
  231                         return EINVAL;
  232                 }
  233                 s = sizeof(process_fpreg32);
  234                 r = (ptrace_regrfunc_t)process_read_fpregs32;
  235                 w = (ptrace_regwfunc_t)process_write_fpregs32;
  236         } else
  237 #endif
  238         {
  239                 s = sizeof(struct fpreg);
  240                 r = (ptrace_regrfunc_t)process_read_fpregs;
  241                 w = (ptrace_regwfunc_t)process_write_fpregs;
  242         }
  243         return proc_regio(l, uio, s, r, w);
  244 #else
  245         return EINVAL;
  246 #endif
  247 }
  248 
  249 
  250 int
  251 process_dodbregs(struct lwp *curl /*tracer*/,
  252     struct lwp *l /*traced*/,
  253     struct uio *uio)
  254 {
  255 #if defined(PT_GETDBREGS) || defined(PT_SETDBREGS)
  256         size_t s;
  257         ptrace_regrfunc_t r;
  258         ptrace_regwfunc_t w;
  259 
  260 #ifdef COMPAT_NETBSD32
  261         const bool pk32 = (curl->l_proc->p_flag & PK_32) != 0;
  262 
  263         if (__predict_false(pk32)) {
  264                 if ((l->l_proc->p_flag & PK_32) == 0) {
  265                         // 32 bit tracer can't trace 64 bit process
  266                         return EINVAL;
  267                 }
  268                 s = sizeof(process_dbreg32);
  269                 r = (ptrace_regrfunc_t)process_read_dbregs32;
  270                 w = (ptrace_regwfunc_t)process_write_dbregs32;
  271         } else
  272 #endif
  273         {
  274                 s = sizeof(struct dbreg);
  275                 r = (ptrace_regrfunc_t)process_read_dbregs;
  276                 w = (ptrace_regwfunc_t)process_write_dbregs;
  277         }
  278         return proc_regio(l, uio, s, r, w);
  279 #else
  280         return EINVAL;
  281 #endif
  282 }

Cache object: 3a2a883fefe1933a866c9165a95e7769


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