diff options
author | Robert Swiecki <robert@swiecki.net> | 2017-06-01 21:37:27 +0200 |
---|---|---|
committer | Robert Swiecki <robert@swiecki.net> | 2017-06-01 21:37:27 +0200 |
commit | 810d2c973f33cddd54ef880df716f93e3fa1b038 (patch) | |
tree | f2bf5124b5f9c91c905ba48beec219dcb56bde87 | |
parent | 05666b309c7e747f09272beba5e72c1059cb62e9 (diff) | |
download | honggfuzz-810d2c973f33cddd54ef880df716f93e3fa1b038.tar.gz |
subproc: use arch_clone also for subproc_System
-rw-r--r-- | arch.h | 4 | ||||
-rw-r--r-- | cmdline.c | 5 | ||||
-rw-r--r-- | fuzz.c | 4 | ||||
-rw-r--r-- | libcommon/common.h | 2 | ||||
-rw-r--r-- | linux/arch.c | 138 | ||||
-rw-r--r-- | mac/arch.c | 6 | ||||
-rw-r--r-- | posix/arch.c | 6 | ||||
-rw-r--r-- | subproc.c | 13 | ||||
-rw-r--r-- | subproc.h | 2 |
9 files changed, 108 insertions, 72 deletions
@@ -36,6 +36,8 @@ extern pid_t arch_fork(honggfuzz_t * fuzz, fuzzer_t * fuzzer); extern void arch_reapChild(honggfuzz_t * fuzz, fuzzer_t * fuzzer); -extern void arch_prepareChild(honggfuzz_t * fuzz, fuzzer_t * fuzzer); +extern void arch_prepareParent(honggfuzz_t * fuzz, fuzzer_t * fuzzer); + +extern void arch_prepareParentAfterFork(honggfuzz_t * fuzz, fuzzer_t * fuzzer); #endif /* _HF_ARCH_H_ */ @@ -257,7 +257,7 @@ bool cmdlineParse(int argc, char *argv[], honggfuzz_t * hfuzz) .symsWl = NULL, .cloneFlags = 0, .kernelOnly = false, - .skipGLibCCheck = false, + .useClone = true, }, }; /* *INDENT-ON* */ @@ -509,9 +509,6 @@ bool cmdlineParse(int argc, char *argv[], honggfuzz_t * hfuzz) case 0x532: hfuzz->linux.cloneFlags |= (CLONE_NEWUSER | CLONE_NEWIPC); break; - case 0x540: - hfuzz->linux.skipGLibCCheck = true; - break; #endif /* defined(_HF_ARCH_LINUX) */ default: cmdlineUsage(argv[0], custom_opts); @@ -150,7 +150,7 @@ static bool fuzz_prepareFileExternally(honggfuzz_t * hfuzz, fuzzer_t * fuzzer) LOG_D("Created '%s' as an input file", fuzzer->fileName); const char *const argv[] = { hfuzz->externalCommand, fuzzer->fileName, NULL }; - if (subproc_System(argv) != 0) { + if (subproc_System(hfuzz, fuzzer, argv) != 0) { LOG_E("Subprocess '%s' returned abnormally", hfuzz->externalCommand); return false; } @@ -177,7 +177,7 @@ static bool fuzz_postProcessFile(honggfuzz_t * hfuzz, fuzzer_t * fuzzer) } const char *const argv[] = { hfuzz->postExternalCommand, fuzzer->fileName, NULL }; - if (subproc_System(argv) != 0) { + if (subproc_System(hfuzz, fuzzer, argv) != 0) { LOG_E("Subprocess '%s' returned abnormally", hfuzz->postExternalCommand); return false; } diff --git a/libcommon/common.h b/libcommon/common.h index 8afe3763..04cd416f 100644 --- a/libcommon/common.h +++ b/libcommon/common.h @@ -290,7 +290,7 @@ typedef struct { size_t symsWlCnt; uintptr_t cloneFlags; bool kernelOnly; - bool skipGLibCCheck; + bool useClone; } linux; } honggfuzz_t; diff --git a/linux/arch.c b/linux/arch.c index 9a0c37a5..ecf738c5 100644 --- a/linux/arch.c +++ b/linux/arch.c @@ -112,14 +112,41 @@ static inline bool arch_shouldAttach(honggfuzz_t * hfuzz, fuzzer_t * fuzzer) return true; } -pid_t arch_fork(honggfuzz_t * hfuzz, fuzzer_t * fuzzer) +static uint8_t arch_clone_stack[128 * 1024]; +static __thread jmp_buf env; + +#if defined(__has_feature) +#if __has_feature(address_sanitizer) +__attribute__ ((no_sanitize("address"))) __attribute__ ((no_sanitize("memory"))) +#endif /* if __has_feature(address_sanitizer) */ +#endif /* if defined(__has_feature) */ +static int arch_cloneFunc(void *arg UNUSED) { - arch_perfClose(hfuzz, fuzzer); + longjmp(env, 1); + abort(); + return 0; +} - if (hfuzz->linux.cloneFlags && unshare(hfuzz->linux.cloneFlags) == -1) { - LOG_E("unshare(%tx)", hfuzz->linux.cloneFlags); +/* Avoid problem with caching of PID/TID in glibc */ +static pid_t arch_clone(uintptr_t flags) +{ + if (flags & CLONE_VM) { + LOG_E("Cannot use clone(flags & CLONE_VM)"); + return -1; + } + + if (setjmp(env) == 0) { + void *stack_mid = &arch_clone_stack[sizeof(arch_clone_stack) / 2]; + /* Parent */ + return clone(arch_cloneFunc, stack_mid, flags, NULL, NULL, NULL); } - pid_t pid = fork(); + /* Child */ + return 0; +} + +pid_t arch_fork(honggfuzz_t * hfuzz, fuzzer_t * fuzzer UNUSED) +{ + pid_t pid = hfuzz->linux.useClone ? arch_clone(CLONE_UNTRACED | SIGCHLD) : fork(); if (pid == -1) { return pid; } @@ -128,46 +155,19 @@ pid_t arch_fork(honggfuzz_t * hfuzz, fuzzer_t * fuzzer) if (prctl(PR_SET_PDEATHSIG, (unsigned long)SIGKILL, 0UL, 0UL, 0UL) == -1) { PLOG_W("prctl(PR_SET_PDEATHSIG, SIGKILL)"); } - if (hfuzz->linux.cloneFlags & CLONE_NEWNET) { - if (arch_ifaceUp("lo") == false) { - LOG_W("Cannot bring interface 'lo' up"); - } - } return pid; } - - /* Parent */ - if (hfuzz->persistent) { - const struct f_owner_ex fown = { - .type = F_OWNER_TID, - .pid = syscall(__NR_gettid), - }; - if (fcntl(fuzzer->persistentSock, F_SETOWN_EX, &fown)) { - PLOG_F("fcntl(%d, F_SETOWN_EX)", fuzzer->persistentSock); - } - if (fcntl(fuzzer->persistentSock, F_SETSIG, SIGIO) == -1) { - PLOG_F("fcntl(%d, F_SETSIG, SIGIO)", fuzzer->persistentSock); - } - if (fcntl(fuzzer->persistentSock, F_SETFL, O_ASYNC) == -1) { - PLOG_F("fcntl(%d, F_SETFL, O_ASYNC)", fuzzer->persistentSock); - } - int sndbuf = (1024 * 1024 * 2); /* 2MiB */ - if (setsockopt(fuzzer->persistentSock, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf)) == - -1) { - LOG_W("Couldn't set FD send buffer to '%d' bytes", sndbuf); - } - } - - pid_t perf_pid = (hfuzz->linux.pid == 0) ? pid : hfuzz->linux.pid; - if (arch_perfOpen(perf_pid, hfuzz, fuzzer) == false) { - return -1; - } - return pid; } bool arch_launchChild(honggfuzz_t * hfuzz, char *fileName) { + if (hfuzz->linux.cloneFlags & CLONE_NEWNET) { + if (arch_ifaceUp("lo") == false) { + LOG_W("Cannot bring interface 'lo' up"); + } + } + /* * Make it attach-able by ptrace() */ @@ -237,7 +237,39 @@ bool arch_launchChild(honggfuzz_t * hfuzz, char *fileName) return false; } -void arch_prepareChild(honggfuzz_t * hfuzz, fuzzer_t * fuzzer) +void arch_prepareParentAfterFork(honggfuzz_t * hfuzz, fuzzer_t * fuzzer) +{ + arch_perfClose(hfuzz, fuzzer); + + /* Parent */ + if (hfuzz->persistent) { + const struct f_owner_ex fown = { + .type = F_OWNER_TID, + .pid = syscall(__NR_gettid), + }; + if (fcntl(fuzzer->persistentSock, F_SETOWN_EX, &fown)) { + PLOG_F("fcntl(%d, F_SETOWN_EX)", fuzzer->persistentSock); + } + if (fcntl(fuzzer->persistentSock, F_SETSIG, SIGIO) == -1) { + PLOG_F("fcntl(%d, F_SETSIG, SIGIO)", fuzzer->persistentSock); + } + if (fcntl(fuzzer->persistentSock, F_SETFL, O_ASYNC) == -1) { + PLOG_F("fcntl(%d, F_SETFL, O_ASYNC)", fuzzer->persistentSock); + } + int sndbuf = (1024 * 1024 * 2); /* 2MiB */ + if (setsockopt(fuzzer->persistentSock, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf)) == + -1) { + LOG_W("Couldn't set FD send buffer to '%d' bytes", sndbuf); + } + } + + pid_t perf_pid = (hfuzz->linux.pid == 0) ? fuzzer->pid : hfuzz->linux.pid; + if (arch_perfOpen(perf_pid, hfuzz, fuzzer) == false) { + LOG_F("arch_perfOpen(pid=%d)", (int)perf_pid); + } +} + +void arch_prepareParent(honggfuzz_t * hfuzz, fuzzer_t * fuzzer) { pid_t ptracePid = (hfuzz->linux.pid > 0) ? hfuzz->linux.pid : fuzzer->pid; pid_t childPid = fuzzer->pid; @@ -245,6 +277,7 @@ void arch_prepareChild(honggfuzz_t * hfuzz, fuzzer_t * fuzzer) if (arch_shouldAttach(hfuzz, fuzzer) == true) { if (arch_ptraceAttach(hfuzz, ptracePid) == false) { LOG_E("arch_ptraceAttach(pid=%d) failed", ptracePid); + kill(ptracePid, SIGKILL); } fuzzer->linux.attachedPid = ptracePid; } @@ -401,30 +434,24 @@ bool arch_archInit(honggfuzz_t * hfuzz) const char *(*gvs) (void) = dlsym(RTLD_DEFAULT, "gnu_get_libc_version"); for (;;) { if (!gvs) { - LOG_D("Unknown libc implementation"); + LOG_W("Unknown libc implementation. Using clone() instead of fork()"); break; } const char *gversion = gvs(); int major, minor; if (sscanf(gversion, "%d.%d", &major, &minor) != 2) { - LOG_W("Unknown glibc version:'%s'", gversion); + LOG_W("Unknown glibc version:'%s'. Using clone() instead of fork()", gversion); break; } if ((major < 2) || (major == 2 && minor < 23)) { - if (hfuzz->linux.skipGLibCCheck) { - LOG_W("Your glibc version:'%s' will most likely result in malloc()-related " - "deadlocks. Min. version 2.24 (Or, Ubuntu's 2.23-0ubuntu6) suggested. " - "See https://sourceware.org/bugzilla/show_bug.cgi?id=19431 for explanation", - gversion); - break; - } else { - LOG_F("Your glibc version:'%s' will most likely result in malloc()-related " - "deadlocks. Min. version 2.24 (Or, Ubuntu's 2.23-0ubuntu6) required. " - "See https://sourceware.org/bugzilla/show_bug.cgi?id=19431 for explanation. " - "Use --linux_skip_glibc_check to continue despite this check.", gversion); - } + LOG_W("Your glibc version:'%s' will most likely result in malloc()-related " + "deadlocks. Min. version 2.24 (Or, Ubuntu's 2.23-0ubuntu6) suggested. " + "See https://sourceware.org/bugzilla/show_bug.cgi?id=19431 for explanation. " + "Using clone() instead of fork()", gversion); + break; } LOG_D("Glibc version:'%s', OK", gversion); + hfuzz->linux.useClone = false; break; } @@ -538,6 +565,11 @@ bool arch_archInit(honggfuzz_t * hfuzz) hfuzz->linux.numMajorFrames = 14; } + if (hfuzz->linux.cloneFlags && unshare(hfuzz->linux.cloneFlags) == -1) { + LOG_E("unshare(%tx)", hfuzz->linux.cloneFlags); + return false; + } + return true; } @@ -372,7 +372,11 @@ bool arch_launchChild(honggfuzz_t * hfuzz, char *fileName) return false; } -void arch_prepareChild(honggfuzz_t * hfuzz UNUSED, fuzzer_t * fuzzer UNUSED) +void arch_prepareParent(honggfuzz_t * hfuzz UNUSED, fuzzer_t * fuzzer UNUSED) +{ +} + +void arch_prepareParentAfterFork(honggfuzz_t * hfuzz UNUSED, fuzzer_t * fuzzer UNUSED) { } diff --git a/posix/arch.c b/posix/arch.c index 3ad35187..8f305e94 100644 --- a/posix/arch.c +++ b/posix/arch.c @@ -186,7 +186,11 @@ bool arch_launchChild(honggfuzz_t * hfuzz, char *fileName) return false; } -void arch_prepareChild(honggfuzz_t * hfuzz UNUSED, fuzzer_t * fuzzer UNUSED) +void arch_prepareParent(honggfuzz_t * hfuzz UNUSED, fuzzer_t * fuzzer UNUSED) +{ +} + +void arch_prepareParentAfterFork(honggfuzz_t * hfuzz UNUSED, fuzzer_t * fuzzer UNUSED) { } @@ -293,6 +293,8 @@ static bool subproc_New(honggfuzz_t * hfuzz, fuzzer_t * fuzzer) fuzzer->persistentPid = fuzzer->pid; } + arch_prepareParentAfterFork(hfuzz, fuzzer); + return true; } @@ -303,7 +305,7 @@ bool subproc_Run(honggfuzz_t * hfuzz, fuzzer_t * fuzzer) return false; } - arch_prepareChild(hfuzz, fuzzer); + arch_prepareParent(hfuzz, fuzzer); if (hfuzz->persistent == true && subproc_persistentSendFile(fuzzer) == false) { LOG_W("Could not send file contents to the persistent process"); } @@ -312,20 +314,15 @@ bool subproc_Run(honggfuzz_t * hfuzz, fuzzer_t * fuzzer) return true; } -uint8_t subproc_System(const char *const argv[]) +uint8_t subproc_System(honggfuzz_t * hfuzz, fuzzer_t * fuzzer, const char *const argv[]) { - pid_t pid = fork(); + pid_t pid = arch_fork(hfuzz, fuzzer); if (pid == -1) { PLOG_E("Couldn't fork"); return 255; } - if (!pid) { logMutexReset(); - sigset_t sset; - sigemptyset(&sset); - sigprocmask(SIG_SETMASK, &sset, NULL); - setsid(); execv(argv[0], (char *const *)&argv[0]); PLOG_F("Couldn't execute '%s'", argv[0]); return 255; @@ -40,7 +40,7 @@ extern bool subproc_Run(honggfuzz_t * hfuzz, fuzzer_t * fuzzer); extern bool subproc_persistentModeRoundDone(honggfuzz_t * hfuzz, fuzzer_t * fuzzer); -extern uint8_t subproc_System(const char *const argv[]); +extern uint8_t subproc_System(honggfuzz_t * hfuzz, fuzzer_t * fuzzer, const char *const argv[]); extern void subproc_checkTimeLimit(honggfuzz_t * hfuzz, fuzzer_t * fuzzer); |