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
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
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_EXPAND_HAVOC_NOW", "AFL_USE_FASAN", "AFL_USE_QASAN",
"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[];

View File

@ -159,6 +159,8 @@ typedef struct afl_forkserver {
u8 uses_asan; /* Target uses ASAN/LSAN/MSAN? (bit 0/1/2 respectively) */
bool setenv; /* setenv() to discriminate the forkserver? */
bool debug; /* debug mode? */
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_old_forkserver;
u8 __afl_forkserver_setenv = 0;
#ifdef __AFL_CODE_COVERAGE
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,
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 + 1);
if (unlikely(__afl_forkserver_setenv)) {
unsetenv("AFL_FORKSERVER_PARENT");
}
return;
}

View File

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