Source-Changes-HG archive

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

[src/trunk]: src/tests/kernel Extend ATF tests in t_trapsignal.sh to verify s...



details:   https://anonhg.NetBSD.org/src/rev/8664a51e4f82
branches:  trunk
changeset: 322881:8664a51e4f82
user:      kamil <kamil%NetBSD.org@localhost>
date:      Tue May 22 04:32:56 2018 +0000

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

diffstat:

 tests/kernel/h_segv.c        |   57 +++++++++++++++++----
 tests/kernel/t_trapsignal.sh |  110 +++++++++++++++++++++++++++++++++++-------
 2 files changed, 138 insertions(+), 29 deletions(-)

diffs (truncated from 303 to 300 lines):

diff -r 05d689575894 -r 8664a51e4f82 tests/kernel/h_segv.c
--- a/tests/kernel/h_segv.c     Tue May 22 03:07:50 2018 +0000
+++ b/tests/kernel/h_segv.c     Tue May 22 04:32:56 2018 +0000
@@ -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 @@
        { "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 @@
 
        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 @@
                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 @@
                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 @@
                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;
 }
diff -r 05d689575894 -r 8664a51e4f82 tests/kernel/t_trapsignal.sh
--- a/tests/kernel/t_trapsignal.sh      Tue May 22 03:07:50 2018 +0000
+++ b/tests/kernel/t_trapsignal.sh      Tue May 22 04:32:56 2018 +0000
@@ -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_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
+



Home | Main Index | Thread Index | Old Index