Source-Changes-HG archive

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

[src/trunk]: src/tests/kernel Handle FPE and BUS scenarios in the ATF t_traps...



details:   https://anonhg.NetBSD.org/src/rev/c6e41f91f0e8
branches:  trunk
changeset: 362104:c6e41f91f0e8
user:      kamil <kamil%NetBSD.org@localhost>
date:      Sun May 27 17:04:45 2018 +0000

description:
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>

diffstat:

 tests/kernel/h_segv.c        |  149 +++++++++++++++++++++++++++++---------
 tests/kernel/t_trapsignal.sh |  165 ++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 278 insertions(+), 36 deletions(-)

diffs (truncated from 413 to 300 lines):

diff -r 64802ccfa0b2 -r c6e41f91f0e8 tests/kernel/h_segv.c
--- a/tests/kernel/h_segv.c     Sun May 27 14:03:56 2018 +0000
+++ b/tests/kernel/h_segv.c     Sun May 27 17:04:45 2018 +0000
@@ -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 @@
 #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 @@
        int v;
 } sn[] = {
        { "segv",       SIGSEGV },
-       { "trap",       SIGTRAP }
+       { "trap",       SIGTRAP },
+       { "ill",        SIGILL },
+       { "fpe",        SIGFPE },
+       { "bus",        SIGBUS }
 };
 
 static void
+trigger_segv(void)
+{
+       volatile int *p = (int *)(intptr_t)atoi("0");
+
+       *p = 1;
+}
+
+static void
+trigger_trap(void)
+{
+
+#ifdef PTRACE_BREAKPOINT_ASM
+       PTRACE_BREAKPOINT_ASM;
+#else
+       /* 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;
+       }
+}
+
+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) {
-               if (sig == SIGSEGV)
-                       *p = 0;
-               else if (sig == SIGTRAP) {
-#ifdef PTRACE_BREAKPOINT_ASM
-                       PTRACE_BREAKPOINT_ASM;
-#else
-                       /* port me */
-#endif
-               }
-       }
-        exit(EXIT_SUCCESS);
+       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 @@
 {
        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 @@
                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 @@
                        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;
 }
diff -r 64802ccfa0b2 -r c6e41f91f0e8 tests/kernel/t_trapsignal.sh
--- a/tests/kernel/t_trapsignal.sh      Sun May 27 14:03:56 2018 +0000
+++ b/tests/kernel/t_trapsignal.sh      Sun May 27 17:04:45 2018 +0000
@@ -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 @@
                ${HELPER} segv ignore
 }
 
+# SIGTRAP
+
 atf_test_case trap_simple
 trap_simple()
 {
@@ -165,6 +170,146 @@
                ${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()



Home | Main Index | Thread Index | Old Index