about summary refs log tree commit diff
path: root/frida_mode/src
diff options
context:
space:
mode:
Diffstat (limited to 'frida_mode/src')
-rw-r--r--frida_mode/src/entry.c2
-rw-r--r--frida_mode/src/js/api.js9
-rw-r--r--frida_mode/src/js/js_api.c8
-rw-r--r--frida_mode/src/main.c3
-rw-r--r--frida_mode/src/seccomp/seccomp.c157
-rw-r--r--frida_mode/src/seccomp/seccomp_atomic.c28
-rw-r--r--frida_mode/src/seccomp/seccomp_child.c69
-rw-r--r--frida_mode/src/seccomp/seccomp_event.c45
-rw-r--r--frida_mode/src/seccomp/seccomp_filter.c258
-rw-r--r--frida_mode/src/seccomp/seccomp_socket.c121
-rw-r--r--frida_mode/src/seccomp/seccomp_syscall.c335
11 files changed, 1035 insertions, 0 deletions
diff --git a/frida_mode/src/entry.c b/frida_mode/src/entry.c
index 3ec8f5be..186ddd3a 100644
--- a/frida_mode/src/entry.c
+++ b/frida_mode/src/entry.c
@@ -8,6 +8,7 @@
 #include "instrument.h"
 #include "persistent.h"
 #include "ranges.h"
+#include "seccomp.h"
 #include "stalker.h"
 #include "stats.h"
 #include "util.h"
@@ -26,6 +27,7 @@ static void entry_launch(void) {
   /* Child here */
   entry_run = TRUE;
   instrument_on_fork();
+  seccomp_on_fork();
   stats_on_fork();
 
 }
diff --git a/frida_mode/src/js/api.js b/frida_mode/src/js/api.js
index cf422ba9..40bb4a16 100644
--- a/frida_mode/src/js/api.js
+++ b/frida_mode/src/js/api.js
@@ -191,6 +191,14 @@ class Afl {
     static setPrefetchDisable() {
         Afl.jsApiSetPrefetchDisable();
     }
+    /**
+     * See `AFL_FRIDA_SECCOMP_FILE`. This function takes a single `string` as
+     * an argument.
+     */
+    static setSeccompFile(file) {
+        const buf = Memory.allocUtf8String(file);
+        Afl.jsApiSetSeccompFile(buf);
+    }
     /*
      * Set a function to be called for each instruction which is instrumented
      * by AFL FRIDA mode.
@@ -271,6 +279,7 @@ Afl.jsApiSetPersistentHook = Afl.jsApiGetFunction("js_api_set_persistent_hook",
 Afl.jsApiSetPersistentReturn = Afl.jsApiGetFunction("js_api_set_persistent_return", "void", ["pointer"]);
 Afl.jsApiSetPrefetchBackpatchDisable = Afl.jsApiGetFunction("js_api_set_prefetch_backpatch_disable", "void", []);
 Afl.jsApiSetPrefetchDisable = Afl.jsApiGetFunction("js_api_set_prefetch_disable", "void", []);
+Afl.jsApiSetSeccompFile = Afl.jsApiGetFunction("js_api_set_seccomp_file", "void", ["pointer"]);
 Afl.jsApiSetStalkerCallback = Afl.jsApiGetFunction("js_api_set_stalker_callback", "void", ["pointer"]);
 Afl.jsApiSetStalkerIcEntries = Afl.jsApiGetFunction("js_api_set_stalker_ic_entries", "void", ["uint32"]);
 Afl.jsApiSetStatsFile = Afl.jsApiGetFunction("js_api_set_stats_file", "void", ["pointer"]);
diff --git a/frida_mode/src/js/js_api.c b/frida_mode/src/js/js_api.c
index 49ca3baa..9dba79aa 100644
--- a/frida_mode/src/js/js_api.c
+++ b/frida_mode/src/js/js_api.c
@@ -7,6 +7,7 @@
 #include "persistent.h"
 #include "prefetch.h"
 #include "ranges.h"
+#include "seccomp.h"
 #include "stalker.h"
 #include "stats.h"
 #include "util.h"
@@ -171,6 +172,13 @@ js_api_set_instrument_unstable_coverage_file(char *path) {
 
 }
 
+__attribute__((visibility("default"))) void js_api_set_seccomp_file(
+    char *file) {
+
+  seccomp_filename = g_strdup(file);
+
+}
+
 __attribute__((visibility("default"))) void js_api_set_stdout(char *file) {
 
   output_stdout = g_strdup(file);
diff --git a/frida_mode/src/main.c b/frida_mode/src/main.c
index 91687046..c0de9c6b 100644
--- a/frida_mode/src/main.c
+++ b/frida_mode/src/main.c
@@ -25,6 +25,7 @@
 #include "persistent.h"
 #include "prefetch.h"
 #include "ranges.h"
+#include "seccomp.h"
 #include "stalker.h"
 #include "stats.h"
 #include "util.h"
@@ -177,6 +178,7 @@ __attribute__((visibility("default"))) void afl_frida_start(void) {
   persistent_config();
   prefetch_config();
   ranges_config();
+  seccomp_config();
   stalker_config();
   stats_config();
 
@@ -191,6 +193,7 @@ __attribute__((visibility("default"))) void afl_frida_start(void) {
   lib_init();
   persistent_init();
   prefetch_init();
+  seccomp_init();
   stalker_init();
   ranges_init();
   stats_init();
diff --git a/frida_mode/src/seccomp/seccomp.c b/frida_mode/src/seccomp/seccomp.c
new file mode 100644
index 00000000..7683cd71
--- /dev/null
+++ b/frida_mode/src/seccomp/seccomp.c
@@ -0,0 +1,157 @@
+#include <execinfo.h>
+#include <fcntl.h>
+#include <linux/seccomp.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include "frida-gumjs.h"
+
+#include "debug.h"
+
+#include "seccomp.h"
+#include "util.h"
+
+char *seccomp_filename = NULL;
+
+static void seccomp_vprint(int fd, char *format, va_list ap) {
+
+  char buffer[4096] = {0};
+  int  len;
+
+  if (vsnprintf(buffer, sizeof(buffer) - 1, format, ap) < 0) { return; }
+
+  len = strnlen(buffer, sizeof(buffer));
+  IGNORED_RETURN(write(fd, buffer, len));
+
+}
+
+void seccomp_print(char *format, ...) {
+
+  va_list ap;
+  va_start(ap, format);
+  seccomp_vprint(SECCOMP_OUTPUT_FILE_FD, format, ap);
+  va_end(ap);
+
+}
+
+static void seccomp_filter_callback(struct seccomp_notif *     req,
+                                    struct seccomp_notif_resp *resp,
+                                    GumReturnAddressArray *    frames) {
+
+  GumDebugSymbolDetails details = {0};
+  if (req->data.nr == SYS_OPENAT) {
+
+    seccomp_print("SYS_OPENAT: (%s)\n", (char *)req->data.args[1]);
+
+  }
+
+  seccomp_print(
+      "\nID (%#llx) for PID %d - %d (%s) [0x%llx 0x%llx 0x%llx 0x%llx 0x%llx "
+      "0x%llx ]\n",
+      req->id, req->pid, req->data.nr, seccomp_syscall_lookup(req->data.nr),
+      req->data.args[0], req->data.args[1], req->data.args[2],
+      req->data.args[3], req->data.args[4], req->data.args[5]);
+
+  seccomp_print("FRAMES: (%u)\n", frames->len);
+  char **syms = backtrace_symbols(frames->items, frames->len);
+  if (syms == NULL) { FATAL("Failed to get symbols"); }
+
+  for (guint i = 0; i < frames->len; i++) {
+
+    if (gum_symbol_details_from_address(frames->items[i], &details)) {
+
+      seccomp_print("\t%3d. %s!%s\n", i, details.module_name,
+                    details.symbol_name);
+
+    } else {
+
+      seccomp_print("\t%3d. %s\n", i, syms[i]);
+
+    }
+
+  }
+
+  free(syms);
+
+  resp->error = 0;
+  resp->val = 0;
+  resp->id = req->id;
+  resp->flags = SECCOMP_USER_NOTIF_FLAG_CONTINUE;
+
+}
+
+static void seccomp_child(int signal_parent, void *ctx) {
+
+  int sock_fd = *((int *)ctx);
+  int fd = seccomp_socket_recv(sock_fd);
+
+  if (close(sock_fd) < 0) { FATAL("child - close"); }
+
+  seccomp_event_signal(signal_parent);
+  seccomp_filter_child_install();
+  seccomp_filter_run(fd, seccomp_filter_callback);
+
+}
+
+void seccomp_on_fork(void) {
+
+  int   sock[2] = {-1, -1};
+  pid_t child = -1;
+  int   child_fd = -1;
+
+  if (seccomp_filename == NULL) { return; }
+
+  seccomp_socket_create(sock);
+  seccomp_child_run(seccomp_child, sock, &child, &child_fd);
+
+  if (dup2(child_fd, SECCOMP_PARENT_EVENT_FD) < 0) { FATAL("dup2"); }
+
+  if (close(child_fd) < 0) { FATAL("seccomp_on_fork - close (1)"); }
+
+  if (close(sock[STDIN_FILENO]) < 0) { FATAL("grandparent - close (2)"); }
+
+  int fd = seccomp_filter_install(child);
+  seccomp_socket_send(sock[STDOUT_FILENO], fd);
+
+  if (close(sock[STDOUT_FILENO]) < 0) { FATAL("grandparent - close (3)"); }
+
+  if (close(fd) < 0) { FATAL("grandparent - close (4)"); }
+
+  seccomp_child_wait(SECCOMP_PARENT_EVENT_FD);
+
+}
+
+void seccomp_config(void) {
+
+  seccomp_filename = getenv("AFL_FRIDA_SECCOMP_FILE");
+
+}
+
+void seccomp_init(void) {
+
+  char *path = NULL;
+  int   fd;
+
+  OKF("Seccomp - file [%s]", seccomp_filename);
+
+  if (seccomp_filename == NULL) { return; }
+
+  path = g_canonicalize_filename(seccomp_filename, g_get_current_dir());
+
+  OKF("Seccomp - path [%s]", path);
+
+  fd = open(path, O_RDWR | O_CREAT | O_TRUNC,
+            S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
+
+  if (dup2(fd, SECCOMP_OUTPUT_FILE_FD) < 0) {
+
+    FATAL("Failed to duplicate seccomp output file");
+
+  }
+
+  if (close(fd) < 0) { FATAL("Failed to close seccomp output file fd"); }
+
+  g_free(path);
+
+}
+
diff --git a/frida_mode/src/seccomp/seccomp_atomic.c b/frida_mode/src/seccomp/seccomp_atomic.c
new file mode 100644
index 00000000..1720a726
--- /dev/null
+++ b/frida_mode/src/seccomp/seccomp_atomic.c
@@ -0,0 +1,28 @@
+#include <stdbool.h>
+#include <stdio.h>
+
+#include "debug.h"
+
+void seccomp_atomic_set(volatile bool *ptr, bool val) {
+
+  if (!__sync_bool_compare_and_swap(ptr, !val, val)) {
+
+    FATAL("Failed to set event");
+
+  }
+
+}
+
+bool seccomp_atomic_try_set(volatile bool *ptr, bool val) {
+
+  return __sync_bool_compare_and_swap(ptr, !val, val);
+
+}
+
+void seccomp_atomic_wait(volatile bool *ptr, bool val) {
+
+  while (!__sync_bool_compare_and_swap(ptr, val, !val))
+    ;
+
+}
+
diff --git a/frida_mode/src/seccomp/seccomp_child.c b/frida_mode/src/seccomp/seccomp_child.c
new file mode 100644
index 00000000..4d494137
--- /dev/null
+++ b/frida_mode/src/seccomp/seccomp_child.c
@@ -0,0 +1,69 @@
+#include <fcntl.h>
+#include <sched.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/mman.h>
+#include <sys/prctl.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "debug.h"
+
+#include "seccomp.h"
+
+#define SECCOMP_CHILD_STACK_SIZE (1UL << 20)
+
+typedef void (*seccomp_child_func_t)(int event_fd, void *ctx);
+
+typedef struct {
+
+  seccomp_child_func_t func;
+  int                  event_fd;
+  void *               ctx;
+
+} seccomp_child_func_ctx_t;
+
+static int seccomp_child_func(void *ctx) {
+
+  seccomp_child_func_ctx_t *args = (seccomp_child_func_ctx_t *)ctx;
+  args->func(args->event_fd, args->ctx);
+  _exit(0);
+  return 0;
+
+}
+
+void seccomp_child_run(seccomp_child_func_t child_func, void *ctx, pid_t *child,
+                       int *event_fd) {
+
+  int fd = seccomp_event_create();
+
+  seccomp_child_func_ctx_t *child_ctx =
+      malloc(sizeof(seccomp_child_func_ctx_t));
+  child_ctx->func = child_func;
+  child_ctx->ctx = ctx;
+  child_ctx->event_fd = fd;
+
+  int flags = CLONE_VM | CLONE_UNTRACED;
+
+  char *stack =
+      (char *)mmap(NULL, SECCOMP_CHILD_STACK_SIZE, PROT_READ | PROT_WRITE,
+                   MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+  if (stack == MAP_FAILED) { FATAL("mmap"); }
+
+  pid_t child_pid = clone(seccomp_child_func, &stack[SECCOMP_CHILD_STACK_SIZE],
+                          flags, child_ctx, NULL, NULL, NULL);
+  if (child_pid < 0) { FATAL("clone"); }
+
+  if (child != NULL) { *child = child_pid; }
+  if (event_fd != NULL) { *event_fd = fd; }
+
+}
+
+void seccomp_child_wait(int event_fd) {
+
+  seccomp_event_wait(event_fd);
+  seccomp_event_destroy(event_fd);
+
+}
+
diff --git a/frida_mode/src/seccomp/seccomp_event.c b/frida_mode/src/seccomp/seccomp_event.c
new file mode 100644
index 00000000..ecb9be32
--- /dev/null
+++ b/frida_mode/src/seccomp/seccomp_event.c
@@ -0,0 +1,45 @@
+#include <stdint.h>
+#include <stdio.h>
+#include <sys/eventfd.h>
+#include <unistd.h>
+
+#include "debug.h"
+
+#include "seccomp.h"
+
+int seccomp_event_create(void) {
+
+  int fd = eventfd(0, 0);
+  if (fd < 0) { FATAL("seccomp_event_create"); }
+  return fd;
+
+}
+
+void seccomp_event_signal(int fd) {
+
+  uint64_t val = 1;
+  if (write(fd, &val, sizeof(uint64_t)) != sizeof(uint64_t)) {
+
+    FATAL("seccomp_event_signal");
+
+  }
+
+}
+
+void seccomp_event_wait(int fd) {
+
+  uint64_t val = 1;
+  if (read(fd, &val, sizeof(uint64_t)) != sizeof(uint64_t)) {
+
+    FATAL("seccomp_event_wait");
+
+  }
+
+}
+
+void seccomp_event_destroy(int fd) {
+
+  if (close(fd) < 0) { FATAL("seccomp_event_destroy"); }
+
+}
+
diff --git a/frida_mode/src/seccomp/seccomp_filter.c b/frida_mode/src/seccomp/seccomp_filter.c
new file mode 100644
index 00000000..c16e7ebd
--- /dev/null
+++ b/frida_mode/src/seccomp/seccomp_filter.c
@@ -0,0 +1,258 @@
+#include <alloca.h>
+#include <errno.h>
+#include <execinfo.h>
+#include <linux/filter.h>
+#include <linux/seccomp.h>
+#include <sys/ioctl.h>
+#include <sys/prctl.h>
+#include <sys/syscall.h>
+#include <signal.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "debug.h"
+
+#include "frida-gumjs.h"
+
+#include "seccomp.h"
+#include "util.h"
+
+#define SECCOMP_FILTER_NUM_FRAMES 512
+
+extern void gum_linux_parse_ucontext(const ucontext_t *uc, GumCpuContext *ctx);
+
+static struct sock_filter filter[] = {
+
+    /* Allow us sendmsg to SECCOMP_FD */
+    BPF_STMT(BPF_LD | BPF_W | BPF_ABS, (offsetof(struct seccomp_data, nr))),
+    BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_sendmsg, 0, 3),
+    BPF_STMT(BPF_LD | BPF_W | BPF_ABS,
+             (offsetof(struct seccomp_data, args[0]))),
+    BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, SECCOMP_SOCKET_SEND_FD, 0, 1),
+    BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),
+
+    /* Allow close */
+    BPF_STMT(BPF_LD | BPF_W | BPF_ABS, (offsetof(struct seccomp_data, nr))),
+    BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_close, 0, 1),
+    BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),
+
+    /* Allow sigreturn */
+    BPF_STMT(BPF_LD | BPF_W | BPF_ABS, (offsetof(struct seccomp_data, nr))),
+    BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_rt_sigreturn, 0, 1),
+    BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),
+
+    /* Allow sigprocmaksk */
+    BPF_STMT(BPF_LD | BPF_W | BPF_ABS, (offsetof(struct seccomp_data, nr))),
+    BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_rt_sigprocmask, 0, 1),
+    BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),
+
+    /* Allow console output*/
+    BPF_STMT(BPF_LD | BPF_W | BPF_ABS, (offsetof(struct seccomp_data, nr))),
+    BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_lseek, 2, 0),
+    BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_fstat, 1, 0),
+    BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_write, 0, 4),
+    BPF_STMT(BPF_LD | BPF_W | BPF_ABS,
+             (offsetof(struct seccomp_data, args[0]))),
+    BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, STDERR_FILENO, 1, 0),
+    BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, STDOUT_FILENO, 0, 1),
+    BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),
+
+    /* Allow waiting for the child */
+    BPF_STMT(BPF_LD | BPF_W | BPF_ABS, (offsetof(struct seccomp_data, nr))),
+    BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_read, 0, 3),
+    BPF_STMT(BPF_LD | BPF_W | BPF_ABS,
+             (offsetof(struct seccomp_data, args[0]))),
+    BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, SECCOMP_PARENT_EVENT_FD, 0, 1),
+    BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),
+
+    /* Allow us to make anonymous maps */
+    BPF_STMT(BPF_LD | BPF_W | BPF_ABS, (offsetof(struct seccomp_data, nr))),
+    BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_mmap, 0, 3),
+    BPF_STMT(BPF_LD | BPF_W | BPF_ABS,
+             (offsetof(struct seccomp_data, args[4]))),
+    BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, -1, 0, 1),
+    BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),
+
+    /* Allow msync/mincore used by cmplog */
+    BPF_STMT(BPF_LD | BPF_W | BPF_ABS, (offsetof(struct seccomp_data, nr))),
+    BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_msync, 1, 0),
+    BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_mincore, 0, 1),
+    BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),
+
+    /*
+     * Allow tgkill (SIGKILL, SIGSTOP) used in persistent mode. Also
+     * allow seccomp to send (SIGUSR1) to the child to collect trace.
+     */
+    BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_tgkill, 0, 5),
+    BPF_STMT(BPF_LD | BPF_W | BPF_ABS,
+             (offsetof(struct seccomp_data, args[2]))),
+    /* Used by seccomp to signal the child to collect a callstack*/
+    BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, SIGUSR1, 2, 0),
+    /* Used when handling faults */
+    BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, SIGKILL, 1, 0),
+    /* Used by target app of interest */
+    BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, SIGSTOP, 0, 1),
+    BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),
+
+    /* Allow getpid / gettid */
+    BPF_STMT(BPF_LD | BPF_W | BPF_ABS, (offsetof(struct seccomp_data, nr))),
+    BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_getpid, 1, 0),
+    BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_gettid, 0, 1),
+    BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),
+
+    /* Allow exit_group */
+    BPF_STMT(BPF_LD | BPF_W | BPF_ABS, (offsetof(struct seccomp_data, nr))),
+    BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_exit_group, 0, 1),
+    BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),
+
+    /* Allow brk */
+    BPF_STMT(BPF_LD | BPF_W | BPF_ABS, (offsetof(struct seccomp_data, nr))),
+    BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_brk, 0, 1),
+    BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),
+
+    /* Send the rest to user-mode to filter */
+    BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_USER_NOTIF)};
+
+static volatile bool         seccomp_filter_parent_done = false;
+static volatile bool         seccomp_filter_child_done = false;
+static pid_t                 seccomp_filter_child = -1;
+static GumCpuContext         seccomp_filter_cpu_context = {0};
+static GumReturnAddressArray seccomp_filter_frames = {.len = 0, .items = {0}};
+static GumBacktracer *       seccomp_filter_backtracer = NULL;
+
+static void seccomp_filter_child_handler(int sig, siginfo_t *info,
+                                         void *ucontext) {
+
+  GumCpuContext cpu_context;
+  if (seccomp_filter_backtracer == NULL) {
+
+    seccomp_filter_backtracer = gum_backtracer_make_fuzzy();
+
+  }
+
+  gum_backtracer_generate(seccomp_filter_backtracer,
+                          &seccomp_filter_cpu_context, &seccomp_filter_frames);
+
+  seccomp_atomic_set(&seccomp_filter_child_done, true);
+
+}
+
+static void seccomp_filter_parent_handler(int sig, siginfo_t *info,
+                                          void *ucontext) {
+
+  UNUSED_PARAMETER(sig);
+  UNUSED_PARAMETER(info);
+
+  ucontext_t *uc = (ucontext_t *)ucontext;
+  gum_linux_parse_ucontext(uc, &seccomp_filter_cpu_context);
+
+  if (tgkill(seccomp_filter_child, seccomp_filter_child, SIGUSR1) < 0) {
+
+    FATAL("kill");
+
+  }
+
+  seccomp_atomic_wait(&seccomp_filter_child_done, true);
+  seccomp_atomic_set(&seccomp_filter_parent_done, true);
+
+}
+
+void seccomp_filter_child_install(void) {
+
+  const struct sigaction sa = {.sa_sigaction = seccomp_filter_child_handler,
+                               .sa_flags = SA_SIGINFO | SA_RESTART};
+  if (sigaction(SIGUSR1, &sa, NULL) < 0) { FATAL("sigaction"); }
+
+}
+
+int seccomp_filter_install(pid_t child) {
+
+  seccomp_filter_child = child;
+
+  const struct sigaction sa = {.sa_sigaction = seccomp_filter_parent_handler,
+                               .sa_flags = SA_SIGINFO | SA_RESTART};
+
+  struct sock_fprog filter_prog = {
+
+      .len = sizeof(filter) / sizeof(struct sock_filter), .filter = filter};
+
+  if (sigaction(SIGUSR1, &sa, NULL) < 0) { FATAL("sigaction"); }
+
+  if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
+
+    FATAL("PR_SET_NO_NEW_PRIVS %d", errno);
+
+  }
+
+  int fd = syscall(SYS_seccomp, SECCOMP_SET_MODE_FILTER,
+                   SECCOMP_FILTER_FLAG_NEW_LISTENER, &filter_prog);
+  if (fd < 0) { FATAL("SYS_seccomp %d", fd); }
+
+  return fd;
+
+}
+
+void seccomp_filter_run(int fd, seccomp_filter_callback_t callback) {
+
+  struct seccomp_notif *     req = NULL;
+  struct seccomp_notif_resp *resp = NULL;
+  struct seccomp_notif_sizes sizes;
+
+  if (syscall(SYS_seccomp, SECCOMP_GET_NOTIF_SIZES, 0, &sizes) == -1) {
+
+    FATAL("seccomp-SECCOMP_GET_NOTIF_SIZES");
+
+  }
+
+  if (sizes.seccomp_notif != sizeof(struct seccomp_notif)) {
+
+    FATAL("size - seccomp_notif");
+
+  }
+
+  if (sizes.seccomp_notif_resp != sizeof(struct seccomp_notif_resp)) {
+
+    FATAL("size - seccomp_notif");
+
+  }
+
+  req = alloca(sizes.seccomp_notif);
+  resp = alloca(sizes.seccomp_notif_resp);
+
+  while (true) {
+
+    memset(req, 0, sizes.seccomp_notif);
+
+    if (ioctl(fd, SECCOMP_IOCTL_NOTIF_RECV, req) < 0) {
+
+      if (errno == EINTR) { continue; }
+      FATAL("SECCOMP_IOCTL_NOTIF_RECV: %d\n", fd);
+
+    }
+
+    if (seccomp_atomic_try_set(&seccomp_filter_parent_done, false)) {
+
+      callback(req, resp, &seccomp_filter_frames);
+
+    } else {
+
+      if (kill(req->pid, SIGUSR1) < 0) { FATAL("kill"); }
+
+    }
+
+    if (ioctl(fd, SECCOMP_IOCTL_NOTIF_SEND, resp) < 0) {
+
+      if (errno == ENOENT) { continue; }
+      OKF("SECCOMP_IOCTL_NOTIF_SEND");
+      continue;
+
+    }
+
+  }
+
+}
+
diff --git a/frida_mode/src/seccomp/seccomp_socket.c b/frida_mode/src/seccomp/seccomp_socket.c
new file mode 100644
index 00000000..ca42e158
--- /dev/null
+++ b/frida_mode/src/seccomp/seccomp_socket.c
@@ -0,0 +1,121 @@
+#include <stdio.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <unistd.h>
+
+#include "debug.h"
+
+#include "seccomp.h"
+
+union cmsg {
+
+  char           buf[CMSG_SPACE(sizeof(int))];
+  struct cmsghdr hdr;
+
+};
+
+void seccomp_socket_create(int *sock) {
+
+  int tmp_sock[2] = {-1, -1};
+  if (socketpair(AF_UNIX, SOCK_STREAM, 0, tmp_sock) < 0) {
+
+    FATAL("socketpair");
+
+  }
+
+  if (dup2(tmp_sock[STDIN_FILENO], SECCOMP_SOCKET_RECV_FD) < 0) {
+
+    FATAL("seccomp_socket_create - dup2 (1)");
+
+  }
+
+  if (dup2(tmp_sock[STDOUT_FILENO], SECCOMP_SOCKET_SEND_FD) < 0) {
+
+    FATAL("seccomp_socket_create - dup2 (1)");
+
+  }
+
+  if (close(tmp_sock[STDIN_FILENO]) < 0) {
+
+    FATAL("seccomp_socket_create - close (1)");
+
+  }
+
+  if (close(tmp_sock[STDOUT_FILENO]) < 0) {
+
+    FATAL("seccomp_socket_create - close (2)");
+
+  }
+
+  sock[STDIN_FILENO] = SECCOMP_SOCKET_RECV_FD;
+  sock[STDOUT_FILENO] = SECCOMP_SOCKET_SEND_FD;
+
+}
+
+void seccomp_socket_send(int sockfd, int fd) {
+
+  int          data = 12345;
+  struct iovec iov = {.iov_base = &data, .iov_len = sizeof(data)};
+  union cmsg   control_msg = {.hdr = {
+
+                                .cmsg_len = CMSG_LEN(sizeof(int)),
+                                .cmsg_level = SOL_SOCKET,
+                                .cmsg_type = SCM_RIGHTS,
+
+                            }};
+
+  struct msghdr message = {.msg_control = control_msg.buf,
+                           .msg_controllen = sizeof(control_msg.buf),
+                           .msg_flags = 0,
+                           .msg_iov = &iov,
+                           .msg_iovlen = 1,
+                           .msg_name = NULL,
+                           .msg_namelen = 0};
+
+  memcpy(CMSG_DATA(&control_msg.hdr), &fd, sizeof(int));
+
+  if (sendmsg(sockfd, &message, 0) == -1) { FATAL("sendmsg"); }
+
+}
+
+int seccomp_socket_recv(int sockfd) {
+
+  int           data;
+  struct iovec  iov = {.iov_base = &data, .iov_len = sizeof(data)};
+  union cmsg    control_msg = {0};
+  struct msghdr message = {.msg_control = control_msg.buf,
+                           .msg_controllen = sizeof(control_msg.buf),
+                           .msg_flags = 0,
+                           .msg_iov = &iov,
+                           .msg_iovlen = 1,
+                           .msg_name = NULL,
+                           .msg_namelen = 0};
+
+  int fd;
+
+  if (recvmsg(sockfd, &message, 0) < 0) { FATAL("recvmsg"); }
+
+  if (control_msg.hdr.cmsg_len != CMSG_LEN(sizeof(int))) {
+
+    FATAL("control_msg.hdr.cmsg_len");
+
+  }
+
+  if (control_msg.hdr.cmsg_level != SOL_SOCKET) {
+
+    FATAL("control_msg.hdr.cmsg_level");
+
+  }
+
+  if (control_msg.hdr.cmsg_type != SCM_RIGHTS) {
+
+    FATAL("control_msg.hdr.cmsg_type");
+
+  }
+
+  memcpy(&fd, CMSG_DATA(&control_msg.hdr), sizeof(int));
+
+  return fd;
+
+}
+
diff --git a/frida_mode/src/seccomp/seccomp_syscall.c b/frida_mode/src/seccomp/seccomp_syscall.c
new file mode 100644
index 00000000..b2c084c8
--- /dev/null
+++ b/frida_mode/src/seccomp/seccomp_syscall.c
@@ -0,0 +1,335 @@
+#include <limits.h>
+#include <stdio.h>
+
+#include "debug.h"
+
+#include "seccomp.h"
+
+typedef struct {
+
+  int  id;
+  char name[PATH_MAX];
+
+} syscall_entry_t;
+
+static syscall_entry_t seccomp_syscall_table[] = {
+
+    {SYS_READ, "SYS_READ"},
+    {SYS_WRITE, "SYS_WRITE"},
+    {SYS_OPEN, "SYS_OPEN"},
+    {SYS_CLOSE, "SYS_CLOSE"},
+    {SYS_STAT, "SYS_STAT"},
+    {SYS_FSTAT, "SYS_FSTAT"},
+    {SYS_LSTAT, "SYS_LSTAT"},
+    {SYS_POLL, "SYS_POLL"},
+    {SYS_LSEEK, "SYS_LSEEK"},
+    {SYS_MMAP, "SYS_MMAP"},
+    {SYS_MPROTECT, "SYS_MPROTECT"},
+    {SYS_MUNMAP, "SYS_MUNMAP"},
+    {SYS_BRK, "SYS_BRK"},
+    {SYS_RT_SIGACTION, "SYS_RT_SIGACTION"},
+    {SYS_RT_SIGPROCMASK, "SYS_RT_SIGPROCMASK"},
+    {SYS_RT_SIGRETURN, "SYS_RT_SIGRETURN"},
+    {SYS_IOCTL, "SYS_IOCTL"},
+    {SYS_PREAD64, "SYS_PREAD64"},
+    {SYS_PWRITE64, "SYS_PWRITE64"},
+    {SYS_READV, "SYS_READV"},
+    {SYS_WRITEV, "SYS_WRITEV"},
+    {SYS_ACCESS, "SYS_ACCESS"},
+    {SYS_PIPE, "SYS_PIPE"},
+    {SYS_SELECT, "SYS_SELECT"},
+    {SYS_SCHED_YIELD, "SYS_SCHED_YIELD"},
+    {SYS_MREMAP, "SYS_MREMAP"},
+    {SYS_MSYNC, "SYS_MSYNC"},
+    {SYS_MINCORE, "SYS_MINCORE"},
+    {SYS_MADVISE, "SYS_MADVISE"},
+    {SYS_SHMGET, "SYS_SHMGET"},
+    {SYS_SHMAT, "SYS_SHMAT"},
+    {SYS_SHMCTL, "SYS_SHMCTL"},
+    {SYS_DUP, "SYS_DUP"},
+    {SYS_DUP2, "SYS_DUP2"},
+    {SYS_PAUSE, "SYS_PAUSE"},
+    {SYS_NANOSLEEP, "SYS_NANOSLEEP"},
+    {SYS_GETITIMER, "SYS_GETITIMER"},
+    {SYS_ALARM, "SYS_ALARM"},
+    {SYS_SETITIMER, "SYS_SETITIMER"},
+    {SYS_GETPID, "SYS_GETPID"},
+    {SYS_SENDFILE, "SYS_SENDFILE"},
+    {SYS_SOCKET, "SYS_SOCKET"},
+    {SYS_CONNECT, "SYS_CONNECT"},
+    {SYS_ACCEPT, "SYS_ACCEPT"},
+    {SYS_SENDTO, "SYS_SENDTO"},
+    {SYS_RECVFROM, "SYS_RECVFROM"},
+    {SYS_SENDMSG, "SYS_SENDMSG"},
+    {SYS_RECVMSG, "SYS_RECVMSG"},
+    {SYS_SHUTDOWN, "SYS_SHUTDOWN"},
+    {SYS_BIND, "SYS_BIND"},
+    {SYS_LISTEN, "SYS_LISTEN"},
+    {SYS_GETSOCKNAME, "SYS_GETSOCKNAME"},
+    {SYS_GETPEERNAME, "SYS_GETPEERNAME"},
+    {SYS_SOCKETPAIR, "SYS_SOCKETPAIR"},
+    {SYS_SETSOCKOPT, "SYS_SETSOCKOPT"},
+    {SYS_GETSOCKOPT, "SYS_GETSOCKOPT"},
+    {SYS_CLONE, "SYS_CLONE"},
+    {SYS_FORK, "SYS_FORK"},
+    {SYS_VFORK, "SYS_VFORK"},
+    {SYS_EXECVE, "SYS_EXECVE"},
+    {SYS_EXIT, "SYS_EXIT"},
+    {SYS_WAIT4, "SYS_WAIT4"},
+    {SYS_KILL, "SYS_KILL"},
+    {SYS_UNAME, "SYS_UNAME"},
+    {SYS_SEMGET, "SYS_SEMGET"},
+    {SYS_SEMOP, "SYS_SEMOP"},
+    {SYS_SEMCTL, "SYS_SEMCTL"},
+    {SYS_SHMDT, "SYS_SHMDT"},
+    {SYS_MSGGET, "SYS_MSGGET"},
+    {SYS_MSGSND, "SYS_MSGSND"},
+    {SYS_MSGRCV, "SYS_MSGRCV"},
+    {SYS_MSGCTL, "SYS_MSGCTL"},
+    {SYS_FCNTL, "SYS_FCNTL"},
+    {SYS_FLOCK, "SYS_FLOCK"},
+    {SYS_FSYNC, "SYS_FSYNC"},
+    {SYS_FDATASYNC, "SYS_FDATASYNC"},
+    {SYS_TRUNCATE, "SYS_TRUNCATE"},
+    {SYS_FTRUNCATE, "SYS_FTRUNCATE"},
+    {SYS_GETDENTS, "SYS_GETDENTS"},
+    {SYS_GETCWD, "SYS_GETCWD"},
+    {SYS_CHDIR, "SYS_CHDIR"},
+    {SYS_FCHDIR, "SYS_FCHDIR"},
+    {SYS_RENAME, "SYS_RENAME"},
+    {SYS_MKDIR, "SYS_MKDIR"},
+    {SYS_RMDIR, "SYS_RMDIR"},
+    {SYS_CREAT, "SYS_CREAT"},
+    {SYS_LINK, "SYS_LINK"},
+    {SYS_UNLINK, "SYS_UNLINK"},
+    {SYS_SYMLINK, "SYS_SYMLINK"},
+    {SYS_READLINK, "SYS_READLINK"},
+    {SYS_CHMOD, "SYS_CHMOD"},
+    {SYS_FCHMOD, "SYS_FCHMOD"},
+    {SYS_CHOWN, "SYS_CHOWN"},
+    {SYS_FCHOWN, "SYS_FCHOWN"},
+    {SYS_LCHOWN, "SYS_LCHOWN"},
+    {SYS_UMASK, "SYS_UMASK"},
+    {SYS_GETTIMEOFDAY, "SYS_GETTIMEOFDAY"},
+    {SYS_GETRLIMIT, "SYS_GETRLIMIT"},
+    {SYS_GETRUSAGE, "SYS_GETRUSAGE"},
+    {SYS_SYSINFO, "SYS_SYSINFO"},
+    {SYS_TIMES, "SYS_TIMES"},
+    {SYS_PTRACE, "SYS_PTRACE"},
+    {SYS_GETUID, "SYS_GETUID"},
+    {SYS_SYSLOG, "SYS_SYSLOG"},
+    {SYS_GETGID, "SYS_GETGID"},
+    {SYS_SETUID, "SYS_SETUID"},
+    {SYS_SETGID, "SYS_SETGID"},
+    {SYS_GETEUID, "SYS_GETEUID"},
+    {SYS_GETEGID, "SYS_GETEGID"},
+    {SYS_SETPGID, "SYS_SETPGID"},
+    {SYS_GETPPID, "SYS_GETPPID"},
+    {SYS_GETPGRP, "SYS_GETPGRP"},
+    {SYS_SETSID, "SYS_SETSID"},
+    {SYS_SETREUID, "SYS_SETREUID"},
+    {SYS_SETREGID, "SYS_SETREGID"},
+    {SYS_GETGROUPS, "SYS_GETGROUPS"},
+    {SYS_SETGROUPS, "SYS_SETGROUPS"},
+    {SYS_SETRESUID, "SYS_SETRESUID"},
+    {SYS_GETRESUID, "SYS_GETRESUID"},
+    {SYS_SETRESGID, "SYS_SETRESGID"},
+    {SYS_GETRESGID, "SYS_GETRESGID"},
+    {SYS_GETPGID, "SYS_GETPGID"},
+    {SYS_SETFSUID, "SYS_SETFSUID"},
+    {SYS_SETFSGID, "SYS_SETFSGID"},
+    {SYS_GETSID, "SYS_GETSID"},
+    {SYS_CAPGET, "SYS_CAPGET"},
+    {SYS_CAPSET, "SYS_CAPSET"},
+    {SYS_RT_SIGPENDING, "SYS_RT_SIGPENDING"},
+    {SYS_RT_SIGTIMEDWAIT, "SYS_RT_SIGTIMEDWAIT"},
+    {SYS_RT_SIGQUEUEINFO, "SYS_RT_SIGQUEUEINFO"},
+    {SYS_RT_SIGSUSPEND, "SYS_RT_SIGSUSPEND"},
+    {SYS_SIGALTSTACK, "SYS_SIGALTSTACK"},
+    {SYS_UTIME, "SYS_UTIME"},
+    {SYS_MKNOD, "SYS_MKNOD"},
+    {SYS_USELIB, "SYS_USELIB"},
+    {SYS_PERSONALITY, "SYS_PERSONALITY"},
+    {SYS_USTAT, "SYS_USTAT"},
+    {SYS_STATFS, "SYS_STATFS"},
+    {SYS_FSTATFS, "SYS_FSTATFS"},
+    {SYS_SYSFS, "SYS_SYSFS"},
+    {SYS_GETPRIORITY, "SYS_GETPRIORITY"},
+    {SYS_SETPRIORITY, "SYS_SETPRIORITY"},
+    {SYS_SCHED_SETPARAM, "SYS_SCHED_SETPARAM"},
+    {SYS_SCHED_GETPARAM, "SYS_SCHED_GETPARAM"},
+    {SYS_SCHED_SETSCHEDULER, "SYS_SCHED_SETSCHEDULER"},
+    {SYS_SCHED_GETSCHEDULER, "SYS_SCHED_GETSCHEDULER"},
+    {SYS_SCHED_GET_PRIORITY_MAX, "SYS_SCHED_GET_PRIORITY_MAX"},
+    {SYS_SCHED_GET_PRIORITY_MIN, "SYS_SCHED_GET_PRIORITY_MIN"},
+    {SYS_SCHED_RR_GET_INTERVAL, "SYS_SCHED_RR_GET_INTERVAL"},
+    {SYS_MLOCK, "SYS_MLOCK"},
+    {SYS_MUNLOCK, "SYS_MUNLOCK"},
+    {SYS_MLOCKALL, "SYS_MLOCKALL"},
+    {SYS_MUNLOCKALL, "SYS_MUNLOCKALL"},
+    {SYS_VHANGUP, "SYS_VHANGUP"},
+    {SYS_MODIFY_LDT, "SYS_MODIFY_LDT"},
+    {SYS_PIVOT_ROOT, "SYS_PIVOT_ROOT"},
+    {SYS__SYSCTL, "SYS__SYSCTL"},
+    {SYS_PRCTL, "SYS_PRCTL"},
+    {SYS_ARCH_PRCTL, "SYS_ARCH_PRCTL"},
+    {SYS_ADJTIMEX, "SYS_ADJTIMEX"},
+    {SYS_SETRLIMIT, "SYS_SETRLIMIT"},
+    {SYS_CHROOT, "SYS_CHROOT"},
+    {SYS_SYNC, "SYS_SYNC"},
+    {SYS_ACCT, "SYS_ACCT"},
+    {SYS_SETTIMEOFDAY, "SYS_SETTIMEOFDAY"},
+    {SYS_MOUNT, "SYS_MOUNT"},
+    {SYS_UMOUNT2, "SYS_UMOUNT2"},
+    {SYS_SWAPON, "SYS_SWAPON"},
+    {SYS_SWAPOFF, "SYS_SWAPOFF"},
+    {SYS_REBOOT, "SYS_REBOOT"},
+    {SYS_SETHOSTNAME, "SYS_SETHOSTNAME"},
+    {SYS_SETDOMAINNAME, "SYS_SETDOMAINNAME"},
+    {SYS_IOPL, "SYS_IOPL"},
+    {SYS_IOPERM, "SYS_IOPERM"},
+    {SYS_CREATE_MODULE, "SYS_CREATE_MODULE"},
+    {SYS_INIT_MODULE, "SYS_INIT_MODULE"},
+    {SYS_DELETE_MODULE, "SYS_DELETE_MODULE"},
+    {SYS_GET_KERNEL_SYMS, "SYS_GET_KERNEL_SYMS"},
+    {SYS_QUERY_MODULE, "SYS_QUERY_MODULE"},
+    {SYS_QUOTACTL, "SYS_QUOTACTL"},
+    {SYS_NFSSERVCTL, "SYS_NFSSERVCTL"},
+    {SYS_GETPMSG, "SYS_GETPMSG"},
+    {SYS_PUTPMSG, "SYS_PUTPMSG"},
+    {SYS_AFS_SYSCALL, "SYS_AFS_SYSCALL"},
+    {SYS_TUXCALL, "SYS_TUXCALL"},
+    {SYS_SECURITY, "SYS_SECURITY"},
+    {SYS_GETTID, "SYS_GETTID"},
+    {SYS_READAHEAD, "SYS_READAHEAD"},
+    {SYS_SETXATTR, "SYS_SETXATTR"},
+    {SYS_LSETXATTR, "SYS_LSETXATTR"},
+    {SYS_FSETXATTR, "SYS_FSETXATTR"},
+    {SYS_GETXATTR, "SYS_GETXATTR"},
+    {SYS_LGETXATTR, "SYS_LGETXATTR"},
+    {SYS_FGETXATTR, "SYS_FGETXATTR"},
+    {SYS_LISTXATTR, "SYS_LISTXATTR"},
+    {SYS_LLISTXATTR, "SYS_LLISTXATTR"},
+    {SYS_FLISTXATTR, "SYS_FLISTXATTR"},
+    {SYS_REMOVEXATTR, "SYS_REMOVEXATTR"},
+    {SYS_LREMOVEXATTR, "SYS_LREMOVEXATTR"},
+    {SYS_FREMOVEXATTR, "SYS_FREMOVEXATTR"},
+    {SYS_TKILL, "SYS_TKILL"},
+    {SYS_TIME, "SYS_TIME"},
+    {SYS_FUTEX, "SYS_FUTEX"},
+    {SYS_SCHED_SETAFFINITY, "SYS_SCHED_SETAFFINITY"},
+    {SYS_SCHED_GETAFFINITY, "SYS_SCHED_GETAFFINITY"},
+    {SYS_SET_THREAD_AREA, "SYS_SET_THREAD_AREA"},
+    {SYS_IO_SETUP, "SYS_IO_SETUP"},
+    {SYS_IO_DESTROY, "SYS_IO_DESTROY"},
+    {SYS_IO_GETEVENTS, "SYS_IO_GETEVENTS"},
+    {SYS_IO_SUBMIT, "SYS_IO_SUBMIT"},
+    {SYS_IO_CANCEL, "SYS_IO_CANCEL"},
+    {SYS_GET_THREAD_AREA, "SYS_GET_THREAD_AREA"},
+    {SYS_LOOKUP_DCOOKIE, "SYS_LOOKUP_DCOOKIE"},
+    {SYS_EPOLL_CREATE, "SYS_EPOLL_CREATE"},
+    {SYS_EPOLL_CTL_OLD, "SYS_EPOLL_CTL_OLD"},
+    {SYS_EPOLL_WAIT_OLD, "SYS_EPOLL_WAIT_OLD"},
+    {SYS_REMAP_FILE_PAGES, "SYS_REMAP_FILE_PAGES"},
+    {SYS_GETDENTS64, "SYS_GETDENTS64"},
+    {SYS_SET_TID_ADDRESS, "SYS_SET_TID_ADDRESS"},
+    {SYS_RESTART_SYSCALL, "SYS_RESTART_SYSCALL"},
+    {SYS_SEMTIMEDOP, "SYS_SEMTIMEDOP"},
+    {SYS_FADVISE64, "SYS_FADVISE64"},
+    {SYS_TIMER_CREATE, "SYS_TIMER_CREATE"},
+    {SYS_TIMER_SETTIME, "SYS_TIMER_SETTIME"},
+    {SYS_TIMER_GETTIME, "SYS_TIMER_GETTIME"},
+    {SYS_TIMER_GETOVERRUN, "SYS_TIMER_GETOVERRUN"},
+    {SYS_TIMER_DELETE, "SYS_TIMER_DELETE"},
+    {SYS_CLOCK_SETTIME, "SYS_CLOCK_SETTIME"},
+    {SYS_CLOCK_GETTIME, "SYS_CLOCK_GETTIME"},
+    {SYS_CLOCK_GETRES, "SYS_CLOCK_GETRES"},
+    {SYS_CLOCK_NANOSLEEP, "SYS_CLOCK_NANOSLEEP"},
+    {SYS_EXIT_GROUP, "SYS_EXIT_GROUP"},
+    {SYS_EPOLL_WAIT, "SYS_EPOLL_WAIT"},
+    {SYS_EPOLL_CTL, "SYS_EPOLL_CTL"},
+    {SYS_TGKILL, "SYS_TGKILL"},
+    {SYS_UTIMES, "SYS_UTIMES"},
+    {SYS_VSERVER, "SYS_VSERVER"},
+    {SYS_MBIND, "SYS_MBIND"},
+    {SYS_SET_MEMPOLICY, "SYS_SET_MEMPOLICY"},
+    {SYS_GET_MEMPOLICY, "SYS_GET_MEMPOLICY"},
+    {SYS_MQ_OPEN, "SYS_MQ_OPEN"},
+    {SYS_MQ_UNLINK, "SYS_MQ_UNLINK"},
+    {SYS_MQ_TIMEDSEND, "SYS_MQ_TIMEDSEND"},
+    {SYS_MQ_TIMEDRECEIVE, "SYS_MQ_TIMEDRECEIVE"},
+    {SYS_MQ_NOTIFY, "SYS_MQ_NOTIFY"},
+    {SYS_MQ_GETSETATTR, "SYS_MQ_GETSETATTR"},
+    {SYS_KEXEC_LOAD, "SYS_KEXEC_LOAD"},
+    {SYS_WAITID, "SYS_WAITID"},
+    {SYS_ADD_KEY, "SYS_ADD_KEY"},
+    {SYS_REQUEST_KEY, "SYS_REQUEST_KEY"},
+    {SYS_KEYCTL, "SYS_KEYCTL"},
+    {SYS_IOPRIO_SET, "SYS_IOPRIO_SET"},
+    {SYS_IOPRIO_GET, "SYS_IOPRIO_GET"},
+    {SYS_INOTIFY_INIT, "SYS_INOTIFY_INIT"},
+    {SYS_INOTIFY_ADD_WATCH, "SYS_INOTIFY_ADD_WATCH"},
+    {SYS_INOTIFY_RM_WATCH, "SYS_INOTIFY_RM_WATCH"},
+    {SYS_MIGRATE_PAGES, "SYS_MIGRATE_PAGES"},
+    {SYS_OPENAT, "SYS_OPENAT"},
+    {SYS_MKDIRAT, "SYS_MKDIRAT"},
+    {SYS_MKNODAT, "SYS_MKNODAT"},
+    {SYS_FCHOWNAT, "SYS_FCHOWNAT"},
+    {SYS_FUTIMESAT, "SYS_FUTIMESAT"},
+    {SYS_NEWFSTATAT, "SYS_NEWFSTATAT"},
+    {SYS_UNLINKAT, "SYS_UNLINKAT"},
+    {SYS_RENAMEAT, "SYS_RENAMEAT"},
+    {SYS_LINKAT, "SYS_LINKAT"},
+    {SYS_SYMLINKAT, "SYS_SYMLINKAT"},
+    {SYS_READLINKAT, "SYS_READLINKAT"},
+    {SYS_FCHMODAT, "SYS_FCHMODAT"},
+    {SYS_FACCESSAT, "SYS_FACCESSAT"},
+    {SYS_PSELECT6, "SYS_PSELECT6"},
+    {SYS_PPOLL, "SYS_PPOLL"},
+    {SYS_UNSHARE, "SYS_UNSHARE"},
+    {SYS_SET_ROBUST_LIST, "SYS_SET_ROBUST_LIST"},
+    {SYS_GET_ROBUST_LIST, "SYS_GET_ROBUST_LIST"},
+    {SYS_SPLICE, "SYS_SPLICE"},
+    {SYS_TEE, "SYS_TEE"},
+    {SYS_SYNC_FILE_RANGE, "SYS_SYNC_FILE_RANGE"},
+    {SYS_VMSPLICE, "SYS_VMSPLICE"},
+    {SYS_MOVE_PAGES, "SYS_MOVE_PAGES"},
+    {SYS_UTIMENSAT, "SYS_UTIMENSAT"},
+    {SYS_EPOLL_PWAIT, "SYS_EPOLL_PWAIT"},
+    {SYS_SIGNALFD, "SYS_SIGNALFD"},
+    {SYS_TIMERFD_CREATE, "SYS_TIMERFD_CREATE"},
+    {SYS_EVENTFD, "SYS_EVENTFD"},
+    {SYS_FALLOCATE, "SYS_FALLOCATE"},
+    {SYS_TIMERFD_SETTIME, "SYS_TIMERFD_SETTIME"},
+    {SYS_TIMERFD_GETTIME, "SYS_TIMERFD_GETTIME"},
+    {SYS_ACCEPT4, "SYS_ACCEPT4"},
+    {SYS_SIGNALFD4, "SYS_SIGNALFD4"},
+    {SYS_EVENTFD2, "SYS_EVENTFD2"},
+    {SYS_EPOLL_CREATE1, "SYS_EPOLL_CREATE1"},
+    {SYS_DUP3, "SYS_DUP3"},
+    {SYS_PIPE2, "SYS_PIPE2"},
+    {SYS_INOTIFY_INIT1, "SYS_INOTIFY_INIT1"},
+    {SYS_PREADV, "SYS_PREADV"},
+    {SYS_PWRITEV, "SYS_PWRITEV"},
+    {SYS_RT_TGSIGQUEUEINFO, "SYS_RT_TGSIGQUEUEINFO"},
+    {SYS_PERF_EVENT_OPEN, "SYS_PERF_EVENT_OPEN"},
+    {SYS_RECVMMSG, "SYS_RECVMMSG"},
+    {SYS_FANOTIFY_INIT, "SYS_FANOTIFY_INIT"},
+    {SYS_FANOTIFY_MARK, "SYS_FANOTIFY_MARK"},
+    {SYS_PRLIMIT64, "SYS_PRLIMIT64"},
+
+};
+
+char *seccomp_syscall_lookup(int id) {
+
+  if (id < 0) { FATAL("Invalid id: %d", id); }
+  if ((uint32_t)id >= sizeof(seccomp_syscall_table) / sizeof(syscall_entry_t)) {
+
+    FATAL("Invalid id: %d", id);
+
+  }
+
+  return seccomp_syscall_table[id].name;
+
+}
+