Module Name:    src
Committed By:   kamil
Date:           Sun May 27 17:04:45 UTC 2018

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

Log Message:
Handle FPE and BUS scenarios in the ATF t_trapsignal tests

These crash signals are crucial for proper handling of abnormal conditions
in a program. The additional purpose of these tests it to assure the proper
handling of these signals for the coming ptrace(2)-related changes in the
signal routing code.

Add a stub for ILL scenarios.

All tests pass (on amd64).

The shell ATF script contains duplicated code. There should be a way to
deduplicate it, without rewrite to C.

Sponsored by <The NetBSD Foundation>


To generate a diff of this commit:
cvs rdiff -u -r1.4 -r1.5 src/tests/kernel/h_segv.c
cvs rdiff -u -r1.3 -r1.4 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.4 src/tests/kernel/h_segv.c:1.5
--- src/tests/kernel/h_segv.c:1.4	Tue May 22 04:32:56 2018
+++ src/tests/kernel/h_segv.c	Sun May 27 17:04:45 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: h_segv.c,v 1.4 2018/05/22 04:32:56 kamil Exp $	*/
+/*	$NetBSD: h_segv.c,v 1.5 2018/05/27 17:04:45 kamil Exp $	*/
 
 /*-
  * Copyright (c) 2017 The NetBSD Foundation, Inc.
@@ -29,9 +29,10 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: h_segv.c,v 1.4 2018/05/22 04:32:56 kamil Exp $");
+__RCSID("$NetBSD: h_segv.c,v 1.5 2018/05/27 17:04:45 kamil Exp $");
 
 #include <sys/types.h>
+#include <sys/mman.h>
 #include <sys/ptrace.h>
 #include <stdio.h>
 #include <string.h>
@@ -40,9 +41,6 @@ __RCSID("$NetBSD: h_segv.c,v 1.4 2018/05
 #include <signal.h>
 #include <err.h>
 
-// A faulting address
-static int *p = (int *) 0xfefefef0;
-
 static int flags;
 #define F_RECURSE 	1
 #define F_HANDLE	2
@@ -65,27 +63,107 @@ static struct {
 	int v;
 } sn[] = {
 	{ "segv",	SIGSEGV },
-	{ "trap",	SIGTRAP }
+	{ "trap",	SIGTRAP },
+	{ "ill",	SIGILL },
+	{ "fpe",	SIGFPE },
+	{ "bus",	SIGBUS }
 };
 
 static void
-foo(int s)
+trigger_segv(void)
+{
+	volatile int *p = (int *)(intptr_t)atoi("0");
+
+	*p = 1;
+}
+
+static void
+trigger_trap(void)
 {
-        char buf[64];
-        int i = snprintf(buf, sizeof(buf), "got %d\n", s);
-        write(2, buf, i);
-	if (flags & F_RECURSE) {
-		if (sig == SIGSEGV)
-			*p = 0;
-		else if (sig == SIGTRAP) {
+
 #ifdef PTRACE_BREAKPOINT_ASM
-			PTRACE_BREAKPOINT_ASM;
+	PTRACE_BREAKPOINT_ASM;
 #else
-			/* port me */
-#endif
-		}
+	/* port me */
+#endif	
+}
+
+static void
+trigger_ill(void)
+{
+
+#ifdef PTRACE_ILLEGAL_ASM
+	PTRACE_ILLEGAL_ASM;
+#else
+	/* port me */
+#endif	
+}
+
+static void
+trigger_fpe(void)
+{
+	volatile int a = getpid();
+	volatile int b = strtol("0", NULL, 0);
+
+	usleep(a/b);
+}
+
+static void
+trigger_bus(void)
+{
+	FILE *fp;
+	char *p;
+
+	/* Open an empty file for writing. */
+	fp = tmpfile();
+	if (fp == NULL)
+		err(EXIT_FAILURE, "tmpfile");
+
+	/* Map an empty file with mmap(2) to a pointer. */
+	p = mmap(0, 1, PROT_WRITE, MAP_PRIVATE, fileno(fp), 0);
+	if (p == MAP_FAILED)
+		err(EXIT_FAILURE, "mmap");
+
+	/* Invalid memory access causes CPU trap, translated to SIGBUS */
+	*p = 'a';
+}
+
+static void
+trigger(void)
+{
+
+	switch (sig) {
+	case SIGSEGV:
+		trigger_segv();
+		break;
+	case SIGTRAP:
+		trigger_trap();
+		break;
+	case SIGILL:
+		trigger_ill();
+		break;
+	case SIGFPE:
+		trigger_fpe();
+		break;
+	case SIGBUS:
+		trigger_bus();
+		break;
+	default:
+		break;
 	}
-        exit(EXIT_SUCCESS);
+}
+
+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)
+		trigger();
+
+	exit(EXIT_SUCCESS);
 }
 
 static __dead void
@@ -93,13 +171,16 @@ usage(void)
 {
 	const char *pname = getprogname();
 
-	fprintf(stderr, "Usage: %s recurse|mask|handle|ignore ...\n", pname);
+	fprintf(stderr, "Usage: %s segv|trap|ill|fpe|bus "
+	                "[recurse|mask|handle|ignore] ...\n", pname);
+
 	exit(EXIT_FAILURE);
 }
 
 int
 main(int argc, char *argv[])
 {
+
 	if (argc == 1)
 	    usage();
 
@@ -108,15 +189,20 @@ main(int argc, char *argv[])
 		for (j = 0; j < __arraycount(nv); j++) {
 			if (strcmp(nv[j].n, argv[i]) == 0) {
 				flags |= nv[j].v;
-				break;
+				goto consumed;
 			}
+		}
+		for (j = 0; j < __arraycount(sn); j++) {
 			if (strcmp(sn[j].n, argv[i]) == 0) {
 				sig = sn[j].v;
-				break;
+				goto consumed;
 			}
 		}
-		if (j == __arraycount(nv))
-			usage();
+
+		usage();
+
+	consumed:
+		continue;
 	}
 
 	if (flags == 0 || sig == 0)
@@ -151,14 +237,7 @@ main(int argc, char *argv[])
 			err(EXIT_FAILURE, "sigaction");
 	}
 
-	if (sig == SIGSEGV)
-	        *p = 1;
-	else if (sig == SIGTRAP) {
-#ifdef PTRACE_BREAKPOINT_ASM
-		PTRACE_BREAKPOINT_ASM;
-#else
-		/* port me */
-#endif
-	}
+	trigger();
+
 	return EXIT_SUCCESS;
 }

Index: src/tests/kernel/t_trapsignal.sh
diff -u src/tests/kernel/t_trapsignal.sh:1.3 src/tests/kernel/t_trapsignal.sh:1.4
--- src/tests/kernel/t_trapsignal.sh:1.3	Tue May 22 04:32:56 2018
+++ src/tests/kernel/t_trapsignal.sh	Sun May 27 17:04:45 2018
@@ -1,4 +1,4 @@
-# $NetBSD: t_trapsignal.sh,v 1.3 2018/05/22 04:32:56 kamil Exp $
+# $NetBSD: t_trapsignal.sh,v 1.4 2018/05/27 17:04:45 kamil Exp $
 #
 # Copyright (c) 2017 The NetBSD Foundation, Inc.
 # All rights reserved.
@@ -29,6 +29,9 @@
 #
 
 HELPER=$(atf_get_srcdir)/h_segv
+
+# SIGSEGV
+
 atf_test_case segv_simple
 segv_simple()
 {
@@ -97,6 +100,8 @@ segv_ignore_body()
 		${HELPER} segv ignore
 }
 
+# SIGTRAP
+
 atf_test_case trap_simple
 trap_simple()
 {
@@ -165,6 +170,146 @@ trap_ignore_body()
 		${HELPER} trap ignore
 }
 
+# SIGFPE
+
+atf_test_case fpe_simple
+fpe_simple()
+{
+	atf_set "descr" "Test unhandled SIGFPE with the right exit code"
+}
+fpe_simple_body()
+{
+	atf_check -s signal:8 -o "inline:" -e "inline:" \
+		${HELPER} fpe recurse
+}
+
+atf_test_case fpe_handle
+fpe_handle()
+{
+	atf_set "descr" "Test handled SIGFPE traps call the signal handler"
+}
+fpe_handle_body()
+{
+	atf_check -s exit:0 -o "inline:" -e "inline:got 8\n" \
+		${HELPER} fpe handle
+}
+
+atf_test_case fpe_mask
+fpe_mask()
+{
+	atf_set "descr" "Test that masking the trapped SIGFPE signal get reset"
+}
+fpe_mask_body()
+{
+	atf_check -s signal:8 -o "inline:" -e "inline:" \
+		${HELPER} fpe mask
+}
+
+atf_test_case fpe_handle_mask
+fpe_handle_mask()
+{
+	atf_set "descr" "Test handled and masked SIGFPE traps get reset"
+}
+fpe_handle_mask_body()
+{
+	atf_check -s signal:8 -o "inline:" -e "inline:" \
+		${HELPER} fpe mask handle
+}
+
+atf_test_case fpe_handle_recurse
+fpe_handle_recurse()
+{
+	atf_set "descr" "Test that receiving SIGFPE in the handler resets"
+}
+
+fpe_handle_recurse_body()
+{
+	atf_check -s signal:8 -o "inline:" -e "inline:got 8\n" \
+		${HELPER} fpe handle recurse
+}
+
+atf_test_case fpe_ignore
+fpe_ignore()
+{
+	atf_set "descr" "Test ignored trap with right exit code"
+}
+
+fpe_ignore_body()
+{
+	atf_check -s signal:8 -o "inline:" -e "inline:" \
+		${HELPER} fpe ignore
+}
+
+# SIGBUS
+
+atf_test_case bus_simple
+bus_simple()
+{
+	atf_set "descr" "Test unhandled SIGBUS with the right exit code"
+}
+bus_simple_body()
+{
+	atf_check -s signal:10 -o "inline:" -e "inline:" \
+		${HELPER} bus recurse
+}
+
+atf_test_case bus_handle
+bus_handle()
+{
+	atf_set "descr" "Test handled SIGBUS traps call the signal handler"
+}
+bus_handle_body()
+{
+	atf_check -s exit:0 -o "inline:" -e "inline:got 10\n" \
+		${HELPER} bus handle
+}
+
+atf_test_case bus_mask
+bus_mask()
+{
+	atf_set "descr" "Test that masking the trapped SIGBUS signal get reset"
+}
+bus_mask_body()
+{
+	atf_check -s signal:10 -o "inline:" -e "inline:" \
+		${HELPER} bus mask
+}
+
+atf_test_case bus_handle_mask
+bus_handle_mask()
+{
+	atf_set "descr" "Test handled and masked SIGBUS traps get reset"
+}
+bus_handle_mask_body()
+{
+	atf_check -s signal:10 -o "inline:" -e "inline:" \
+		${HELPER} bus mask handle
+}
+
+atf_test_case bus_handle_recurse
+bus_handle_recurse()
+{
+	atf_set "descr" "Test that receiving SIGBUS in the handler resets"
+}
+
+bus_handle_recurse_body()
+{
+	atf_check -s signal:10 -o "inline:" -e "inline:got 10\n" \
+		${HELPER} bus handle recurse
+}
+
+atf_test_case bus_ignore
+bus_ignore()
+{
+	atf_set "descr" "Test ignored trap with right exit code"
+}
+
+bus_ignore_body()
+{
+	atf_check -s signal:10 -o "inline:" -e "inline:" \
+		${HELPER} bus ignore
+}
+
 atf_init_test_cases()
 {
 	atf_add_test_case segv_simple
@@ -178,4 +323,22 @@ atf_init_test_cases()
 	atf_add_test_case trap_mask
 	atf_add_test_case trap_handle_recurse
 	atf_add_test_case trap_ignore
+
+#	atf_add_test_case ill_simple
+#	atf_add_test_case ill_handle
+#	atf_add_test_case ill_mask
+#	atf_add_test_case ill_handle_recurse
+#	atf_add_test_case ill_ignore
+
+	atf_add_test_case fpe_simple
+	atf_add_test_case fpe_handle
+	atf_add_test_case fpe_mask
+	atf_add_test_case fpe_handle_recurse
+	atf_add_test_case fpe_ignore
+
+	atf_add_test_case bus_simple
+	atf_add_test_case bus_handle
+	atf_add_test_case bus_mask
+	atf_add_test_case bus_handle_recurse
+	atf_add_test_case bus_ignore
 }

Reply via email to