about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--REUSE.toml2
-rw-r--r--loftix/emulation.scm64
-rw-r--r--loftix/fuzzing.scm55
-rw-r--r--patches/qemu-for-aflplusplus-casts.patch45
-rw-r--r--patches/qemu-for-aflplusplus-imported-headers.patch181
5 files changed, 296 insertions, 51 deletions
diff --git a/REUSE.toml b/REUSE.toml
index dafc565..74dcddc 100644
--- a/REUSE.toml
+++ b/REUSE.toml
@@ -170,6 +170,8 @@ path = [ 'patches/afl++-*.patch',
          'patches/fuzzolic-unbundle.patch',
          'patches/fuzzolic-utils-make.patch',
          'patches/jasper-no-define-int-types.patch',
+         'patches/qemu-for-aflplusplus-casts.patch',
+         'patches/qemu-for-aflplusplus-imported-headers.patch',
          'patches/qemu-for-fuzzolic-static-global.patch' ]
 SPDX-FileCopyrightText = 'Nguyễn Gia Phong'
 SPDX-License-Identifier = 'GPL-3.0-or-later'
diff --git a/loftix/emulation.scm b/loftix/emulation.scm
index 372428e..14b5dea 100644
--- a/loftix/emulation.scm
+++ b/loftix/emulation.scm
@@ -17,25 +17,27 @@
 
 (define-public qemu-for-aflplusplus
   (let ((base qemu-minimal)
-        (base-version "5.2.50")
-        (commit "790d2124fd054621d3c0d3ec31bea114b60601f9")
-        (revision "master"))
+        (commit "3babe948e64da063861c20583bda14b402c5c07a")
+        (revision "0"))
     (hidden-package
      (package
        (inherit base)
-       (synopsis "QEMU for AFL++")
-       (name "qemu-for-aflplusplus")
-       (version (git-version base-version revision commit))
-       (home-page "https://github.com/AFLplusplus/qemuafl")
+       (name "qemu")
+       (version (git-version "5.2.50" revision commit))
        (source
         (origin
           (method git-fetch)
-          (uri (git-reference (url home-page)
+          (uri (git-reference (url "https://github.com/AFLplusplus/qemuafl")
                               (commit commit)
                               (recursive? #t)))
           (file-name (git-file-name name version))
           (sha256
-           (base32 "1l2kl8768l4mbkiaj63zn6gsdn3qpl3rg7s6h62rmd7599ar3xn3"))))
+           (base32 "0k2mhwzi7wav6r0bgba3s154lrwm3s3fc1cl2fxz8z2fmj52iq69"))
+          (patches (search-patches
+                    ;; https://github.com/AFLplusplus/qemuafl/pull/79
+                    "patches/qemu-for-aflplusplus-casts.patch"
+                    ;; https://github.com/AFLplusplus/qemuafl/pull/78
+                    "patches/qemu-for-aflplusplus-imported-headers.patch"))))
        (arguments
         (substitute-keyword-arguments (package-arguments base)
           ((#:configure-flags _ #~'())
@@ -44,12 +46,13 @@
                     ;; AFL++ only supports using a single afl-qemu-trace,
                     ;; so we only build qemu for the native target.
                     (match #$(let-system system system)
-                      ("x86_64-linux"   "x86_64-linux-user")
-                      ("i686-linux"     "i386-linux-user")
                       ("aarch64-linux"  "aarch64-linux-user")
                       ("armhf-linux"    "arm-linux-user")
+                      ("i686-linux"     "i386-linux-user")
                       ("mips64el-linux" "mips64el-linux-user")
-                      ("powerpc-linux"  "ppc-linux-user")))))
+                      ("powerpc-linux"  "ppc-linux-user")
+                      ("riscv64-linux"  "riscv64-linux-user")
+                      ("x86_64-linux"   "x86_64-linux-user")))))
           ((#:phases phases)
            #~(modify-phases #$phases
                (delete 'replace-firmwares)
@@ -57,29 +60,28 @@
                (delete 'fix-optionrom-makefile)
                (delete 'disable-unusable-tests)
                (replace 'configure
-                 (lambda* (#:key outputs configure-flags
-                           #:allow-other-keys)
+                 (lambda* (#:key configure-flags #:allow-other-keys)
                    ;; The `configure' script doesn't understand some of the
                    ;; GNU options.  Thus, add a new phase that's compatible.
-                   (let ((out (assoc-ref outputs "out")))
-                     (setenv "SHELL" (which "bash"))
-                     ;; The binaries need to be linked against -lrt.
-                     (setenv "LDFLAGS" "-lrt")
-                     (apply invoke
-                            `("./configure"
-                              ,(string-append "--cc=" (which "gcc"))
-                              ;; Some architectures insist on using HOST_CC
-                              ,(string-append "--host-cc=" (which "gcc"))
-                              "--disable-debug-info" ; save build space
-                              ,(string-append "--prefix=" out)
-                              ,(string-append "--sysconfdir=/etc")
-                              ,@configure-flags)))))
+                   (setenv "SHELL" (which "bash"))
+                   ;; The binaries need to be linked against -lrt.
+                   (setenv "LDFLAGS" "-lrt")
+                   (apply invoke
+                          "./configure"
+                          (string-append "--cc=" #$(cc-for-target))
+                          ;; Some architectures insist on using HOST_CC
+                          (string-append "--host-cc=" #$(cc-for-target))
+                          "--disable-debug-info" ; save build space
+                          (string-append "--prefix=" #$output)
+                          (string-append "--sysconfdir=/etc")
+                          configure-flags)))
                (add-after 'install 'install-qasan-header
-                 (lambda* (#:key outputs #:allow-other-keys)
+                 (lambda _
                    (install-file "qemuafl/qasan.h"
-                                 (string-append (assoc-ref outputs "out")
-                                                "/include"))))
-               (delete 'delete-firmwares)))))))))
+                                 (string-append #$output "/include"))))
+               (delete 'delete-firmwares)))))
+       (home-page "https://github.com/AFLplusplus/qemuafl")
+       (synopsis "QEMU for AFL++")))))
 
 (define-public qemu-for-fuzzolic
   (let ((base qemu-minimal)
diff --git a/loftix/fuzzing.scm b/loftix/fuzzing.scm
index aea1a02..c9da958 100644
--- a/loftix/fuzzing.scm
+++ b/loftix/fuzzing.scm
@@ -30,26 +30,41 @@
   #:export (for-evocatio))
 
 (define-public afl++
-  (package
-    (inherit aflplusplus)
-    (name "afl++")
-    (arguments
-      (substitute-keyword-arguments (package-arguments aflplusplus)
-        ((#:phases phases)
-         #~(modify-phases #$phases
-             (add-after 'build 'build-qasan
-               (lambda* (#:key make-flags #:allow-other-keys)
-                 (apply invoke "make" "-C" "qemu_mode/libqasan" make-flags)))
-             ;; afl-qemu-trace is a symbolic link to QEMU's binary.
-             ;; Substituting its source code with AFL++'s output path
-             ;; would result in a dependency cycle.
-             (add-after 'install-qemu 'wrap-qemu
-               (lambda* (#:key outputs #:allow-other-keys)
-                 (let ((out (assoc-ref outputs "out")))
-                   (wrap-program (string-append out "/bin/afl-qemu-trace")
-                     `("AFL_PATH" = (,(string-append out "/lib/afl")))))))))))
-    (inputs (modify-inputs (package-inputs aflplusplus)
-              (replace "qemu" qemu-for-aflplusplus)))))
+  (let ((commit "93a6e1dbd19da92702dd7393d1cd1b405a6c29ee"))
+    (package
+      (inherit aflplusplus)
+      (name "afl++")
+      (version (git-version "4.35a" "0" commit))
+      (source
+       (origin
+         (method git-fetch)
+         (uri (git-reference
+               (url "https://github.com/AFLplusplus/AFLplusplus")
+               (commit commit)))
+         (file-name (git-file-name name version))
+         (sha256
+          (base32 "16b516f9xwxv61wzwbgw4wazx3jnhai3zlb0wpw3q0gdxcb7y61q"))))
+      (arguments
+       (substitute-keyword-arguments (package-arguments aflplusplus)
+         ((#:phases phases)
+          #~(modify-phases #$phases
+              (add-after 'build 'build-qasan
+                (lambda* (#:key parallel-build? make-flags #:allow-other-keys)
+                  (apply invoke "make" "-C" "qemu_mode/libqasan"
+                         "-j" (number->string (if parallel-build?
+                                                  (parallel-job-count)
+                                                  "1"))
+                         make-flags)))
+              ;; afl-qemu-trace is a symbolic link to QEMU's binary.
+              ;; Substituting its source code with AFL++'s output path
+              ;; would result in a dependency cycle.
+              (add-after 'install-qemu 'wrap-qemu
+                (lambda _
+                  (wrap-program (string-append #$output "/bin/afl-qemu-trace")
+                    `("AFL_PATH" =
+                      (,(string-append #$output "/lib/afl"))))))))))
+      (inputs (modify-inputs (package-inputs aflplusplus)
+                (replace "qemu" qemu-for-aflplusplus))))))
 
 (define-public afl-dyninst
   (package
diff --git a/patches/qemu-for-aflplusplus-casts.patch b/patches/qemu-for-aflplusplus-casts.patch
new file mode 100644
index 0000000..fee864d
--- /dev/null
+++ b/patches/qemu-for-aflplusplus-casts.patch
@@ -0,0 +1,45 @@
+From c490d42fe3db664d03e3c75d7b23243a717d3437 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Nguy=E1=BB=85n=20Gia=20Phong?= <cnx@loang.net>
+Date: Mon, 20 Oct 2025 20:08:48 +0900
+Subject: [PATCH] Add explicit casts
+
+---
+ accel/tcg/cpu-exec.c    | 4 ++--
+ accel/tcg/tcg-runtime.c | 2 +-
+ 2 files changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c
+index 2def088a34c6c..e62318fdcb067 100644
+--- a/accel/tcg/cpu-exec.c
++++ b/accel/tcg/cpu-exec.c
+@@ -285,7 +285,7 @@ static void restore_memory_snapshot(void) {
+ 
+ static int use_ijon = 0;
+ static unsigned char *ijon_map_ptr = dummy;
+-static uint64_t *ijon_max_ptr = dummy;
++static uint64_t *ijon_max_ptr = (uint64_t *)dummy;
+ 
+ /* IJON state tracking globals */
+ #if defined(__ANDROID__) || defined(__HAIKU__) || defined(NO_TLS)
+@@ -408,7 +408,7 @@ static void parse_ijon_line(const char *line, int line_num) {
+ 
+   } else {
+ 
+-    g_var_addr[ijon_hooker_cnt] = ijon_reg_to_addr(fields[2]);
++    g_var_addr[ijon_hooker_cnt] = (target_ulong) ijon_reg_to_addr(fields[2]);
+     if (g_var_addr[ijon_hooker_cnt] == 0) {
+       IJON_PARSE_ERROR(line_num, line, "Invalid register name in field 3. Value: '%s'", fields[2]);
+     }
+diff --git a/accel/tcg/tcg-runtime.c b/accel/tcg/tcg-runtime.c
+index 04bb709c918d3..fde4d299bb9dd 100644
+--- a/accel/tcg/tcg-runtime.c
++++ b/accel/tcg/tcg-runtime.c
+@@ -40,7 +40,7 @@ uint32_t afl_hash_ip(uint64_t);
+ void HELPER(ijon_func_call)(target_ulong var_addr, target_ulong var_len, target_ulong itype, target_ulong idx)
+ {
+   uint64_t buf = 0;
+-  memcpy(&buf, var_addr, var_len);
++  memcpy(&buf, (const void *)var_addr, var_len);
+   ijon_dispatch(itype, idx, buf);
+   fprintf(stderr, "trigger ijon: addr=0x%016" PRIx64 " tag=%s value %ld\n", var_addr, ijon_to_str(itype), buf);
+ }
diff --git a/patches/qemu-for-aflplusplus-imported-headers.patch b/patches/qemu-for-aflplusplus-imported-headers.patch
new file mode 100644
index 0000000..0bad00f
--- /dev/null
+++ b/patches/qemu-for-aflplusplus-imported-headers.patch
@@ -0,0 +1,181 @@
+From 8879cf700ce4e5fed7c1ab7ba4543f234d5cd5d1 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Nguy=E1=BB=85n=20Gia=20Phong?= <cnx@loang.net>
+Date: Mon, 20 Oct 2025 20:04:20 +0900
+Subject: [PATCH] Update headers imported from AFL++
+
+---
+ qemuafl/imported/config.h | 36 ++++++++++++++++++++++----
+ qemuafl/imported/types.h  | 53 +++++++++++++++++++++++++++++++++++++--
+ 2 files changed, 82 insertions(+), 7 deletions(-)
+
+diff --git a/qemuafl/imported/config.h b/qemuafl/imported/config.h
+index 5ac0540d4efd3..0690b992b80e9 100644
+--- a/qemuafl/imported/config.h
++++ b/qemuafl/imported/config.h
+@@ -26,7 +26,7 @@
+ /* Version string: */
+ 
+ // c = release, a = volatile github dev, e = experimental branch
+-#define VERSION "++4.32a"
++#define VERSION "++4.35a"
+ 
+ /******************************************************
+  *                                                    *
+@@ -49,6 +49,9 @@
+    Default: 300 (seconds) */
+ #define STRATEGY_SWITCH_TIME 1000
+ 
++/* Default file permission umode when creating directories */
++#define DEFAULT_DIRS_PERMISSION 0700
++
+ /* Default file permission umode when creating files (default: 0600) */
+ #define DEFAULT_PERMISSION 0600
+ 
+@@ -171,7 +174,9 @@
+ #define EXEC_TM_ROUND 20U
+ 
+ /* 64bit arch MACRO */
+-#if (defined(__x86_64__) || defined(__arm64__) || defined(__aarch64__))
++#if (defined(__x86_64__) || defined(__arm64__) || defined(__aarch64__) ||    \
++     (defined(__riscv) && __riscv_xlen == 64) || defined(__powerpc64le__) || \
++     defined(__s390x__) || defined(__loongarch64))
+   #define WORD_SIZE_64 1
+ #endif
+ 
+@@ -200,8 +205,8 @@
+ 
+ /* Maximum number of unique hangs or crashes to record: */
+ 
+-#define KEEP_UNIQUE_HANG 500U
+-#define KEEP_UNIQUE_CRASH 10000U
++#define KEEP_UNIQUE_HANG 512U
++#define KEEP_UNIQUE_CRASH 25600U
+ 
+ /* Baseline number of random tweaks during a single 'havoc' stage: */
+ 
+@@ -337,6 +342,10 @@
+ 
+ #define AVG_SMOOTHING 16
+ 
++/* Max length of sync id (the id after -M and -S) */
++
++#define SYNC_ID_MAX_LEN 50
++
+ /* Sync interval (every n havoc cycles): */
+ 
+ #define SYNC_INTERVAL 8
+@@ -422,9 +431,15 @@
+ 
+ #define SHM_ENV_VAR "__AFL_SHM_ID"
+ 
+-/* Environment variable used to pass SHM FUZZ ID to the called program. */
++/* Environment variable used to pass shared memory fuzz map id
++and the mapping size to the called program. */
+ 
+ #define SHM_FUZZ_ENV_VAR "__AFL_SHM_FUZZ_ID"
++#define SHM_FUZZ_MAP_SIZE_ENV_VAR "__AFL_SHM_FUZZ_MAP_SIZE"
++
++/* Default size of the shared memory fuzz map.
++We add 4 byte for one u32 length field. */
++#define SHM_FUZZ_MAP_SIZE_DEFAULT (MAX_FILE + 4)
+ 
+ /* Other less interesting, internal-only variables. */
+ 
+@@ -488,6 +503,17 @@
+   #define MAP_INITIAL_SIZE MAP_SIZE
+ #endif
+ 
++/* IJON max tracking map configuration */
++
++/* Number of IJON slots (power-of-2 for efficient bitmasking) */
++#define MAP_SIZE_IJON_ENTRIES 512
++
++/* IJON map size for set/inc/xor */
++#define MAP_SIZE_IJON_MAP 65536
++
++/* IJON map footprint in bytes (64-bit values for legacy compatibility) */
++#define MAP_SIZE_IJON_BYTES (MAP_SIZE_IJON_ENTRIES * sizeof(u64))  // = 4096
++
+ /* Maximum allocator request size (keep well under INT_MAX): */
+ 
+ #define MAX_ALLOC 0x40000000
+diff --git a/qemuafl/imported/types.h b/qemuafl/imported/types.h
+index d370bcfba28ab..a9ad56c5252aa 100644
+--- a/qemuafl/imported/types.h
++++ b/qemuafl/imported/types.h
+@@ -64,6 +64,7 @@ typedef uint128_t         u128;
+ #define FS_OPT_AUTODICT 0x10000000
+ #define FS_OPT_SHDMEM_FUZZ 0x01000000
+ #define FS_OPT_NEWCMPLOG 0x02000000
++#define FS_OPT_IJON 0x04000000
+ #define FS_OPT_OLD_AFLPP_WORKAROUND 0x0f000000
+ // FS_OPT_MAX_MAPSIZE is 8388608 = 0x800000 = 2^23 = 1 << 23
+ #define FS_OPT_MAX_MAPSIZE ((0x00fffffeU >> 1) + 1)
+@@ -161,6 +162,54 @@ typedef int128_t s128;
+                                                \
+   })
+ 
++#define EXTRACT16(_s, _o)      \
++  ({                           \
++                               \
++    u8 *s = (u8 *)(_s) + (_o); \
++    u16 _ret = s[1];           \
++    _ret = (_ret << 8) | s[0]; \
++    _ret;                      \
++                               \
++  })
++
++#define EXTRACT32(_s, _o)      \
++  ({                           \
++                               \
++    u8 *s = (u8 *)(_s) + (_o); \
++    u32 _ret = s[3];           \
++    _ret = (_ret << 8) | s[2]; \
++    _ret = (_ret << 8) | s[1]; \
++    _ret = (_ret << 8) | s[0]; \
++    _ret;                      \
++                               \
++  })
++
++#define INSERT16(_d, _o, _x)   \
++  {                            \
++                               \
++    u8 *d = (u8 *)(_d) + (_o); \
++    u16 x = _x;                \
++    d[0] = x & 0xFF;           \
++    x >>= 8;                   \
++    d[1] = x & 0xFF;           \
++                               \
++  }
++
++#define INSERT32(_d, _o, _x)   \
++  {                            \
++                               \
++    u8 *d = (u8 *)(_d) + (_o); \
++    u32 x = _x;                \
++    d[0] = x & 0xFF;           \
++    x >>= 8;                   \
++    d[1] = x & 0xFF;           \
++    x >>= 8;                   \
++    d[2] = x & 0xFF;           \
++    x >>= 8;                   \
++    d[3] = x & 0xFF;           \
++                               \
++  }
++
+ #ifdef AFL_LLVM_PASS
+   #if defined(__linux__) || !defined(__ANDROID__)
+     #define AFL_SR(s) (srandom(s))
+@@ -172,10 +221,10 @@ typedef int128_t s128;
+ #else
+   #if defined(__linux__) || !defined(__ANDROID__)
+     #define SR(s) (srandom(s))
+-    #define R(x) (random() % (x))
++    #define AFL_R(x) (random() % (x))
+   #else
+     #define SR(s) ((void)s)
+-    #define R(x) (arc4random_uniform(x))
++    #define AFL_R(x) (arc4random_uniform(x))
+   #endif
+ #endif                                                    /* ^AFL_LLVM_PASS */
+