Source-Changes-HG archive

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

[src/trunk]: src Introduce new interface in ptrace(2) - PT_GET_SIGMASK and PT...



details:   https://anonhg.NetBSD.org/src/rev/cd7b2438843a
branches:  trunk
changeset: 821652:cd7b2438843a
user:      kamil <kamil%NetBSD.org@localhost>
date:      Sun Feb 12 06:09:52 2017 +0000

description:
Introduce new interface in ptrace(2) - PT_GET_SIGMASK and PT_SET_SIGMASK

Add new interface to add ability to get/set signal mask of a tracee.
It has been inspired by Linux PTRACE_GETSIGMASK and PTRACE_SETSIGMASK, but
adapted for NetBSD API.

This interface is used for checkpointing software to set/restore context
of a process including signal mask like criu or just to track this property
in reverse-execution software like Record and Replay Framework (rr).


Add new ATF tests for this interface
====================================
getsigmask1:
    Verify that plain PT_SET_SIGMASK can be called

getsigmask2:
    Verify that PT_SET_SIGMASK reports correct mask from tracee

setsigmask1:
    Verify that plain PT_SET_SIGMASK can be called with empty mask

setsigmask2:
    Verify that sigmask is preserved between PT_GET_SIGMASK and
    PT_SET_SIGMASK

setsigmask3:
    Verify that sigmask is preserved between PT_GET_SIGMASK, process
    resumed and PT_SET_SIGMASK

setsigmask4:
    Verify that new sigmask is visible in tracee


Kernel ABI bump delayed as there are more interfaces to come in ptrace(2).

Sponsored by <The NetBSD Foundation>

diffstat:

 lib/libc/sys/ptrace.2        |   29 +++-
 sys/kern/sys_ptrace_common.c |   37 ++++-
 sys/sys/ptrace.h             |    8 +-
 tests/kernel/t_ptrace_wait.c |  376 ++++++++++++++++++++++++++++++++++++++++++-
 4 files changed, 442 insertions(+), 8 deletions(-)

diffs (truncated from 549 to 300 lines):

diff -r 5e13403d767d -r cd7b2438843a lib/libc/sys/ptrace.2
--- a/lib/libc/sys/ptrace.2     Sun Feb 12 05:21:34 2017 +0000
+++ b/lib/libc/sys/ptrace.2     Sun Feb 12 06:09:52 2017 +0000
@@ -1,7 +1,7 @@
-.\"    $NetBSD: ptrace.2,v 1.58 2017/01/27 12:52:39 wiz Exp $
+.\"    $NetBSD: ptrace.2,v 1.59 2017/02/12 06:09:53 kamil Exp $
 .\"
 .\" This file is in the public domain.
-.Dd January 25, 2016
+.Dd February 12, 2016
 .Dt PTRACE 2
 .Os
 .Sh NAME
@@ -514,6 +514,31 @@
 .Fa data
 argument should be set to
 .Li sizeof(struct ptrace_siginfo) .
+.It Dv PT_SET_SIGMASK
+This request loads the traced process' signal mask from
+.Dq Li "sigset_t"
+(defined in
+.In sys/sigtypes.h )
+pointed to by
+.Fa addr .
+The
+.Fa data
+argument contains the LWP ID of the thread whose registers are to
+be written.
+If zero is supplied, the first thread of the process is written.
+.It Dv PT_GET_SIGMASK
+This request is the converse of
+.Dv PT_SET_SIGMASK ;
+it reads the traced process' signal mask into
+.Dq Li "sigset_t"
+(defined in
+.In sys/sigtypes.h )
+pointed to by
+.Fa addr .
+The
+.Fa data
+argument contains the LWP ID of the thread whose mask is to be read.
+If zero is supplied, the first thread of the process is read.
 .El
 .Pp
 Additionally, the following requests exist but are
diff -r 5e13403d767d -r cd7b2438843a sys/kern/sys_ptrace_common.c
--- a/sys/kern/sys_ptrace_common.c      Sun Feb 12 05:21:34 2017 +0000
+++ b/sys/kern/sys_ptrace_common.c      Sun Feb 12 06:09:52 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: sys_ptrace_common.c,v 1.13 2017/02/11 19:32:41 kamil Exp $     */
+/*     $NetBSD: sys_ptrace_common.c,v 1.14 2017/02/12 06:09:52 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.13 2017/02/11 19:32:41 kamil Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sys_ptrace_common.c,v 1.14 2017/02/12 06:09:52 kamil Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_ptrace.h"
@@ -212,6 +212,8 @@
        case PT_GET_PROCESS_STATE:
        case PT_SET_SIGINFO:
        case PT_GET_SIGINFO:
+       case PT_SET_SIGMASK:
+       case PT_GET_SIGMASK:
 #ifdef __HAVE_PTRACE_MACHDEP
        PTRACE_MACHDEP_REQUEST_CASES
 #endif
@@ -406,6 +408,8 @@
        case  PT_IO:
        case  PT_SET_SIGINFO:
        case  PT_GET_SIGINFO:
+       case  PT_SET_SIGMASK:
+       case  PT_GET_SIGMASK:
 #ifdef PT_GETREGS
        case  PT_GETREGS:
 #endif
@@ -1039,6 +1043,35 @@
 
                break;
 
+       case  PT_SET_SIGMASK:
+               write = 1;
+
+       case  PT_GET_SIGMASK:
+               /* write = 0 done above. */
+
+               tmp = data;
+               if (tmp != 0 && t->p_nlwps > 1) {
+                       lwp_delref(lt);
+                       mutex_enter(t->p_lock);
+                       lt = lwp_find(t, tmp);
+                       if (lt == NULL) {
+                               mutex_exit(t->p_lock);
+                               error = ESRCH;
+                               break;
+                       }
+                       lwp_addref(lt);
+                       mutex_exit(t->p_lock);
+               }
+
+               if (!process_validregs(lt))
+                       error = EINVAL;
+               else if (write == 1)
+                       error = copyin(addr, &lt->l_sigmask, sizeof(sigset_t));
+               else
+                       error = copyout(&lt->l_sigmask, addr, sizeof(sigset_t));
+                       
+               break;
+
 #ifdef PT_SETREGS
        case  PT_SETREGS:
                write = 1;
diff -r 5e13403d767d -r cd7b2438843a sys/sys/ptrace.h
--- a/sys/sys/ptrace.h  Sun Feb 12 05:21:34 2017 +0000
+++ b/sys/sys/ptrace.h  Sun Feb 12 06:09:52 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ptrace.h,v 1.55 2017/01/16 21:35:59 kamil Exp $        */
+/*     $NetBSD: ptrace.h,v 1.56 2017/02/12 06:09:52 kamil Exp $        */
 
 /*-
  * Copyright (c) 1984, 1993
@@ -55,6 +55,8 @@
 #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_SET_SIGMASK          21      /* set signal mask */
+#define        PT_GET_SIGMASK          22      /* get signal mask */
 
 #define        PT_FIRSTMACH            32      /* for machine-specific requests */
 #include <machine/ptrace.h>            /* machine-specific requests, if any */
@@ -80,7 +82,9 @@
 /* 17 */    "PT_GET_EVENT_MASK", \
 /* 18 */    "PT_GET_PROCESS_STATE", \
 /* 19 */    "PT_SET_SIGINFO", \
-/* 20 */    "PT_GET_SIGINFO",
+/* 20 */    "PT_GET_SIGINFO", \
+/* 20 */    "PT_GET_SIGMASK", \
+/* 20 */    "PT_GET_SIGMASK",
 
 /* PT_{G,S}EVENT_MASK */
 typedef struct ptrace_event {
diff -r 5e13403d767d -r cd7b2438843a tests/kernel/t_ptrace_wait.c
--- a/tests/kernel/t_ptrace_wait.c      Sun Feb 12 05:21:34 2017 +0000
+++ b/tests/kernel/t_ptrace_wait.c      Sun Feb 12 06:09:52 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: t_ptrace_wait.c,v 1.69 2017/01/27 16:43:07 kamil Exp $ */
+/*     $NetBSD: t_ptrace_wait.c,v 1.70 2017/02/12 06:09:52 kamil Exp $ */
 
 /*-
  * Copyright (c) 2016 The NetBSD Foundation, Inc.
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: t_ptrace_wait.c,v 1.69 2017/01/27 16:43:07 kamil Exp $");
+__RCSID("$NetBSD: t_ptrace_wait.c,v 1.70 2017/02/12 06:09:52 kamil Exp $");
 
 #include <sys/param.h>
 #include <sys/types.h>
@@ -6583,6 +6583,370 @@
        TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
 }
 
+ATF_TC(getsigmask1);
+ATF_TC_HEAD(getsigmask1, tc)
+{
+       atf_tc_set_md_var(tc, "descr",
+           "Verify that plain PT_SET_SIGMASK can be called");
+}
+
+ATF_TC_BODY(getsigmask1, tc)
+{
+       const int exitval = 5;
+       const int sigval = SIGSTOP;
+       pid_t child, wpid;
+#if defined(TWAIT_HAVE_STATUS)
+       int status;
+#endif
+       sigset_t mask;
+
+       printf("Before forking process PID=%d\n", getpid());
+       ATF_REQUIRE((child = fork()) != -1);
+       if (child == 0) {
+               printf("Before calling PT_TRACE_ME from child %d\n", getpid());
+               FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
+
+               printf("Before raising %s from child\n", strsignal(sigval));
+               FORKEE_ASSERT(raise(sigval) == 0);
+
+               printf("Before exiting of the child process\n");
+               _exit(exitval);
+       }
+       printf("Parent process PID=%d, child's PID=%d\n", getpid(), child);
+
+       printf("Before calling %s() for the child\n", TWAIT_FNAME);
+       TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
+
+       validate_status_stopped(status, sigval);
+
+       printf("Before calling PT_GET_SIGMASK\n");
+       ATF_REQUIRE(ptrace(PT_GET_SIGMASK, child, &mask, 0) != -1);
+
+       printf("Before resuming the child process where it left off and "
+           "without signal to be sent\n");
+       ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
+
+       printf("Before calling %s() for the child\n", TWAIT_FNAME);
+       TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
+
+       validate_status_exited(status, exitval);
+
+       printf("Before calling %s() for the child\n", TWAIT_FNAME);
+       TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
+}
+
+ATF_TC(getsigmask2);
+ATF_TC_HEAD(getsigmask2, tc)
+{
+       atf_tc_set_md_var(tc, "descr",
+           "Verify that PT_SET_SIGMASK reports correct mask from tracee");
+}
+
+ATF_TC_BODY(getsigmask2, tc)
+{
+       const int exitval = 5;
+       const int sigval = SIGSTOP;
+       const int sigmasked = SIGTRAP;
+       pid_t child, wpid;
+#if defined(TWAIT_HAVE_STATUS)
+       int status;
+#endif
+       sigset_t mask;
+       sigset_t expected_mask;
+       ATF_REQUIRE(sigemptyset(&mask) == 0);
+       ATF_REQUIRE(sigemptyset(&expected_mask) == 0);
+       ATF_REQUIRE(sigaddset(&expected_mask, sigmasked) == 0);
+
+       printf("Before forking process PID=%d\n", getpid());
+       ATF_REQUIRE((child = fork()) != -1);
+       if (child == 0) {
+               printf("Before calling PT_TRACE_ME from child %d\n", getpid());
+               FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
+
+               sigaddset(&mask, sigmasked);
+               sigprocmask(SIG_BLOCK, &mask, NULL);
+
+               printf("Before raising %s from child\n", strsignal(sigval));
+               FORKEE_ASSERT(raise(sigval) == 0);
+
+               printf("Before exiting of the child process\n");
+               _exit(exitval);
+       }
+       printf("Parent process PID=%d, child's PID=%d\n", getpid(), child);
+
+       printf("Before calling %s() for the child\n", TWAIT_FNAME);
+       TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
+
+       validate_status_stopped(status, sigval);
+
+       printf("Before calling PT_GET_SIGMASK\n");
+       ATF_REQUIRE(ptrace(PT_GET_SIGMASK, child, &mask, 0) != -1);
+
+       ATF_REQUIRE(memcmp(&mask, &expected_mask, sizeof(sigset_t)) == 0);
+
+       printf("Before resuming the child process where it left off and "
+           "without signal to be sent\n");
+       ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
+
+       printf("Before calling %s() for the child\n", TWAIT_FNAME);
+       TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
+
+       validate_status_exited(status, exitval);
+
+       printf("Before calling %s() for the child\n", TWAIT_FNAME);
+       TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
+}
+
+ATF_TC(setsigmask1);
+ATF_TC_HEAD(setsigmask1, tc)
+{
+       atf_tc_set_md_var(tc, "descr",
+           "Verify that plain PT_SET_SIGMASK can be called with empty mask");
+}
+
+ATF_TC_BODY(setsigmask1, tc)
+{
+       const int exitval = 5;
+       const int sigval = SIGSTOP;
+       pid_t child, wpid;
+#if defined(TWAIT_HAVE_STATUS)
+       int status;
+#endif
+       sigset_t mask;
+       ATF_REQUIRE(sigemptyset(&mask) == 0);
+



Home | Main Index | Thread Index | Old Index