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