aboutsummaryrefslogtreecommitdiffstats
path: root/executor
diff options
context:
space:
mode:
authorMark Johnston <markjdb@gmail.com>2020-08-07 12:48:58 -0400
committerDmitry Vyukov <dvyukov@google.com>2020-08-08 11:09:48 +0200
commit01975a06cb1a7b426ae17985374f2fff3ec38b62 (patch)
treea10683c2345a620f0db29654d6fd4e6083e578c5 /executor
parent594e57536fbab6e403f888f0831240448ffc810d (diff)
executor: always ignore SIGBUS on FreeBSD
syz-executor uses a heuristic to help fail closed if an invalid access might corrupt the output region. This heuristic fails on FreeBSD, where SIGBUS is delievered with si_addr equal to address of the faulting instruction, rather than 0 when the fault address cannot be determined (e.g., an amd64 protection fault). Always handle SIGBUS quietly on FreeBSD. This fixes pkg/runtest tests for sys/test/test/nonfailing.
Diffstat (limited to 'executor')
-rw-r--r--executor/common.h14
1 files changed, 13 insertions, 1 deletions
diff --git a/executor/common.h b/executor/common.h
index 35e3c78da..77bbfc8b5 100644
--- a/executor/common.h
+++ b/executor/common.h
@@ -78,7 +78,19 @@ static void segv_handler(int sig, siginfo_t* info, void* ctx)
uintptr_t addr = (uintptr_t)info->si_addr;
const uintptr_t prog_start = 1 << 20;
const uintptr_t prog_end = 100 << 20;
- if (__atomic_load_n(&skip_segv, __ATOMIC_RELAXED) && (addr < prog_start || addr > prog_end)) {
+ int skip = __atomic_load_n(&skip_segv, __ATOMIC_RELAXED) != 0;
+ int valid = addr < prog_start || addr > prog_end;
+#if GOOS_freebsd || (GOOS_test && HOSTGOOS_freebsd)
+ // FreeBSD delivers SIGBUS in response to any fault that isn't a page
+ // fault. In this case it tries to be helpful and sets si_addr to the
+ // address of the faulting instruction rather than zero as other
+ // operating systems seem to do. However, such faults should always be
+ // ignored.
+ if (sig == SIGBUS) {
+ valid = 1;
+ }
+#endif
+ if (skip && valid) {
debug("SIGSEGV on %p, skipping\n", (void*)addr);
#if GOOS_akaros
struct user_context* uctx = (struct user_context*)ctx;