diff options
| author | Mark Johnston <markjdb@gmail.com> | 2020-08-07 12:48:58 -0400 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2020-08-08 11:09:48 +0200 |
| commit | 01975a06cb1a7b426ae17985374f2fff3ec38b62 (patch) | |
| tree | a10683c2345a620f0db29654d6fd4e6083e578c5 /executor | |
| parent | 594e57536fbab6e403f888f0831240448ffc810d (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.h | 14 |
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; |
