diff options
| -rw-r--r-- | REUSE.toml | 2 | ||||
| -rw-r--r-- | loftix/emulation.scm | 64 | ||||
| -rw-r--r-- | loftix/fuzzing.scm | 55 | ||||
| -rw-r--r-- | patches/qemu-for-aflplusplus-casts.patch | 45 | ||||
| -rw-r--r-- | patches/qemu-for-aflplusplus-imported-headers.patch | 181 |
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 */ + |
