Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys Introduce new ptrace(2) interface: PT_SET_SIGINFO and PT...



details:   https://anonhg.NetBSD.org/src/rev/ce477df5c14b
branches:  trunk
changeset: 820309:ce477df5c14b
user:      kamil <kamil%NetBSD.org@localhost>
date:      Fri Jan 06 22:53:17 2017 +0000

description:
Introduce new ptrace(2) interface: PT_SET_SIGINFO and PT_GET_SIGINFO

This interface is designed to read signal information emited to tracee and
fake this signal with new value.

This functionality is required to distinguish types of events that occured
in the tracee and intercepted by a debugger.

These accessors introduce a new structure type ptrace_siginfo:
/*
 * Signal Information structure
 */
typedef struct ptrace_siginfo {
       siginfo_t       psi_siginfo;    /* signal information structure */
       lwpid_t         psi_lwpid;      /* destination LWP of the signal
                                        * value 0 means the whole process
                                        * (route signal to all LWPs) */
} ptrace_siginfo_t;

Include <sys/siginfo.h> in <sys/ptrace.h> in order to not break existing
software due to unknown symbol siginfo_t.

This interface has been proposed to the tech-kern@ mailing list.

Sponsored by <The NetBSD Foundation>

diffstat:

 sys/kern/core_elf32.c        |   8 ++--
 sys/kern/core_netbsd.c       |   8 ++--
 sys/kern/kern_sig.c          |  26 +++++++++----
 sys/kern/sys_ptrace_common.c |  81 ++++++++++++++++++++++++++++++++++++++++++-
 sys/sys/ptrace.h             |  20 +++++++++-
 sys/sys/signalvar.h          |  13 +++---
 6 files changed, 128 insertions(+), 28 deletions(-)

diffs (truncated from 353 to 300 lines):

diff -r d57f1cf89aa1 -r ce477df5c14b sys/kern/core_elf32.c
--- a/sys/kern/core_elf32.c     Fri Jan 06 22:42:58 2017 +0000
+++ b/sys/kern/core_elf32.c     Fri Jan 06 22:53:17 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: core_elf32.c,v 1.49 2016/09/29 20:40:53 christos Exp $ */
+/*     $NetBSD: core_elf32.c,v 1.50 2017/01/06 22:53:17 kamil Exp $    */
 
 /*
  * Copyright (c) 2001 Wasabi Systems, Inc.
@@ -40,7 +40,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(1, "$NetBSD: core_elf32.c,v 1.49 2016/09/29 20:40:53 christos Exp $");
+__KERNEL_RCSID(1, "$NetBSD: core_elf32.c,v 1.50 2017/01/06 22:53:17 kamil Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_coredump.h"
@@ -357,8 +357,8 @@
        /* First, write an elfcore_procinfo. */
        cpi.cpi_version = NETBSD_ELFCORE_PROCINFO_VERSION;
        cpi.cpi_cpisize = sizeof(cpi);
-       cpi.cpi_signo = p->p_sigctx.ps_signo;
-       cpi.cpi_sigcode = p->p_sigctx.ps_code;
+       cpi.cpi_signo = p->p_sigctx.ps_info._signo;
+       cpi.cpi_sigcode = p->p_sigctx.ps_info._code;
        cpi.cpi_siglwp = p->p_sigctx.ps_lwp;
 
        /*
diff -r d57f1cf89aa1 -r ce477df5c14b sys/kern/core_netbsd.c
--- a/sys/kern/core_netbsd.c    Fri Jan 06 22:42:58 2017 +0000
+++ b/sys/kern/core_netbsd.c    Fri Jan 06 22:53:17 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: core_netbsd.c,v 1.22 2014/01/07 07:59:03 dsl Exp $     */
+/*     $NetBSD: core_netbsd.c,v 1.23 2017/01/06 22:53:17 kamil Exp $   */
 
 /*
  * Copyright (c) 1997 Charles D. Cranor and Washington University.
@@ -45,7 +45,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: core_netbsd.c,v 1.22 2014/01/07 07:59:03 dsl Exp $");
+__KERNEL_RCSID(0, "$NetBSD: core_netbsd.c,v 1.23 2017/01/06 22:53:17 kamil Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_coredump.h"
@@ -88,8 +88,8 @@
        cs.core.c_midmag = 0;
        strncpy(cs.core.c_name, p->p_comm, MAXCOMLEN);
        cs.core.c_nseg = 0;
-       cs.core.c_signo = p->p_sigctx.ps_signo;
-       cs.core.c_ucode = p->p_sigctx.ps_code;
+       cs.core.c_signo = p->p_sigctx.ps_info._signo;
+       cs.core.c_ucode = p->p_sigctx.ps_info._code;
        cs.core.c_cpusize = 0;
        cs.core.c_tsize = (u_long)ctob(vm->vm_tsize);
        cs.core.c_dsize = (u_long)ctob(vm->vm_dsize);
diff -r d57f1cf89aa1 -r ce477df5c14b sys/kern/kern_sig.c
--- a/sys/kern/kern_sig.c       Fri Jan 06 22:42:58 2017 +0000
+++ b/sys/kern/kern_sig.c       Fri Jan 06 22:53:17 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: kern_sig.c,v 1.331 2016/12/04 16:40:43 christos Exp $  */
+/*     $NetBSD: kern_sig.c,v 1.332 2017/01/06 22:53:17 kamil Exp $     */
 
 /*-
  * Copyright (c) 2006, 2007, 2008 The NetBSD Foundation, Inc.
@@ -70,7 +70,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_sig.c,v 1.331 2016/12/04 16:40:43 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_sig.c,v 1.332 2017/01/06 22:53:17 kamil Exp $");
 
 #include "opt_ptrace.h"
 #include "opt_dtrace.h"
@@ -1240,8 +1240,7 @@
 
        /* XXX for core dump/debugger */
        p->p_sigctx.ps_lwp = ksi->ksi_lid;
-       p->p_sigctx.ps_signo = ksi->ksi_signo;
-       p->p_sigctx.ps_code = ksi->ksi_trap;
+       p->p_sigctx.ps_info = ksi->ksi_info;
 
        /*
         * Notify any interested parties of the signal.
@@ -1860,8 +1859,16 @@
        l->l_ru.ru_nsignals++;
        if (l->l_sigpendset == NULL) {
                /* From the debugger */
-               if (!siggetinfo(&l->l_sigpend, &ksi, signo))
-                       (void)siggetinfo(&p->p_sigpend, &ksi, signo);
+               if (p->p_sigctx.ps_faked &&
+                   signo == p->p_sigctx.ps_info._signo) {
+                       KSI_INIT(&ksi);
+                       ksi.ksi_info = p->p_sigctx.ps_info;
+                       ksi.ksi_lid = p->p_sigctx.ps_lwp;
+                       p->p_sigctx.ps_faked = false;
+               } else {
+                       if (!siggetinfo(&l->l_sigpend, &ksi, signo))
+                               (void)siggetinfo(&p->p_sigpend, &ksi, signo);
+               }
        } else
                sigget(l->l_sigpendset, &ksi, signo, NULL);
 
@@ -1947,8 +1954,7 @@
        KASSERT(mutex_owned(p->p_lock));
 
        p->p_sigctx.ps_lwp = 0;
-       p->p_sigctx.ps_code = 0;
-       p->p_sigctx.ps_signo = 0;
+       memset(&p->p_sigctx.ps_info, 0, sizeof(p->p_sigctx.ps_info));
 
        mutex_enter(&ps->sa_mutex);
        sigplusset(&SIGACTION_PS(ps, signo).sa_mask, &l->l_sigmask);
@@ -2053,7 +2059,9 @@
 
        exitsig = signo;
        p->p_acflag |= AXSIG;
-       p->p_sigctx.ps_signo = signo;
+       memset(&p->p_sigctx.ps_info, 0, sizeof(p->p_sigctx.ps_info));
+       p->p_sigctx.ps_info._signo = signo;
+       p->p_sigctx.ps_info._code = SI_NOINFO;
 
        if (docore) {
                mutex_exit(p->p_lock);
diff -r d57f1cf89aa1 -r ce477df5c14b sys/kern/sys_ptrace_common.c
--- a/sys/kern/sys_ptrace_common.c      Fri Jan 06 22:42:58 2017 +0000
+++ b/sys/kern/sys_ptrace_common.c      Fri Jan 06 22:53:17 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: sys_ptrace_common.c,v 1.7 2016/12/15 12:04:18 kamil Exp $      */
+/*     $NetBSD: sys_ptrace_common.c,v 1.8 2017/01/06 22:53:17 kamil Exp $      */
 
 /*-
  * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
@@ -118,7 +118,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sys_ptrace_common.c,v 1.7 2016/12/15 12:04:18 kamil Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sys_ptrace_common.c,v 1.8 2017/01/06 22:53:17 kamil Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_ptrace.h"
@@ -210,6 +210,8 @@
        case PT_SET_EVENT_MASK:
        case PT_GET_EVENT_MASK:
        case PT_GET_PROCESS_STATE:
+       case PT_SET_SIGINFO:
+       case PT_GET_SIGINFO:
 #ifdef __HAVE_PTRACE_MACHDEP
        PTRACE_MACHDEP_REQUEST_CASES
 #endif
@@ -300,6 +302,7 @@
        struct ptrace_event pe;
        struct ptrace_state ps;
        struct ptrace_lwpinfo pl;
+       struct ptrace_siginfo psi;
 #ifdef __HAVE_PTRACE_WATCHPOINTS
        struct ptrace_watchpoint pw;
 #endif
@@ -448,6 +451,8 @@
        case  PT_SET_EVENT_MASK:
        case  PT_GET_EVENT_MASK:
        case  PT_GET_PROCESS_STATE:
+       case  PT_SET_SIGINFO:
+       case  PT_GET_SIGINFO:
                /*
                 * You can't do what you want to the process if:
                 *      (1) It's not being traced at all,
@@ -797,6 +802,16 @@
                                proc_unstop(t);
                        else
                                lwp_unstop(lt);
+               } else if (t->p_sigctx.ps_faked) {
+                       if (signo != t->p_sigctx.ps_info._signo) {
+                               error = EINVAL;
+                               break;
+                       }
+                       t->p_sigctx.ps_faked = false;
+                       KSI_INIT_EMPTY(&ksi);
+                       ksi.ksi_info = t->p_sigctx.ps_info;
+                       ksi.ksi_lid = t->p_sigctx.ps_lwp;
+                       kpsignal2(t, &ksi);
                } else if (signo != 0) {
                        KSI_INIT_EMPTY(&ksi);
                        ksi.ksi_signo = signo;
@@ -911,7 +926,8 @@
                         * check ps_signo too.
                         */
                        if (lt->l_lid == t->p_sigctx.ps_lwp
-                           || (t->p_sigctx.ps_lwp == 0 && t->p_sigctx.ps_signo))
+                           || (t->p_sigctx.ps_lwp == 0 &&
+                               t->p_sigctx.ps_info._signo))
                                pl.pl_event = PL_EVENT_SIGNAL;
                }
                mutex_exit(t->p_lock);
@@ -919,6 +935,65 @@
                error = copyout(&pl, addr, sizeof(pl));
                break;
 
+       case  PT_SET_SIGINFO:
+               if (data != sizeof(psi)) {
+                       DPRINTF(("ptrace(%d): %d != %zu\n", req, data,
+                           sizeof(psi)));
+                       error = EINVAL;
+                       break;
+               }
+
+               error = copyin(addr, &psi, sizeof(psi));
+               if (error)
+                       break;
+
+               /* Check that the data is a valid signal number or zero. */
+               if (psi.psi_siginfo.si_signo < 0 ||
+                   psi.psi_siginfo.si_signo >= NSIG) {
+                       error = EINVAL;
+                       break;
+               }
+
+               tmp = psi.psi_lwpid;
+               if (tmp != 0)
+                       lwp_delref(lt);
+
+               mutex_enter(t->p_lock);
+
+               if (tmp != 0) {
+                       lt = lwp_find(t, tmp);
+                       if (lt == NULL) {
+                               mutex_exit(t->p_lock);
+                               error = ESRCH;
+                               break;
+                       }
+                       lwp_addref(lt);
+               }
+
+               t->p_sigctx.ps_faked = true;
+               t->p_sigctx.ps_info = psi.psi_siginfo._info;
+               t->p_sigctx.ps_lwp = psi.psi_lwpid;
+               mutex_exit(t->p_lock);
+               break;
+
+       case  PT_GET_SIGINFO:
+               if (data != sizeof(psi)) {
+                       DPRINTF(("ptrace(%d): %d != %zu\n", req, data,
+                           sizeof(psi)));
+                       error = EINVAL;
+                       break;
+               }
+               mutex_enter(t->p_lock);
+               psi.psi_siginfo._info = t->p_sigctx.ps_info;
+               psi.psi_lwpid = t->p_sigctx.ps_lwp;
+               mutex_exit(t->p_lock);
+
+               error = copyout(&psi, addr, sizeof(psi));
+               if (error)
+                       break;
+
+               break;
+
 #ifdef PT_SETREGS
        case  PT_SETREGS:
                write = 1;
diff -r d57f1cf89aa1 -r ce477df5c14b sys/sys/ptrace.h
--- a/sys/sys/ptrace.h  Fri Jan 06 22:42:58 2017 +0000
+++ b/sys/sys/ptrace.h  Fri Jan 06 22:53:17 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ptrace.h,v 1.51 2016/12/15 20:04:36 martin Exp $       */
+/*     $NetBSD: ptrace.h,v 1.52 2017/01/06 22:53:17 kamil Exp $        */
 
 /*-
  * Copyright (c) 1984, 1993
@@ -34,6 +34,8 @@
 #ifndef        _SYS_PTRACE_H_
 #define        _SYS_PTRACE_H_
 
+#include <sys/siginfo.h>
+
 #define        PT_TRACE_ME             0       /* child declares it's being traced */
 #define        PT_READ_I               1       /* read word in child's I space */
 #define        PT_READ_D               2       /* read word in child's D space */
@@ -51,6 +53,8 @@
 #define        PT_SET_EVENT_MASK       16      /* set the event mask, defined below */
 #define        PT_GET_EVENT_MASK       17      /* get the event mask, defined below */
 #define        PT_GET_PROCESS_STATE    18      /* get process state, defined below */
+#define        PT_SET_SIGINFO          19      /* set signal state, defined below */
+#define        PT_GET_SIGINFO          20      /* get signal state, defined below */
 
 #define        PT_FIRSTMACH            32      /* for machine-specific requests */
 #include <machine/ptrace.h>            /* machine-specific requests, if any */
@@ -74,7 +78,9 @@
 /* 15 */    "PT_SYSCALLEMU", \
 /* 16 */    "PT_SET_EVENT_MASK", \
 /* 17 */    "PT_GET_EVENT_MASK", \
-/* 18 */    "PT_GET_PROCESS_STATE",
+/* 18 */    "PT_GET_PROCESS_STATE", \
+/* 19 */    "PT_SET_SIGINFO", \
+/* 20 */    "PT_GET_SIGINFO",
 
 /* PT_{G,S}EVENT_MASK */



Home | Main Index | Thread Index | Old Index