mirror of
https://github.com/AFLplusplus/AFLplusplus.git
synced 2025-06-10 09:11:34 +00:00
Add a test case to `test/test-qemu-mode.sh` and make sure that AFL_QEMU_PERSISTENT_EXITS loops correctly. This works only on platforms for which `afl-qemu-trace` detects exit signals and resets the program counter. This commit updates `test-instr.c` to optionally call `exit(n)` instead of returning n to the operating system. This option can be activated using the `EXIT_AT_END` flag. This way, we can test the QEMU persistent exit mode without having to add a new test file. You can compile and run `test-instr.c` with the exit mode like so: ```bash gcc -o exit -DEXIT_AT_END test-instr.c AFL_QEMU_DEBUG_MAPS= \ AFL_DEBUG= \ AFL_QEMU_PERSISTENT_ADDR=$(readelf -a exit | grep 'main$' | awk '{ printf "0x%s", $2 }') \ AFL_QEMU_PERSISTENT_GPR=1 \ AFL_QEMU_PERSISTENT_EXITS=1 \ ./afl-qemu-trace exit ``` Press enter repeatedly and you will see an output like this: ``` ... Debug: Sending status 0xc201ffff test-instr: Neither one or zero? How quaint! test-instr: Neither one or zero? How quaint! test-instr: Neither one or zero? How quaint! test-instr: Neither one or zero? How quaint! test-instr: Neither one or zero? How quaint! ``` To make sure that persistent exits are detected correctly on x86_64, I've made the following changes to qemuafl: ``` linux-user/i386/cpu_loop.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux-user/i386/cpu_loop.c b/linux-user/i386/cpu_loop.c index 4509f46b95..46bdbaf94a 100644 --- a/linux-user/i386/cpu_loop.c +++ b/linux-user/i386/cpu_loop.c @@ -235,7 +235,7 @@ void cpu_loop(CPUX86State *env) #ifndef TARGET_ABI32 case EXCP_SYSCALL: /* linux syscall from syscall instruction */ - if (afl_fork_child && persistent_exits && + if (persistent_exits && env->regs[R_EAX] == TARGET_NR_exit_group) { env->eip = afl_persistent_addr; continue; ```
91 lines
1.7 KiB
C
91 lines
1.7 KiB
C
/*
|
|
american fuzzy lop++ - a trivial program to test the build
|
|
--------------------------------------------------------
|
|
Originally written by Michal Zalewski
|
|
Copyright 2014 Google Inc. All rights reserved.
|
|
Copyright 2019-2024 AFLplusplus Project. All rights reserved.
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at:
|
|
https://www.apache.org/licenses/LICENSE-2.0
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <string.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <fcntl.h>
|
|
|
|
#ifdef TEST_SHARED_OBJECT
|
|
#define main main_exported
|
|
#endif
|
|
|
|
int main(int argc, char **argv) {
|
|
|
|
int fd = 0, cnt;
|
|
char buff[8];
|
|
char *buf = buff;
|
|
|
|
// we support command line parameter and stdin
|
|
if (argc == 2) {
|
|
|
|
buf = argv[1];
|
|
|
|
} else {
|
|
|
|
if (argc >= 3 && strcmp(argv[1], "-f") == 0) {
|
|
|
|
if ((fd = open(argv[2], O_RDONLY)) < 0) {
|
|
|
|
fprintf(stderr, "Error: unable to open %s\n", argv[2]);
|
|
exit(-1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ((cnt = read(fd, buf, sizeof(buf) - 1)) < 1) {
|
|
|
|
printf("Hum?\n");
|
|
#ifdef EXIT_AT_END
|
|
exit(1);
|
|
#else
|
|
return 1;
|
|
#endif
|
|
|
|
}
|
|
|
|
buf[cnt] = 0;
|
|
|
|
}
|
|
|
|
if (getenv("AFL_DEBUG")) fprintf(stderr, "test-instr: %s\n", buf);
|
|
|
|
// we support three input cases (plus a 4th if stdin is used but there is no
|
|
// input)
|
|
switch (buf[0]) {
|
|
|
|
case '0':
|
|
printf("Looks like a zero to me!\n");
|
|
break;
|
|
|
|
case '1':
|
|
printf("Pretty sure that is a one!\n");
|
|
break;
|
|
|
|
default:
|
|
printf("Neither one or zero? How quaint!\n");
|
|
break;
|
|
|
|
}
|
|
#ifdef EXIT_AT_END
|
|
exit(0);
|
|
#endif
|
|
|
|
return 0;
|
|
|
|
}
|
|
|