Module Name:    src
Committed By:   kamil
Date:           Tue May 22 04:32:56 UTC 2018

Modified Files:
        src/tests/kernel: h_segv.c t_trapsignal.sh

Log Message:
Extend ATF tests in t_trapsignal.sh to verify software breakpoint traps

There are at least four types of SIGTRAP events:
 - software/hardware single step (trace trap)
 - software breakpoint
 - hardware breakpoint/watchpoint
 - kernel event (exec, fork, vfork, vfork-done, lwp-create, lwp-exit)

A program can execute software breakpoint without the context of being
traced and this is a regular crash signal emitting SIGTRAP (TRAP_BRKPT).

Rename original trap_* tests (trap_simple, trap_handle, trap_mask,
trap_handle_recurse and trap_ignore) to segv_* tests and restrict them for
SIGSEGV.

Add new tests: trap_* testing the same scenarios as segv_ ones, however
verifying the software breakpoint trap (SIGTRAP).

Keep the original name of h_segv.c, and extend it for software breakpoint
events.

The purpose of these tests is to verify SIGTRAP kernel paths without the
ptrace(2) context.

All tests pass.

Sponsored by <The NetBSD Foundation>


To generate a diff of this commit:
cvs rdiff -u -r1.3 -r1.4 src/tests/kernel/h_segv.c
cvs rdiff -u -r1.2 -r1.3 src/tests/kernel/t_trapsignal.sh

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/tests/kernel/h_segv.c
diff -u src/tests/kernel/h_segv.c:1.3 src/tests/kernel/h_segv.c:1.4
--- src/tests/kernel/h_segv.c:1.3	Mon May 21 08:49:03 2018
+++ src/tests/kernel/h_segv.c	Tue May 22 04:32:56 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: h_segv.c,v 1.3 2018/05/21 08:49:03 kamil Exp $	*/
+/*	$NetBSD: h_segv.c,v 1.4 2018/05/22 04:32:56 kamil Exp $	*/
 
 /*-
  * Copyright (c) 2017 The NetBSD Foundation, Inc.
@@ -29,8 +29,10 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: h_segv.c,v 1.3 2018/05/21 08:49:03 kamil Exp $");
+__RCSID("$NetBSD: h_segv.c,v 1.4 2018/05/22 04:32:56 kamil Exp $");
 
+#include <sys/types.h>
+#include <sys/ptrace.h>
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
@@ -57,21 +59,41 @@ static struct {
 	{ "ignore",	F_IGNORE }
 };
 
+static int sig;
+static struct {
+	const char *n;
+	int v;
+} sn[] = {
+	{ "segv",	SIGSEGV },
+	{ "trap",	SIGTRAP }
+};
+
 static void
 foo(int s)
 {
         char buf[64];
         int i = snprintf(buf, sizeof(buf), "got %d\n", s);
         write(2, buf, i);
-	if (flags & F_RECURSE)
-		*p = 0;
+	if (flags & F_RECURSE) {
+		if (sig == SIGSEGV)
+			*p = 0;
+		else if (sig == SIGTRAP) {
+#ifdef PTRACE_BREAKPOINT_ASM
+			PTRACE_BREAKPOINT_ASM;
+#else
+			/* port me */
+#endif
+		}
+	}
         exit(EXIT_SUCCESS);
 }
 
 static __dead void
 usage(void)
 {
-	fprintf(stderr, "Usage: %s recurse|mask|handle ...\n", getprogname());
+	const char *pname = getprogname();
+
+	fprintf(stderr, "Usage: %s recurse|mask|handle|ignore ...\n", pname);
 	exit(EXIT_FAILURE);
 }
 
@@ -83,16 +105,21 @@ main(int argc, char *argv[])
 
 	for (int i = 1; i < argc; i++) {
 		size_t j;
-		for (j = 0; j < __arraycount(nv); j++)
+		for (j = 0; j < __arraycount(nv); j++) {
 			if (strcmp(nv[j].n, argv[i]) == 0) {
 				flags |= nv[j].v;
 				break;
 			}
+			if (strcmp(sn[j].n, argv[i]) == 0) {
+				sig = sn[j].v;
+				break;
+			}
+		}
 		if (j == __arraycount(nv))
 			usage();
 	}
 
-	if (flags == 0)
+	if (flags == 0 || sig == 0)
 		usage();
 
 	if (flags & F_HANDLE) {
@@ -101,7 +128,7 @@ main(int argc, char *argv[])
 		sa.sa_flags = SA_RESTART;
 		sa.sa_handler = foo;
 		sigemptyset(&sa.sa_mask);
-		if (sigaction(SIGSEGV, &sa, NULL) == -1)
+		if (sigaction(sig, &sa, NULL) == -1)
 			err(EXIT_FAILURE, "sigaction");
 	}
 
@@ -109,7 +136,7 @@ main(int argc, char *argv[])
 		sigset_t set;
 
 		sigemptyset(&set);
-		sigaddset(&set, SIGSEGV);
+		sigaddset(&set, sig);
 		if (sigprocmask(SIG_BLOCK, &set, NULL) == -1)
 			err(EXIT_FAILURE, "sigprocmask");
 	}
@@ -120,10 +147,18 @@ main(int argc, char *argv[])
 		memset(&sa, 0, sizeof(sa));
 		sa.sa_handler = SIG_IGN;
 		sigemptyset(&sa.sa_mask);
-		if (sigaction(SIGSEGV, &sa, NULL) == -1)
+		if (sigaction(sig, &sa, NULL) == -1)
 			err(EXIT_FAILURE, "sigaction");
 	}
 
-        *p = 1;
+	if (sig == SIGSEGV)
+	        *p = 1;
+	else if (sig == SIGTRAP) {
+#ifdef PTRACE_BREAKPOINT_ASM
+		PTRACE_BREAKPOINT_ASM;
+#else
+		/* port me */
+#endif
+	}
 	return EXIT_SUCCESS;
 }

Index: src/tests/kernel/t_trapsignal.sh
diff -u src/tests/kernel/t_trapsignal.sh:1.2 src/tests/kernel/t_trapsignal.sh:1.3
--- src/tests/kernel/t_trapsignal.sh:1.2	Mon May 21 08:49:03 2018
+++ src/tests/kernel/t_trapsignal.sh	Tue May 22 04:32:56 2018
@@ -1,4 +1,4 @@
-# $NetBSD: t_trapsignal.sh,v 1.2 2018/05/21 08:49:03 kamil Exp $
+# $NetBSD: t_trapsignal.sh,v 1.3 2018/05/22 04:32:56 kamil Exp $
 #
 # Copyright (c) 2017 The NetBSD Foundation, Inc.
 # All rights reserved.
@@ -29,60 +29,128 @@
 #
 
 HELPER=$(atf_get_srcdir)/h_segv
+atf_test_case segv_simple
+segv_simple()
+{
+	atf_set "descr" "Test unhandled SIGSEGV with the right exit code"
+}
+segv_simple_body()
+{
+	atf_check -s signal:11 -o "inline:" -e "inline:" \
+		${HELPER} segv recurse
+}
+
+atf_test_case segv_handle
+segv_handle()
+{
+	atf_set "descr" "Test handled SIGSEGV traps call the signal handler"
+}
+segv_handle_body()
+{
+	atf_check -s exit:0 -o "inline:" -e "inline:got 11\n" \
+		${HELPER} segv handle
+}
+
+atf_test_case segv_mask
+segv_mask()
+{
+	atf_set "descr" "Test that masking SIGSEGV get reset"
+}
+segv_mask_body()
+{
+	atf_check -s signal:11 -o "inline:" -e "inline:" \
+		${HELPER} segv mask
+}
+
+atf_test_case segv_handle_mask
+segv_handle_mask()
+{
+	atf_set "descr" "Test handled and masked SIGSEGV traps get reset"
+}
+segv_handle_mask_body()
+{
+	atf_check -s signal:11 -o "inline:" -e "inline:" \
+		${HELPER} segv mask handle
+}
+
+atf_test_case segv_handle_recurse
+segv_handle_recurse()
+{
+	atf_set "descr" "Test that receiving SIGSEGV in the handler resets"
+}
+
+segv_handle_recurse_body()
+{
+	atf_check -s signal:11 -o "inline:" -e "inline:got 11\n" \
+		${HELPER} segv handle recurse
+}
+
+atf_test_case segv_ignore
+segv_ignore()
+{
+	atf_set "descr" "Test ignored SIGSEGV trap with right exit code"
+}
+
+segv_ignore_body()
+{
+	atf_check -s signal:11 -o "inline:" -e "inline:" \
+		${HELPER} segv ignore
+}
+
 atf_test_case trap_simple
 trap_simple()
 {
-	atf_set "descr" "Test unhandled traps exit with the right exit code"
+	atf_set "descr" "Test unhandled SIGTRAP with the right exit code"
 }
 trap_simple_body()
 {
-	atf_check -s signal:11 -o "inline:" -e "inline:" \
-		${HELPER} recurse
+	atf_check -s signal:5 -o "inline:" -e "inline:" \
+		${HELPER} trap recurse
 }
 
 atf_test_case trap_handle
 trap_handle()
 {
-	atf_set "descr" "Test handled traps call the signal handler"
+	atf_set "descr" "Test handled SIGTRAP traps call the signal handler"
 }
 trap_handle_body()
 {
-	atf_check -s exit:0 -o "inline:" -e "inline:got 11\n" \
-		${HELPER} handle
+	atf_check -s exit:0 -o "inline:" -e "inline:got 5\n" \
+		${HELPER} trap handle
 }
 
 atf_test_case trap_mask
 trap_mask()
 {
-	atf_set "descr" "Test that masking the trapped signal get reset"
+	atf_set "descr" "Test that masking the trapped SIGTRAP signal get reset"
 }
 trap_mask_body()
 {
-	atf_check -s signal:11 -o "inline:" -e "inline:" \
-		${HELPER} mask
+	atf_check -s signal:5 -o "inline:" -e "inline:" \
+		${HELPER} trap mask
 }
 
 atf_test_case trap_handle_mask
 trap_handle_mask()
 {
-	atf_set "descr" "Test handled and masked traps get reset"
+	atf_set "descr" "Test handled and masked SIGTRAP traps get reset"
 }
 trap_handle_mask_body()
 {
-	atf_check -s signal:11 -o "inline:" -e "inline:" \
-		${HELPER} mask handle
+	atf_check -s signal:5 -o "inline:" -e "inline:" \
+		${HELPER} trap mask handle
 }
 
 atf_test_case trap_handle_recurse
 trap_handle_recurse()
 {
-	atf_set "descr" "Test that receiving the trap in the handler resets"
+	atf_set "descr" "Test that receiving SIGTRAP in the handler resets"
 }
 
 trap_handle_recurse_body()
 {
-	atf_check -s signal:11 -o "inline:" -e "inline:got 11\n" \
-		${HELPER} handle recurse
+	atf_check -s signal:5 -o "inline:" -e "inline:got 5\n" \
+		${HELPER} trap handle recurse
 }
 
 atf_test_case trap_ignore
@@ -93,12 +161,18 @@ trap_ignore()
 
 trap_ignore_body()
 {
-	atf_check -s signal:11 -o "inline:" -e "inline:" \
-		${HELPER} ignore
+	atf_check -s signal:5 -o "inline:" -e "inline:" \
+		${HELPER} trap ignore
 }
 
 atf_init_test_cases()
 {
+	atf_add_test_case segv_simple
+	atf_add_test_case segv_handle
+	atf_add_test_case segv_mask
+	atf_add_test_case segv_handle_recurse
+	atf_add_test_case segv_ignore
+
 	atf_add_test_case trap_simple
 	atf_add_test_case trap_handle
 	atf_add_test_case trap_mask

Reply via email to