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/ce5e7534f9a8
branches: trunk
changeset: 351401:ce5e7534f9a8
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 d68958c05bbe -r ce5e7534f9a8 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 d68958c05bbe -r ce5e7534f9a8 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, <->l_sigmask, sizeof(sigset_t));
+ else
+ error = copyout(<->l_sigmask, addr, sizeof(sigset_t));
+
+ break;
+
#ifdef PT_SETREGS
case PT_SETREGS:
write = 1;
diff -r d68958c05bbe -r ce5e7534f9a8 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 d68958c05bbe -r ce5e7534f9a8 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