about summary refs log tree commit diff
path: root/nixpkgs/pkgs/tools/security/afl
diff options
context:
space:
mode:
Diffstat (limited to 'nixpkgs/pkgs/tools/security/afl')
-rw-r--r--nixpkgs/pkgs/tools/security/afl/README.md19
-rw-r--r--nixpkgs/pkgs/tools/security/afl/default.nix82
-rw-r--r--nixpkgs/pkgs/tools/security/afl/libdislocator.nix34
-rw-r--r--nixpkgs/pkgs/tools/security/afl/qemu-patches/no-etc-install.patch13
-rw-r--r--nixpkgs/pkgs/tools/security/afl/qemu-patches/syscall-glibc2_30.diff51
-rw-r--r--nixpkgs/pkgs/tools/security/afl/qemu.nix79
6 files changed, 278 insertions, 0 deletions
diff --git a/nixpkgs/pkgs/tools/security/afl/README.md b/nixpkgs/pkgs/tools/security/afl/README.md
new file mode 100644
index 000000000000..180cad6bc4ca
--- /dev/null
+++ b/nixpkgs/pkgs/tools/security/afl/README.md
@@ -0,0 +1,19 @@
+Updating the QEMU patches
+=========================
+
+When updating to the latest American Fuzzy Lop, make sure to check for
+any new patches to qemu for binary fuzzing support:
+
+https://github.com/google/AFL/tree/master/qemu_mode
+
+Be sure to check the build script and make sure it's also using the
+right QEMU version and options in `qemu.nix`:
+
+https://github.com/google/AFL/blob/master/qemu_mode/build_qemu_support.sh
+
+`afl-config.h`, `afl-types.h`, and `afl-qemu-cpu-inl.h` are part of
+the afl source code, and copied from `config.h`, `types.h` and
+`afl-qemu-cpu-inl.h` appropriately. These files and the QEMU patches
+need to be slightly adjusted to fix their `#include`s (the patches
+try to otherwise include files like `../../config.h` which causes the
+build to fail).
diff --git a/nixpkgs/pkgs/tools/security/afl/default.nix b/nixpkgs/pkgs/tools/security/afl/default.nix
new file mode 100644
index 000000000000..ccdbd78716d9
--- /dev/null
+++ b/nixpkgs/pkgs/tools/security/afl/default.nix
@@ -0,0 +1,82 @@
+{ lib, stdenv, fetchFromGitHub, callPackage, makeWrapper
+, clang, llvm, which, libcgroup
+}:
+
+let
+  afl-qemu = callPackage ./qemu.nix { inherit afl; };
+  qemu-exe-name = if stdenv.hostPlatform.system == "x86_64-linux" then "qemu-x86_64"
+    else if stdenv.hostPlatform.system == "i686-linux" then "qemu-i386"
+    else throw "afl: no support for ${stdenv.hostPlatform.system}!";
+  afl = stdenv.mkDerivation rec {
+    pname = "afl";
+    version = "2.57b";
+
+    src = fetchFromGitHub {
+      owner = "google";
+      repo = pname;
+      rev = "v${version}";
+      sha256 = "0fqj3g6ds1f21kxz7m9mc1fspi9r4jg9jcmi60inwxijrc5ncvr6";
+    };
+    enableParallelBuilding = true;
+
+    # Note: libcgroup isn't needed for building, just for the afl-cgroup
+    # script.
+    nativeBuildInputs = [ makeWrapper which llvm.dev ];
+    buildInputs = [ llvm ];
+
+    makeFlags = [ "PREFIX=$(out)" ];
+    postBuild = ''
+      make -C llvm_mode $makeFlags -j$NIX_BUILD_CORES
+    '';
+    postInstall = ''
+      # Install the custom QEMU emulator for binary blob fuzzing.
+      cp ${afl-qemu}/bin/${qemu-exe-name} $out/bin/afl-qemu-trace
+
+      # Install the cgroups wrapper for asan-based fuzzing.
+      cp experimental/asan_cgroups/limit_memory.sh $out/bin/afl-cgroup
+      chmod +x $out/bin/afl-cgroup
+      substituteInPlace $out/bin/afl-cgroup \
+        --replace "cgcreate" "${libcgroup}/bin/cgcreate" \
+        --replace "cgexec"   "${libcgroup}/bin/cgexec" \
+        --replace "cgdelete" "${libcgroup}/bin/cgdelete"
+
+      # Patch shebangs before wrapping
+      patchShebangs $out/bin
+
+      # Wrap afl-clang-fast(++) with a *different* AFL_PATH, because it
+      # has totally different semantics in that case(?) - and also set a
+      # proper AFL_CC and AFL_CXX so we don't pick up the wrong one out
+      # of $PATH.
+      # first though we need to replace the afl-clang-fast++ symlink with
+      # a real copy to prevent wrapProgram skipping the symlink and confusing
+      # nix's cc wrapper
+      rm $out/bin/afl-clang-fast++
+      cp $out/bin/afl-clang-fast $out/bin/afl-clang-fast++
+      for x in $out/bin/afl-clang-fast $out/bin/afl-clang-fast++; do
+        wrapProgram $x \
+          --prefix AFL_PATH : "$out/lib/afl" \
+          --run 'export AFL_CC=''${AFL_CC:-${clang}/bin/clang} AFL_CXX=''${AFL_CXX:-${clang}/bin/clang++}'
+      done
+    '';
+
+    passthru.qemu = afl-qemu;
+
+    meta = {
+      description = "Powerful fuzzer via genetic algorithms and instrumentation";
+      longDescription = ''
+        American fuzzy lop is a fuzzer that employs a novel type of
+        compile-time instrumentation and genetic algorithms to
+        automatically discover clean, interesting test cases that
+        trigger new internal states in the targeted binary. This
+        substantially improves the functional coverage for the fuzzed
+        code. The compact synthesized corpora produced by the tool are
+        also useful for seeding other, more labor or resource-intensive
+        testing regimes down the road.
+      '';
+      homepage    = "https://lcamtuf.coredump.cx/afl/";
+      license     = lib.licenses.asl20;
+      platforms   = ["x86_64-linux" "i686-linux"];
+      maintainers = with lib.maintainers; [ thoughtpolice ris ];
+    };
+  };
+in afl
diff --git a/nixpkgs/pkgs/tools/security/afl/libdislocator.nix b/nixpkgs/pkgs/tools/security/afl/libdislocator.nix
new file mode 100644
index 000000000000..400464c00567
--- /dev/null
+++ b/nixpkgs/pkgs/tools/security/afl/libdislocator.nix
@@ -0,0 +1,34 @@
+{ lib, stdenv, afl}:
+
+stdenv.mkDerivation {
+  version = lib.getVersion afl;
+  pname = "libdislocator";
+
+  src = afl.src;
+  sourceRoot = "${afl.src.name}/libdislocator";
+
+  makeFlags = [ "PREFIX=$(out)" ];
+
+  preInstall = ''
+    mkdir -p $out/lib/afl
+  '';
+  postInstall = ''
+    mkdir $out/bin
+    cat > $out/bin/get-libdislocator-so <<END
+    #!${stdenv.shell}
+    echo $out/lib/afl/libdislocator.so
+    END
+    chmod +x $out/bin/get-libdislocator-so
+  '';
+
+  meta = with lib; {
+    homepage = "https://lcamtuf.coredump.cx/afl/";
+    description = ''
+      Drop-in replacement for the libc allocator which improves
+      the odds of bumping into heap-related security bugs in
+      several ways.
+    '';
+    license = lib.licenses.asl20;
+    maintainers = with maintainers; [ ris ];
+  };
+}
diff --git a/nixpkgs/pkgs/tools/security/afl/qemu-patches/no-etc-install.patch b/nixpkgs/pkgs/tools/security/afl/qemu-patches/no-etc-install.patch
new file mode 100644
index 000000000000..5dfbfd780f1c
--- /dev/null
+++ b/nixpkgs/pkgs/tools/security/afl/qemu-patches/no-etc-install.patch
@@ -0,0 +1,13 @@
+diff --git a/Makefile b/Makefile
+index d6b9dc1..ce7c493 100644
+--- a/Makefile
++++ b/Makefile
+@@ -601,7 +601,7 @@ install-localstatedir:
+ endif
+ 
+ 
+-install: all $(if $(BUILD_DOCS),install-doc) install-datadir install-localstatedir
++install: all $(if $(BUILD_DOCS),install-doc) install-datadir
+ ifneq ($(TOOLS),)
+ 	$(call install-prog,$(subst qemu-ga,qemu-ga$(EXESUF),$(TOOLS)),$(DESTDIR)$(bindir))
+ endif
diff --git a/nixpkgs/pkgs/tools/security/afl/qemu-patches/syscall-glibc2_30.diff b/nixpkgs/pkgs/tools/security/afl/qemu-patches/syscall-glibc2_30.diff
new file mode 100644
index 000000000000..aa2950bf157c
--- /dev/null
+++ b/nixpkgs/pkgs/tools/security/afl/qemu-patches/syscall-glibc2_30.diff
@@ -0,0 +1,51 @@
+--- qemu-2.10.0-clean/linux-user/syscall.c	2020-03-12 18:47:47.898592169 +0100
++++ qemu-2.10.0/linux-user/syscall.c	2020-03-13 09:13:42.461809699 +0100
+@@ -34,6 +34,7 @@
+ #include <sys/resource.h>
+ #include <sys/swap.h>
+ #include <linux/capability.h>
++#include <linux/sockios.h> // https://lkml.org/lkml/2019/6/3/988
+ #include <sched.h>
+ #include <sys/timex.h>
+ #ifdef __ia64__
+@@ -256,7 +257,9 @@ static type name (type1 arg1,type2 arg2,
+ #endif
+ 
+ #ifdef __NR_gettid
+-_syscall0(int, gettid)
++// taken from https://patchwork.kernel.org/patch/10862231/
++#define __NR_sys_gettid __NR_gettid
++_syscall0(int, sys_gettid)
+ #else
+ /* This is a replacement for the host gettid() and must return a host
+    errno. */
+@@ -6219,7 +6222,7 @@ static void *clone_func(void *arg)
+     cpu = ENV_GET_CPU(env);
+     thread_cpu = cpu;
+     ts = (TaskState *)cpu->opaque;
+-    info->tid = gettid();
++    info->tid = sys_gettid();
+     task_settid(ts);
+     if (info->child_tidptr)
+         put_user_u32(info->tid, info->child_tidptr);
+@@ -6363,9 +6366,9 @@ static int do_fork(CPUArchState *env, un
+                mapping.  We can't repeat the spinlock hack used above because
+                the child process gets its own copy of the lock.  */
+             if (flags & CLONE_CHILD_SETTID)
+-                put_user_u32(gettid(), child_tidptr);
++                put_user_u32(sys_gettid(), child_tidptr);
+             if (flags & CLONE_PARENT_SETTID)
+-                put_user_u32(gettid(), parent_tidptr);
++                put_user_u32(sys_gettid(), parent_tidptr);
+             ts = (TaskState *)cpu->opaque;
+             if (flags & CLONE_SETTLS)
+                 cpu_set_tls (env, newtls);
+@@ -11402,7 +11405,7 @@ abi_long do_syscall(void *cpu_env, int n
+         break;
+ #endif
+     case TARGET_NR_gettid:
+-        ret = get_errno(gettid());
++        ret = get_errno(sys_gettid());
+         break;
+ #ifdef TARGET_NR_readahead
+     case TARGET_NR_readahead:
diff --git a/nixpkgs/pkgs/tools/security/afl/qemu.nix b/nixpkgs/pkgs/tools/security/afl/qemu.nix
new file mode 100644
index 000000000000..e33c4c2fb03a
--- /dev/null
+++ b/nixpkgs/pkgs/tools/security/afl/qemu.nix
@@ -0,0 +1,79 @@
+{ lib, stdenv, fetchurl, afl, python2, zlib, pkg-config, glib, perl
+, texinfo, libuuid, flex, bison, pixman, autoconf
+}:
+
+with lib;
+
+let
+  cpuTarget = if stdenv.hostPlatform.system == "x86_64-linux" then "x86_64-linux-user"
+    else if stdenv.hostPlatform.system == "i686-linux" then "i386-linux-user"
+    else throw "afl: no support for ${stdenv.hostPlatform.system}!";
+in
+stdenv.mkDerivation rec {
+  pname = "afl-qemu";
+  version = "2.10.0";
+
+  srcs = [
+    (fetchurl {
+      url = "http://wiki.qemu.org/download/qemu-${version}.tar.bz2";
+      sha256 = "0j3dfxzrzdp1w21k21fjvmakzc6lcha1rsclaicwqvbf63hkk7vy";
+    })
+    afl.src
+  ];
+
+  sourceRoot = "qemu-${version}";
+
+  postUnpack = ''
+    cp ${afl.src.name}/types.h $sourceRoot/afl-types.h
+    substitute ${afl.src.name}/config.h $sourceRoot/afl-config.h \
+      --replace "types.h" "afl-types.h"
+    substitute ${afl.src.name}/qemu_mode/patches/afl-qemu-cpu-inl.h $sourceRoot/afl-qemu-cpu-inl.h \
+      --replace "../../config.h" "afl-config.h"
+    substituteInPlace ${afl.src.name}/qemu_mode/patches/cpu-exec.diff \
+      --replace "../patches/afl-qemu-cpu-inl.h" "afl-qemu-cpu-inl.h"
+  '';
+
+  nativeBuildInputs = [
+    python2 perl pkg-config flex bison autoconf texinfo
+  ];
+
+  buildInputs = [
+    zlib glib pixman libuuid
+  ];
+
+  enableParallelBuilding = true;
+
+  patches = [
+    # patches extracted from afl source
+    "../${afl.src.name}/qemu_mode/patches/cpu-exec.diff"
+    "../${afl.src.name}/qemu_mode/patches/elfload.diff"
+    "../${afl.src.name}/qemu_mode/patches/syscall.diff"
+    "../${afl.src.name}/qemu_mode/patches/configure.diff"
+    "../${afl.src.name}/qemu_mode/patches/memfd.diff"
+    # nix-specific patches to make installation more well-behaved
+    ./qemu-patches/no-etc-install.patch
+    # patch for fixing qemu build on glibc >= 2.30
+    ./qemu-patches/syscall-glibc2_30.diff
+  ];
+
+  configureFlags =
+    [ "--disable-system"
+      "--enable-linux-user"
+      "--disable-gtk"
+      "--disable-sdl"
+      "--disable-vnc"
+      "--disable-kvm"
+      "--target-list=${cpuTarget}"
+      "--enable-pie"
+      "--sysconfdir=/etc"
+      "--localstatedir=/var"
+    ];
+
+  meta = with lib; {
+    homepage = "http://www.qemu.org/";
+    description = "Fork of QEMU with AFL instrumentation support";
+    license = licenses.gpl2Plus;
+    maintainers = with maintainers; [ thoughtpolice ];
+    platforms = platforms.linux;
+  };
+}