summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Swiecki <robert@swiecki.net>2017-06-01 21:37:27 +0200
committerRobert Swiecki <robert@swiecki.net>2017-06-01 21:37:27 +0200
commit810d2c973f33cddd54ef880df716f93e3fa1b038 (patch)
treef2bf5124b5f9c91c905ba48beec219dcb56bde87
parent05666b309c7e747f09272beba5e72c1059cb62e9 (diff)
downloadhonggfuzz-810d2c973f33cddd54ef880df716f93e3fa1b038.tar.gz
subproc: use arch_clone also for subproc_System
-rw-r--r--arch.h4
-rw-r--r--cmdline.c5
-rw-r--r--fuzz.c4
-rw-r--r--libcommon/common.h2
-rw-r--r--linux/arch.c138
-rw-r--r--mac/arch.c6
-rw-r--r--posix/arch.c6
-rw-r--r--subproc.c13
-rw-r--r--subproc.h2
9 files changed, 108 insertions, 72 deletions
diff --git a/arch.h b/arch.h
index ec3eb479..f0d520d1 100644
--- a/arch.h
+++ b/arch.h
@@ -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_ */
diff --git a/cmdline.c b/cmdline.c
index 4a6a5329..866fb2f4 100644
--- a/cmdline.c
+++ b/cmdline.c
@@ -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);
diff --git a/fuzz.c b/fuzz.c
index f61cd304..3ccc2bac 100644
--- a/fuzz.c
+++ b/fuzz.c
@@ -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;
}
diff --git a/mac/arch.c b/mac/arch.c
index cd6554b7..4da4e734 100644
--- a/mac/arch.c
+++ b/mac/arch.c
@@ -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)
{
}
diff --git a/subproc.c b/subproc.c
index bbaaaf4c..19185f20 100644
--- a/subproc.c
+++ b/subproc.c
@@ -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;
diff --git a/subproc.h b/subproc.h
index fccd34ea..0f936560 100644
--- a/subproc.h
+++ b/subproc.h
@@ -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);