Merge pull request #2412 from alexandredoyen29/environment_forkserver

Environment variable to discriminate the target and the forkserver
This commit is contained in:
van Hauser
2025-05-05 14:30:40 +02:00
committed by GitHub
5 changed files with 53 additions and 1 deletions

View File

@ -664,6 +664,24 @@ checks or alter some of the more exotic semantics of the tool:
Note that will not be exact and with slow targets it can take seconds Note that will not be exact and with slow targets it can take seconds
until there is a slice for the time test. until there is a slice for the time test.
- When using `AFL_PRELOAD` with a preload that disable `fork()` calls in
the target, the forkserver becomes unable to fork.
To overcome this issue, the `AFL_PRELOAD_DISCRIMINATE_FORKSERVER_PARENT`
permits to be able to check in the preloaded library if the environment
variable `AFL_FORKSERVER_PARENT` is set, to be able to use vanilla
`fork()` in the forkserver, and the placeholder in the target.
Here is a POC :
```C
// AFL_PRELOAD_DISCRIMINATE_FORKSERVER_PARENT=1 afl-fuzz ...
pid_t fork(void)
{
if (getenv("AFL_FORKSERVER_PARENT") == NULL)
return 0; // We are in the target
else
return real_fork(); // We are in the forkserver
}
```
## 6) Settings for afl-qemu-trace ## 6) Settings for afl-qemu-trace
The QEMU wrapper used to instrument binary-only code supports several settings: The QEMU wrapper used to instrument binary-only code supports several settings:

View File

@ -118,7 +118,8 @@ static char *afl_environment_variables[] = {
"AFL_CFISAN_VERBOSE", "AFL_USE_LSAN", "AFL_WINE_PATH", "AFL_NO_SNAPSHOT", "AFL_CFISAN_VERBOSE", "AFL_USE_LSAN", "AFL_WINE_PATH", "AFL_NO_SNAPSHOT",
"AFL_EXPAND_HAVOC_NOW", "AFL_USE_FASAN", "AFL_USE_QASAN", "AFL_EXPAND_HAVOC_NOW", "AFL_USE_FASAN", "AFL_USE_QASAN",
"AFL_PRINT_FILENAMES", "AFL_PIZZA_MODE", "AFL_NO_FASTRESUME", "AFL_PRINT_FILENAMES", "AFL_PIZZA_MODE", "AFL_NO_FASTRESUME",
"AFL_SAN_ABSTRACTION", "AFL_SAN_NO_INST", "AFL_SAN_RECOVER", NULL}; "AFL_SAN_ABSTRACTION", "AFL_SAN_NO_INST", "AFL_SAN_RECOVER",
"AFL_PRELOAD_DISCRIMINATE_FORKSERVER_PARENT", NULL};
extern char *afl_environment_variables[]; extern char *afl_environment_variables[];

View File

@ -159,6 +159,8 @@ typedef struct afl_forkserver {
u8 uses_asan; /* Target uses ASAN/LSAN/MSAN? (bit 0/1/2 respectively) */ u8 uses_asan; /* Target uses ASAN/LSAN/MSAN? (bit 0/1/2 respectively) */
bool setenv; /* setenv() to discriminate the forkserver? */
bool debug; /* debug mode? */ bool debug; /* debug mode? */
u8 san_but_not_instrumented; /* Is it sanitizer enabled but not instrumented? u8 san_but_not_instrumented; /* Is it sanitizer enabled but not instrumented?

View File

@ -119,6 +119,8 @@ u64 __afl_map_addr;
u32 __afl_first_final_loc; u32 __afl_first_final_loc;
u32 __afl_old_forkserver; u32 __afl_old_forkserver;
u8 __afl_forkserver_setenv = 0;
#ifdef __AFL_CODE_COVERAGE #ifdef __AFL_CODE_COVERAGE
typedef struct afl_module_info_t afl_module_info_t; typedef struct afl_module_info_t afl_module_info_t;
@ -888,6 +890,12 @@ static void __afl_start_forkserver(void) {
} }
if (getenv("AFL_PRELOAD_DISCRIMINATE_FORKSERVER_PARENT") != NULL) {
__afl_forkserver_setenv = 1;
}
/* Phone home and tell the parent that we're OK. If parent isn't there, /* Phone home and tell the parent that we're OK. If parent isn't there,
assume we're not running in forkserver mode and just execute program. */ assume we're not running in forkserver mode and just execute program. */
@ -1054,6 +1062,13 @@ static void __afl_start_forkserver(void) {
close(FORKSRV_FD); close(FORKSRV_FD);
close(FORKSRV_FD + 1); close(FORKSRV_FD + 1);
if (unlikely(__afl_forkserver_setenv)) {
unsetenv("AFL_FORKSERVER_PARENT");
}
return; return;
} }

View File

@ -250,6 +250,16 @@ void afl_fsrv_init(afl_forkserver_t *fsrv) {
fsrv->child_kill_signal = SIGKILL; fsrv->child_kill_signal = SIGKILL;
fsrv->max_length = MAX_FILE; fsrv->max_length = MAX_FILE;
if (getenv("AFL_PRELOAD_DISCRIMINATE_FORKSERVER_PARENT") != NULL) {
fsrv->setenv = 1;
} else {
fsrv->setenv = 0;
}
/* exec related stuff */ /* exec related stuff */
fsrv->child_pid = -1; fsrv->child_pid = -1;
fsrv->map_size = get_map_size(); fsrv->map_size = get_map_size();
@ -878,6 +888,12 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
/* CHILD PROCESS */ /* CHILD PROCESS */
if (unlikely(fsrv->setenv)) {
setenv("AFL_FORKSERVER_PARENT", "1", 0);
}
// enable terminating on sigpipe in the children // enable terminating on sigpipe in the children
struct sigaction sa; struct sigaction sa;
memset((char *)&sa, 0, sizeof(sa)); memset((char *)&sa, 0, sizeof(sa));