diff options
| author | kamil <kamil@NetBSD.org> | 2018-05-27 17:04:45 +0000 |
|---|---|---|
| committer | kamil <kamil@NetBSD.org> | 2018-05-27 17:04:45 +0000 |
| commit | 86231c592b2b5e8483e1866eba45b39d80b44d5e (patch) | |
| tree | 52920ae2ff996d497d4075d4431c410472d38b94 /tests/kernel | |
| parent | 77535c1bb61feb0de13ffe4e9010d1dc6d98219c (diff) | |
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 (limited to 'tests/kernel')
| -rw-r--r-- | tests/kernel/h_segv.c | 145 | ||||
| -rw-r--r-- | tests/kernel/t_trapsignal.sh | 165 |
2 files changed, 276 insertions, 34 deletions
diff --git a/tests/kernel/h_segv.c b/tests/kernel/h_segv.c index f07dcf4b7a7..b81491949c6 100644 --- a/tests/kernel/h_segv.c +++ b/tests/kernel/h_segv.c @@ -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/22 04:32:56 kamil Exp $"); #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; } diff --git a/tests/kernel/t_trapsignal.sh b/tests/kernel/t_trapsignal.sh index 13850a7a8fc..d19f69135ae 100644 --- a/tests/kernel/t_trapsignal.sh +++ b/tests/kernel/t_trapsignal.sh @@ -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 } |
