Linux/fork-clone: avoid problems with glibc caching of TID/PID after syscall(__NR_clone)
diff --git a/linux/arch.c b/linux/arch.c
index 7494ea7..ffa943d 100644
--- a/linux/arch.c
+++ b/linux/arch.c
@@ -33,6 +33,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <inttypes.h>
+#include <setjmp.h>
 #include <sys/cdefs.h>
 #include <sys/personality.h>
 #include <sys/ptrace.h>
@@ -79,6 +80,32 @@
     return true;
 }
 
+static uint8_t arch_clone_stack[PTHREAD_STACK_MIN * 2];
+
+static int arch_cloneFunc(void *arg)
+{
+    jmp_buf *env_ptr = (jmp_buf *) arg;
+    longjmp(*env_ptr, 1);
+}
+
+// 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;
+    }
+
+    jmp_buf env;
+    if (setjmp(env) == 0) {
+        void *stack_mid = &arch_clone_stack[sizeof(arch_clone_stack) / 2];
+        // Parent
+        return clone(arch_cloneFunc, stack_mid, flags, &env, NULL, NULL);
+    }
+    // Child
+    return 0;
+}
+
 pid_t arch_fork(honggfuzz_t * hfuzz, fuzzer_t * fuzzer UNUSED)
 {
     /*
@@ -90,7 +117,7 @@
         clone_flags = SIGCHLD;
     }
 
-    pid_t pid = syscall(__NR_clone, (uintptr_t) clone_flags, NULL, NULL, NULL, (uintptr_t) 0);
+    pid_t pid = arch_clone(clone_flags);
 
     if (pid > 0 && hfuzz->persistent) {
         struct f_owner_ex fown = {.type = F_OWNER_TID,.pid = syscall(__NR_gettid), };