about summary refs log tree commit diff
path: root/coresight_mode/patches/0001-Add-AFL-forkserver.patch
blob: 51c242c460501daec0def7a15a5b3206a81b0594 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
diff --git a/glibc-2.33/elf/rtld.c b/glibc-2.33/elf/rtld.c
index 596b6ac3..2ee270d4 100644
--- a/glibc-2.33/elf/rtld.c
+++ b/glibc-2.33/elf/rtld.c
@@ -169,6 +169,99 @@ uintptr_t __pointer_chk_guard_local
 strong_alias (__pointer_chk_guard_local, __pointer_chk_guard)
 #endif
 
+#define AFLCS_RTLD 1
+
+#if AFLCS_RTLD
+
+#include <sys/shm.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <dlfcn.h>
+#include <signal.h>
+
+#include <asm/unistd.h>
+#include <unistd.h>
+
+#define FORKSRV_FD 198
+
+#define AFLCS_ENABLE "__AFLCS_ENABLE"
+
+/* We use this additional AFLCS_# AFLCS_#+1 pair to communicate with proxy */
+#define AFLCS_FORKSRV_FD (FORKSRV_FD - 3)
+#define AFLCS_RTLD_SNIPPET do { __cs_start_forkserver(); } while(0)
+
+/* Fork server logic, invoked before we return from _dl_start. */
+
+static void __cs_start_forkserver(void) {
+  int status;
+  pid_t child_pid;
+  static char tmp[4] = {0, 0, 0, 0};
+
+  if (!getenv(AFLCS_ENABLE)) {
+    return;
+  }
+
+  if (write(AFLCS_FORKSRV_FD + 1, tmp, 4) != 4) {
+    _exit(-1);
+  }
+
+  /* All right, let's await orders... */
+  while (1) {
+    /* Whoops, parent dead? */
+    if (read(AFLCS_FORKSRV_FD, tmp, 4) != 4) {
+      _exit(1);
+    }
+
+    child_pid = INLINE_SYSCALL(clone, 5,
+        CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD, 0,
+        NULL, NULL, &THREAD_SELF->tid);
+    if (child_pid < 0) {
+      _exit(4);
+    }
+    if (!child_pid) {
+      /* Child process. Wait for parent start tracing */
+      kill(getpid(), SIGSTOP);
+      /* Close descriptors and run free. */
+      close(AFLCS_FORKSRV_FD);
+      close(AFLCS_FORKSRV_FD + 1);
+      return;
+    }
+
+    /* Parent. */
+    if (write(AFLCS_FORKSRV_FD + 1, &child_pid, 4) != 4) {
+      _exit(5);
+    }
+
+    /* Wait until SIGCONT is signaled. */
+    if (waitpid(child_pid, &status, WCONTINUED) < 0) {
+      _exit(6);
+    }
+    if (!WIFCONTINUED(status)) {
+      /* Relay status to proxy. */
+      if (write(AFLCS_FORKSRV_FD + 1, &status, 4) != 4) {
+        _exit(7);
+      }
+      continue;
+    }
+    while (1) {
+      /* Get status. */
+      if (waitpid(child_pid, &status, WUNTRACED) < 0) {
+        _exit(8);
+      }
+      /* Relay status to proxy. */
+      if (write(AFLCS_FORKSRV_FD + 1, &status, 4) != 4) {
+        _exit(9);
+      }
+      if (!(WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP)) {
+        /* The child process is exited. */
+        break;
+      }
+    }
+  }
+}
+
+#endif /* AFLCS_RTLD */
+
 /* Check that AT_SECURE=0, or that the passed name does not contain
    directories and is not overly long.  Reject empty names
    unconditionally.  */
@@ -588,6 +681,12 @@ _dl_start (void *arg)
 # define ELF_MACHINE_START_ADDRESS(map, start) (start)
 #endif
 
+    /* AFL-CS-START */
+#if AFLCS_RTLD
+    AFLCS_RTLD_SNIPPET;
+#endif
+    /* AFL-CS-END */
+
     return ELF_MACHINE_START_ADDRESS (GL(dl_ns)[LM_ID_BASE]._ns_loaded, entry);
   }
 }