add AFL_FORKSRV_UID and AFL_FORKSRV_GID env vars

This commit is contained in:
GRAUX Pierre
2025-04-23 14:39:31 +02:00
parent a9900f02cb
commit c8d1b66af3
23 changed files with 536 additions and 77 deletions

View File

@ -686,6 +686,23 @@ checks or alter some of the more exotic semantics of the tool:
} }
``` ```
- `AFL_FORKSRV_UID` allows you to specify the UID that should be used when
running the fork server. When setting this variable, user should ensure
afl-fuzz binary has enough privileges to modify the UID (e.g. CAP\_SETUID
capability in Linux system).
- `AFL_FORKSRV_GID` allows you to specify the GID and the supplementary group
IDs that should be used when running the fork server. When setting this
variable, user should ensure afl-fuzz binary has enough privileges to
modify the GIDs (e.g. CAP\_SETGID capability in Linux system).
- When both `AFL_FORKSRV_UID` and `AFL_FORKSRV_GID` are set, afl-fuzz binary
and the fork server no longer share any IDs. Thus, afl-fuzz binary changes
the group owner of the created files to ensure that the fork server can
still access them. In such case, user should ensure afl-fuzz binary has
enough privileges to modify the ownership of entities (e.g. CAP\_CHOWN
capability in Linux system).
## 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

@ -462,7 +462,10 @@ typedef struct afl_env_vars {
afl_no_startup_calibration, afl_no_warn_instability, afl_no_startup_calibration, afl_no_warn_instability,
afl_post_process_keep_original, afl_crashing_seeds_as_new_crash, afl_post_process_keep_original, afl_crashing_seeds_as_new_crash,
afl_final_sync, afl_ignore_seed_problems, afl_disable_redundant, afl_final_sync, afl_ignore_seed_problems, afl_disable_redundant,
afl_sha1_filenames, afl_no_sync, afl_no_fastresume; afl_sha1_filenames, afl_no_sync, afl_no_fastresume, afl_forksrv_uid_set,
afl_forksrv_gid_set;
u16 afl_forksrv_nb_supl_gids;
u8 *afl_tmpdir, *afl_custom_mutator_library, *afl_python_module, *afl_path, u8 *afl_tmpdir, *afl_custom_mutator_library, *afl_python_module, *afl_path,
*afl_hang_tmout, *afl_forksrv_init_tmout, *afl_preload, *afl_hang_tmout, *afl_forksrv_init_tmout, *afl_preload,
@ -473,6 +476,12 @@ typedef struct afl_env_vars {
s32 afl_pizza_mode; s32 afl_pizza_mode;
uid_t afl_forksrv_uid;
gid_t afl_forksrv_gid;
gid_t *afl_forksrv_supl_gids;
} afl_env_vars_t; } afl_env_vars_t;
struct afl_pass_stat { struct afl_pass_stat {
@ -555,6 +564,10 @@ typedef struct afl_state {
*orig_cmdline, /* Original command line */ *orig_cmdline, /* Original command line */
*infoexec; /* Command to execute on a new crash */ *infoexec; /* Command to execute on a new crash */
mode_t perm, /* File permission when creating files */
dir_perm; /* File permission when creating directories */
u8 chown_needed; /* Group owner of files needs to be modified */
u32 hang_tmout, /* Timeout used for hang det (ms) */ u32 hang_tmout, /* Timeout used for hang det (ms) */
stats_update_freq; /* Stats update frequency (execs) */ stats_update_freq; /* Stats update frequency (execs) */
@ -1443,7 +1456,7 @@ char *sha1_hex_for_file(const char *fname, u32 len);
* enabled. */ * enabled. */
static inline int permissive_create(afl_state_t *afl, const char *fn) { static inline int permissive_create(afl_state_t *afl, const char *fn) {
int fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION); int fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, afl->perm);
if (unlikely(fd < 0)) { if (unlikely(fd < 0)) {
if (!(afl->afl_env.afl_sha1_filenames && errno == EEXIST)) { if (!(afl->afl_env.afl_sha1_filenames && errno == EEXIST)) {
@ -1454,6 +1467,12 @@ static inline int permissive_create(afl_state_t *afl, const char *fn) {
} }
if (afl->chown_needed) {
if (fchown(fd, -1, afl->fsrv.gid) == -1) { PFATAL("fchown() failed"); }
}
return fd; return fd;
} }

View File

@ -144,10 +144,10 @@ u8 *u_stringify_time_diff(u8 *buf, u64 cur_ms, u64 event_ms);
u32 get_map_size(void); u32 get_map_size(void);
/* create a stream file */ /* create a stream file */
FILE *create_ffile(u8 *fn); FILE *create_ffile(u8 *fn, mode_t perm);
/* create a file */ /* create a file */
s32 create_file(u8 *fn); s32 create_file(u8 *fn, mode_t perm);
/* memmem implementation as not all platforms support this */ /* memmem implementation as not all platforms support this */
void *afl_memmem(const void *haystack, size_t haystacklen, const void *needle, void *afl_memmem(const void *haystack, size_t haystacklen, const void *needle,

View File

@ -49,6 +49,9 @@
Default: 300 (seconds) */ Default: 300 (seconds) */
#define STRATEGY_SWITCH_TIME 1000 #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) */ /* Default file permission umode when creating files (default: 0600) */
#define DEFAULT_PERMISSION 0600 #define DEFAULT_PERMISSION 0600

View File

@ -120,7 +120,8 @@ static char *afl_environment_variables[] = {
"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_LLVM_ONLY_FSRV", "AFL_GCC_ONLY_FRSV", "AFL_SAN_ABSTRACTION", "AFL_LLVM_ONLY_FSRV", "AFL_GCC_ONLY_FRSV",
"AFL_SAN_RECOVER", "AFL_PRELOAD_DISCRIMINATE_FORKSERVER_PARENT", NULL}; "AFL_SAN_RECOVER", "AFL_PRELOAD_DISCRIMINATE_FORKSERVER_PARENT",
"AFL_FORKSRV_UID", "AFL_FORKSRV_GID", NULL};
extern char *afl_environment_variables[]; extern char *afl_environment_variables[];

View File

@ -187,6 +187,16 @@ typedef struct afl_forkserver {
s32 persistent_record_pid; s32 persistent_record_pid;
#endif #endif
u8 uid_set;
uid_t uid;
u8 gid_set;
pid_t gid;
u16 nb_supl_gids;
pid_t *supl_gids;
mode_t perm;
u8 chown_needed;
/* Function to kick off the forkserver child */ /* Function to kick off the forkserver child */
void (*init_child_func)(struct afl_forkserver *fsrv, char **argv); void (*init_child_func)(struct afl_forkserver *fsrv, char **argv);

View File

@ -57,7 +57,8 @@ typedef struct sharedmem {
} sharedmem_t; } sharedmem_t;
u8 *afl_shm_init(sharedmem_t *, size_t, unsigned char non_instrumented_mode); u8 *afl_shm_init(sharedmem_t *, size_t, unsigned char non_instrumented_mode,
mode_t mode, int gid);
void afl_shm_deinit(sharedmem_t *); void afl_shm_deinit(sharedmem_t *);
#endif #endif

View File

@ -984,7 +984,7 @@ int main(int argc, char **argv_orig, char **envp) {
fsrv.target_path = find_binary(argv[optind]); fsrv.target_path = find_binary(argv[optind]);
#endif #endif
fsrv.trace_bits = afl_shm_init(&shm, map_size, 0); fsrv.trace_bits = afl_shm_init(&shm, map_size, 0, DEFAULT_PERMISSION, -1);
detect_file_args(argv + optind, fsrv.out_file, &use_stdin); detect_file_args(argv + optind, fsrv.out_file, &use_stdin);
signal(SIGALRM, kill_child); signal(SIGALRM, kill_child);

View File

@ -1397,12 +1397,12 @@ u32 get_map_size(void) {
/* Create a stream file */ /* Create a stream file */
FILE *create_ffile(u8 *fn) { FILE *create_ffile(u8 *fn, mode_t mode) {
s32 fd; s32 fd;
FILE *f; FILE *f;
fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, DEFAULT_PERMISSION); fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, mode);
if (fd < 0) { PFATAL("Unable to create '%s'", fn); } if (fd < 0) { PFATAL("Unable to create '%s'", fn); }
@ -1416,11 +1416,11 @@ FILE *create_ffile(u8 *fn) {
/* Create a file */ /* Create a file */
s32 create_file(u8 *fn) { s32 create_file(u8 *fn, mode_t mode) {
s32 fd; s32 fd;
fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, DEFAULT_PERMISSION); fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, mode);
if (fd < 0) { PFATAL("Unable to create '%s'", fn); } if (fd < 0) { PFATAL("Unable to create '%s'", fn); }

View File

@ -51,6 +51,7 @@
#include <sys/resource.h> #include <sys/resource.h>
#include <sys/select.h> #include <sys/select.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <grp.h>
#ifdef __linux__ #ifdef __linux__
#include <dlfcn.h> #include <dlfcn.h>
@ -208,9 +209,35 @@ static void fsrv_exec_child(afl_forkserver_t *fsrv, char **argv) {
} }
if (fsrv->gid_set) {
if (setregid(fsrv->gid, fsrv->gid) == -1) {
FATAL("setgid failed: %s\n", strerror(errno));
}
if (setgroups(fsrv->nb_supl_gids, fsrv->supl_gids) == -1) {
FATAL("setgroups failed: %s\n", strerror(errno));
}
}
if (fsrv->uid_set) {
if (setreuid(fsrv->uid, fsrv->uid) == -1) {
FATAL("setuid failed: %s\n", strerror(errno));
}
}
execv(fsrv->target_path, argv); execv(fsrv->target_path, argv);
WARNF("Execv failed in forkserver."); WARNF("Execv failed in forkserver: %s.", strerror(errno));
} }
@ -274,6 +301,9 @@ void afl_fsrv_init(afl_forkserver_t *fsrv) {
fsrv->persistent_trace_bits = NULL; fsrv->persistent_trace_bits = NULL;
#endif #endif
fsrv->uid_set = 0;
fsrv->gid_set = 0;
fsrv->init_child_func = fsrv_exec_child; fsrv->init_child_func = fsrv_exec_child;
list_append(&fsrv_list, fsrv); list_append(&fsrv_list, fsrv);
@ -493,6 +523,26 @@ static void afl_fauxsrv_execv(afl_forkserver_t *fsrv, char **argv) {
close(FORKSRV_FD); close(FORKSRV_FD);
close(FORKSRV_FD + 1); close(FORKSRV_FD + 1);
if (fsrv->gid_set) {
if (setgid(fsrv->gid) == -1) {
FATAL("setgid failed: %s\n", strerror(errno));
}
}
if (fsrv->uid_set) {
if (setuid(fsrv->uid) == -1) {
FATAL("setuid failed: %s\n", strerror(errno));
}
}
// finally: exec... // finally: exec...
execv(fsrv->target_path, argv); execv(fsrv->target_path, argv);
@ -1839,14 +1889,18 @@ void __attribute__((hot)) afl_fsrv_write_to_testcase(afl_forkserver_t *fsrv,
if (unlikely(fsrv->no_unlink)) { if (unlikely(fsrv->no_unlink)) {
fd = open(fsrv->out_file, O_WRONLY | O_CREAT | O_TRUNC, fd = open(fsrv->out_file, O_WRONLY | O_CREAT | O_TRUNC, fsrv->perm);
DEFAULT_PERMISSION);
} else { } else {
unlink(fsrv->out_file); /* Ignore errors. */ unlink(fsrv->out_file); /* Ignore errors. */
fd = open(fsrv->out_file, O_WRONLY | O_CREAT | O_EXCL, fd = open(fsrv->out_file, O_WRONLY | O_CREAT | O_EXCL, fsrv->perm);
DEFAULT_PERMISSION);
}
if (fsrv->chown_needed) {
if (fchown(fd, -1, fsrv->gid) == -1) { PFATAL("fchown() failed"); }
} }

View File

@ -84,10 +84,16 @@ void write_bitmap(afl_state_t *afl) {
afl->bitmap_changed = 0; afl->bitmap_changed = 0;
snprintf(fname, PATH_MAX, "%s/fuzz_bitmap", afl->out_dir); snprintf(fname, PATH_MAX, "%s/fuzz_bitmap", afl->out_dir);
fd = open(fname, O_WRONLY | O_CREAT | O_TRUNC, DEFAULT_PERMISSION); fd = open(fname, O_WRONLY | O_CREAT | O_TRUNC, afl->perm);
if (fd < 0) { PFATAL("Unable to open '%s'", fname); } if (fd < 0) { PFATAL("Unable to open '%s'", fname); }
if (afl->chown_needed) {
if (fchown(fd, -1, afl->fsrv.gid) == -1) { PFATAL("fchown() failed"); }
}
ck_write(fd, afl->virgin_bits, afl->fsrv.map_size, fname); ck_write(fd, afl->virgin_bits, afl->fsrv.map_size, fname);
close(fd); close(fd);
@ -429,12 +435,18 @@ void write_crash_readme(afl_state_t *afl) {
sprintf(fn, "%s/crashes/README.txt", afl->out_dir); sprintf(fn, "%s/crashes/README.txt", afl->out_dir);
fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION); fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, afl->perm);
/* Do not die on errors here - that would be impolite. */ /* Do not die on errors here - that would be impolite. */
if (unlikely(fd < 0)) { return; } if (unlikely(fd < 0)) { return; }
if (afl->chown_needed) {
if (fchown(fd, -1, afl->fsrv.gid) == -1) { PFATAL("fchown() failed"); }
}
f = fdopen(fd, "w"); f = fdopen(fd, "w");
if (unlikely(!f)) { if (unlikely(!f)) {
@ -1076,9 +1088,15 @@ may_save_fault:
u8 fn_log[PATH_MAX]; u8 fn_log[PATH_MAX];
(void)(snprintf(fn_log, PATH_MAX, "%s.log", fn) + 1); (void)(snprintf(fn_log, PATH_MAX, "%s.log", fn) + 1);
fd = open(fn_log, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION); fd = open(fn_log, O_WRONLY | O_CREAT | O_EXCL, afl->perm);
if (unlikely(fd < 0)) { PFATAL("Unable to create '%s'", fn_log); } if (unlikely(fd < 0)) { PFATAL("Unable to create '%s'", fn_log); }
if (afl->chown_needed) {
if (fchown(fd, -1, afl->fsrv.gid) == -1) { PFATAL("fchown() failed"); }
}
u32 nyx_aux_string_len = afl->fsrv.nyx_handlers->nyx_get_aux_string( u32 nyx_aux_string_len = afl->fsrv.nyx_handlers->nyx_get_aux_string(
afl->fsrv.nyx_runner, afl->fsrv.nyx_aux_string, afl->fsrv.nyx_runner, afl->fsrv.nyx_aux_string,
afl->fsrv.nyx_aux_string_len); afl->fsrv.nyx_aux_string_len);

View File

@ -748,10 +748,16 @@ void save_auto(afl_state_t *afl) {
s32 fd; s32 fd;
fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, DEFAULT_PERMISSION); fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, afl->perm);
if (fd < 0) { PFATAL("Unable to create '%s'", fn); } if (fd < 0) { PFATAL("Unable to create '%s'", fn); }
if (afl->chown_needed) {
if (fchown(fd, -1, afl->fsrv.gid) == -1) { PFATAL("fchown() failed"); }
}
ck_write(fd, afl->a_extras[i].data, afl->a_extras[i].len, fn); ck_write(fd, afl->a_extras[i].data, afl->a_extras[i].len, fn);
close(fd); close(fd);

View File

@ -1268,9 +1268,20 @@ void perform_dry_run(afl_state_t *afl) {
++afl->saved_crashes; ++afl->saved_crashes;
fd = open(crash_fn, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION); fd = open(crash_fn, O_WRONLY | O_CREAT | O_EXCL, afl->perm);
if (unlikely(fd < 0)) { PFATAL("Unable to create '%s'", crash_fn); } if (unlikely(fd < 0)) { PFATAL("Unable to create '%s'", crash_fn); }
ck_write(fd, use_mem, read_len, crash_fn); ck_write(fd, use_mem, read_len, crash_fn);
if (afl->chown_needed) {
if (fchown(fd, -1, afl->fsrv.gid) == -1) {
PFATAL("fchown() failed");
}
}
close(fd); close(fd);
#ifdef __linux__ #ifdef __linux__
@ -1279,8 +1290,7 @@ void perform_dry_run(afl_state_t *afl) {
u8 crash_log_fn[PATH_MAX]; u8 crash_log_fn[PATH_MAX];
snprintf(crash_log_fn, PATH_MAX, "%s.log", crash_fn); snprintf(crash_log_fn, PATH_MAX, "%s.log", crash_fn);
fd = open(crash_log_fn, O_WRONLY | O_CREAT | O_EXCL, fd = open(crash_log_fn, O_WRONLY | O_CREAT | O_EXCL, afl->perm);
DEFAULT_PERMISSION);
if (unlikely(fd < 0)) { if (unlikely(fd < 0)) {
PFATAL("Unable to create '%s'", crash_log_fn); PFATAL("Unable to create '%s'", crash_log_fn);
@ -1293,6 +1303,17 @@ void perform_dry_run(afl_state_t *afl) {
ck_write(fd, afl->fsrv.nyx_aux_string, nyx_aux_string_len, ck_write(fd, afl->fsrv.nyx_aux_string, nyx_aux_string_len,
crash_log_fn); crash_log_fn);
if (afl->chown_needed) {
if (fchown(fd, -1, afl->fsrv.gid) == -1) {
PFATAL("fchown() failed");
}
}
close(fd); close(fd);
} }
@ -1483,7 +1504,7 @@ void perform_dry_run(afl_state_t *afl) {
/* Helper function: link() if possible, copy otherwise. */ /* Helper function: link() if possible, copy otherwise. */
static void link_or_copy(u8 *old_path, u8 *new_path) { static void link_or_copy(u8 *old_path, u8 *new_path, mode_t perm) {
s32 i = link(old_path, new_path); s32 i = link(old_path, new_path);
if (!i) { return; } if (!i) { return; }
@ -1494,7 +1515,7 @@ static void link_or_copy(u8 *old_path, u8 *new_path) {
sfd = open(old_path, O_RDONLY); sfd = open(old_path, O_RDONLY);
if (sfd < 0) { PFATAL("Unable to open '%s'", old_path); } if (sfd < 0) { PFATAL("Unable to open '%s'", old_path); }
dfd = open(new_path, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION); dfd = open(new_path, O_WRONLY | O_CREAT | O_EXCL, perm);
if (dfd < 0) { PFATAL("Unable to create '%s'", new_path); } if (dfd < 0) { PFATAL("Unable to create '%s'", new_path); }
tmp = ck_alloc(64 * 1024); tmp = ck_alloc(64 * 1024);
@ -1630,10 +1651,16 @@ void pivot_inputs(afl_state_t *afl) {
/* Pivot to the new queue entry. */ /* Pivot to the new queue entry. */
link_or_copy(q->fname, nfn); link_or_copy(q->fname, nfn, afl->perm);
ck_free(q->fname); ck_free(q->fname);
q->fname = nfn; q->fname = nfn;
if (afl->chown_needed) {
if (chown(nfn, -1, afl->fsrv.gid) == -1) { PFATAL("fchown() failed"); }
}
/* Make sure that the passed_det value carries over, too. */ /* Make sure that the passed_det value carries over, too. */
if (q->passed_det) { mark_as_det_done(afl, q); } if (q->passed_det) { mark_as_det_done(afl, q); }
@ -2240,13 +2267,15 @@ void setup_dirs_fds(afl_state_t *afl) {
ACTF("Setting up output directories..."); ACTF("Setting up output directories...");
if (afl->sync_id && mkdir(afl->sync_dir, 0700) && errno != EEXIST) { if (afl->sync_id && mkdir(afl->sync_dir, afl->dir_perm) && errno != EEXIST) {
PFATAL("Unable to create '%s'", afl->sync_dir); PFATAL("Unable to create '%s'", afl->sync_dir);
} }
if (mkdir(afl->out_dir, 0700)) { printf("out_dir = %s\n", afl->out_dir);
if (mkdir(afl->out_dir, afl->dir_perm)) {
if (errno != EEXIST) { PFATAL("Unable to create '%s'", afl->out_dir); } if (errno != EEXIST) { PFATAL("Unable to create '%s'", afl->out_dir); }
@ -2254,6 +2283,16 @@ void setup_dirs_fds(afl_state_t *afl) {
} else { } else {
if (afl->chown_needed) {
if (chown(afl->out_dir, -1, afl->fsrv.gid) == -1) {
PFATAL("fchown() failed");
}
}
if (afl->in_place_resume) { if (afl->in_place_resume) {
FATAL("Resume attempted but old output directory not found"); FATAL("Resume attempted but old output directory not found");
@ -2288,27 +2327,27 @@ void setup_dirs_fds(afl_state_t *afl) {
/* Queue directory for any starting & discovered paths. */ /* Queue directory for any starting & discovered paths. */
tmp = alloc_printf("%s/queue", afl->out_dir); tmp = alloc_printf("%s/queue", afl->out_dir);
if (mkdir(tmp, 0700)) { PFATAL("Unable to create '%s'", tmp); } if (mkdir(tmp, afl->dir_perm)) { PFATAL("Unable to create '%s'", tmp); }
ck_free(tmp); ck_free(tmp);
/* Top-level directory for queue metadata used for session /* Top-level directory for queue metadata used for session
resume and related tasks. */ resume and related tasks. */
tmp = alloc_printf("%s/queue/.state/", afl->out_dir); tmp = alloc_printf("%s/queue/.state/", afl->out_dir);
if (mkdir(tmp, 0700)) { PFATAL("Unable to create '%s'", tmp); } if (mkdir(tmp, afl->dir_perm)) { PFATAL("Unable to create '%s'", tmp); }
ck_free(tmp); ck_free(tmp);
/* Directory for flagging queue entries that went through /* Directory for flagging queue entries that went through
deterministic fuzzing in the past. */ deterministic fuzzing in the past. */
tmp = alloc_printf("%s/queue/.state/deterministic_done/", afl->out_dir); tmp = alloc_printf("%s/queue/.state/deterministic_done/", afl->out_dir);
if (mkdir(tmp, 0700)) { PFATAL("Unable to create '%s'", tmp); } if (mkdir(tmp, afl->dir_perm)) { PFATAL("Unable to create '%s'", tmp); }
ck_free(tmp); ck_free(tmp);
/* Directory with the auto-selected dictionary entries. */ /* Directory with the auto-selected dictionary entries. */
tmp = alloc_printf("%s/queue/.state/auto_extras/", afl->out_dir); tmp = alloc_printf("%s/queue/.state/auto_extras/", afl->out_dir);
if (mkdir(tmp, 0700)) { PFATAL("Unable to create '%s'", tmp); } if (mkdir(tmp, afl->dir_perm)) { PFATAL("Unable to create '%s'", tmp); }
ck_free(tmp); ck_free(tmp);
/* Sync directory for keeping track of cooperating fuzzers. */ /* Sync directory for keeping track of cooperating fuzzers. */
@ -2317,7 +2356,8 @@ void setup_dirs_fds(afl_state_t *afl) {
tmp = alloc_printf("%s/.synced/", afl->out_dir); tmp = alloc_printf("%s/.synced/", afl->out_dir);
if (mkdir(tmp, 0700) && (!afl->in_place_resume || errno != EEXIST)) { if (mkdir(tmp, afl->dir_perm) &&
(!afl->in_place_resume || errno != EEXIST)) {
PFATAL("Unable to create '%s'", tmp); PFATAL("Unable to create '%s'", tmp);
@ -2330,13 +2370,13 @@ void setup_dirs_fds(afl_state_t *afl) {
/* All recorded crashes. */ /* All recorded crashes. */
tmp = alloc_printf("%s/crashes", afl->out_dir); tmp = alloc_printf("%s/crashes", afl->out_dir);
if (mkdir(tmp, 0700)) { PFATAL("Unable to create '%s'", tmp); } if (mkdir(tmp, afl->dir_perm)) { PFATAL("Unable to create '%s'", tmp); }
ck_free(tmp); ck_free(tmp);
/* All recorded hangs. */ /* All recorded hangs. */
tmp = alloc_printf("%s/hangs", afl->out_dir); tmp = alloc_printf("%s/hangs", afl->out_dir);
if (mkdir(tmp, 0700)) { PFATAL("Unable to create '%s'", tmp); } if (mkdir(tmp, afl->dir_perm)) { PFATAL("Unable to create '%s'", tmp); }
ck_free(tmp); ck_free(tmp);
/* Generally useful file descriptors. */ /* Generally useful file descriptors. */
@ -2353,8 +2393,14 @@ void setup_dirs_fds(afl_state_t *afl) {
if (!afl->in_place_resume) { if (!afl->in_place_resume) {
int fd = open(tmp, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION); int fd = open(tmp, O_WRONLY | O_CREAT | O_EXCL, afl->perm);
if (fd < 0) { PFATAL("Unable to create '%s'", tmp); } if (fd < 0) { PFATAL("Unable to create '%s'", tmp); }
if (afl->chown_needed) {
if (fchown(fd, -1, afl->fsrv.gid) == -1) { PFATAL("fchown() failed"); }
}
ck_free(tmp); ck_free(tmp);
afl->fsrv.plot_file = fdopen(fd, "w"); afl->fsrv.plot_file = fdopen(fd, "w");
@ -2380,8 +2426,14 @@ void setup_dirs_fds(afl_state_t *afl) {
} else { } else {
int fd = open(tmp, O_WRONLY | O_CREAT, DEFAULT_PERMISSION); int fd = open(tmp, O_WRONLY | O_CREAT, afl->perm);
if (fd < 0) { PFATAL("Unable to create '%s'", tmp); } if (fd < 0) { PFATAL("Unable to create '%s'", tmp); }
if (afl->chown_needed) {
if (fchown(fd, -1, afl->fsrv.gid) == -1) { PFATAL("fchown() failed"); }
}
ck_free(tmp); ck_free(tmp);
afl->fsrv.plot_file = fdopen(fd, "w"); afl->fsrv.plot_file = fdopen(fd, "w");
@ -2397,8 +2449,14 @@ void setup_dirs_fds(afl_state_t *afl) {
tmp = alloc_printf("%s/plot_det_data", afl->out_dir); tmp = alloc_printf("%s/plot_det_data", afl->out_dir);
int fd = open(tmp, O_WRONLY | O_CREAT, DEFAULT_PERMISSION); int fd = open(tmp, O_WRONLY | O_CREAT, afl->perm);
if (fd < 0) { PFATAL("Unable to create '%s'", tmp); } if (fd < 0) { PFATAL("Unable to create '%s'", tmp); }
if (afl->chown_needed) {
if (fchown(fd, -1, afl->fsrv.gid) == -1) { PFATAL("fchown() failed"); }
}
ck_free(tmp); ck_free(tmp);
afl->fsrv.det_plot_file = fdopen(fd, "w"); afl->fsrv.det_plot_file = fdopen(fd, "w");
@ -2422,8 +2480,14 @@ void setup_cmdline_file(afl_state_t *afl, char **argv) {
/* Store the command line to reproduce our findings */ /* Store the command line to reproduce our findings */
tmp = alloc_printf("%s/cmdline", afl->out_dir); tmp = alloc_printf("%s/cmdline", afl->out_dir);
fd = open(tmp, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION); fd = open(tmp, O_WRONLY | O_CREAT | O_EXCL, afl->perm);
if (fd < 0) { PFATAL("Unable to create '%s'", tmp); } if (fd < 0) { PFATAL("Unable to create '%s'", tmp); }
if (afl->chown_needed) {
if (fchown(fd, -1, afl->fsrv.gid) == -1) { PFATAL("fchown() failed"); }
}
ck_free(tmp); ck_free(tmp);
cmdline_file = fdopen(fd, "w"); cmdline_file = fdopen(fd, "w");
@ -2458,7 +2522,7 @@ void setup_stdio_file(afl_state_t *afl) {
unlink(afl->fsrv.out_file); /* Ignore errors */ unlink(afl->fsrv.out_file); /* Ignore errors */
afl->fsrv.out_fd = afl->fsrv.out_fd =
open(afl->fsrv.out_file, O_RDWR | O_CREAT | O_EXCL, DEFAULT_PERMISSION); open(afl->fsrv.out_file, O_RDWR | O_CREAT | O_EXCL, afl->perm);
if (afl->fsrv.out_fd < 0) { if (afl->fsrv.out_fd < 0) {
@ -2466,6 +2530,16 @@ void setup_stdio_file(afl_state_t *afl) {
} }
if (afl->chown_needed) {
if (fchown(afl->fsrv.out_fd, -1, afl->fsrv.gid) == -1) {
PFATAL("fchown() failed");
}
}
} }
/* Make sure that core dumps don't go to a program. */ /* Make sure that core dumps don't go to a program. */
@ -2902,7 +2976,8 @@ void setup_testcase_shmem(afl_state_t *afl) {
// we need to set the non-instrumented mode to not overwrite the SHM_ENV_VAR // we need to set the non-instrumented mode to not overwrite the SHM_ENV_VAR
size_t shm_fuzz_map_size = SHM_FUZZ_MAP_SIZE_DEFAULT; size_t shm_fuzz_map_size = SHM_FUZZ_MAP_SIZE_DEFAULT;
u8 *map = afl_shm_init(afl->shm_fuzz, shm_fuzz_map_size, 1); u8 *map = afl_shm_init(afl->shm_fuzz, shm_fuzz_map_size, 1, afl->perm,
afl->chown_needed ? afl->fsrv.gid : -1);
afl->shm_fuzz->shmemfuzz_mode = 1; afl->shm_fuzz->shmemfuzz_mode = 1;
if (!map) { FATAL("BUG: Zero return from afl_shm_init."); } if (!map) { FATAL("BUG: Zero return from afl_shm_init."); }

View File

@ -623,10 +623,16 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf,
unlink(q->fname); /* ignore errors */ unlink(q->fname); /* ignore errors */
fd = open(q->fname, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION); fd = open(q->fname, O_WRONLY | O_CREAT | O_EXCL, afl->perm);
if (fd < 0) { PFATAL("Unable to create '%s'", q->fname); } if (fd < 0) { PFATAL("Unable to create '%s'", q->fname); }
if (afl->chown_needed) {
if (fchown(fd, -1, afl->fsrv.gid) == -1) { PFATAL("fchown() failed"); }
}
ck_write(fd, out_buf, out_len, q->fname); ck_write(fd, out_buf, out_len, q->fname);
close(fd); close(fd);

View File

@ -6178,7 +6178,8 @@ u8 fuzz_one(afl_state_t *afl) {
if (afl->do_document == 0) { if (afl->do_document == 0) {
snprintf(path_buf, PATH_MAX, "%s/mutations", afl->out_dir); snprintf(path_buf, PATH_MAX, "%s/mutations", afl->out_dir);
afl->do_document = mkdir(path_buf, 0700); // if it exists we do not care afl->do_document =
mkdir(path_buf, afl->dir_perm); // if it exists we do not care
afl->do_document = 1; afl->do_document = 1;
} else { } else {

View File

@ -432,8 +432,15 @@ void mark_as_det_done(afl_state_t *afl, struct queue_entry *q) {
snprintf(fn, PATH_MAX, "%s/queue/.state/deterministic_done/%s", afl->out_dir, snprintf(fn, PATH_MAX, "%s/queue/.state/deterministic_done/%s", afl->out_dir,
strrchr((char *)q->fname, '/') + 1); strrchr((char *)q->fname, '/') + 1);
fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION); fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, afl->perm);
if (fd < 0) { PFATAL("Unable to create '%s'", fn); } if (fd < 0) { PFATAL("Unable to create '%s'", fn); }
if (afl->chown_needed) {
if (fchown(fd, -1, afl->fsrv.gid) == -1) { PFATAL("fchown() failed"); }
}
close(fd); close(fd);
q->passed_det = 1; q->passed_det = 1;

View File

@ -258,11 +258,21 @@ u32 __attribute__((hot)) write_to_testcase(afl_state_t *afl, void **mem,
afl->document_counter++, afl->document_counter++,
describe_op(afl, 0, NAME_MAX - strlen("000000000:"))); describe_op(afl, 0, NAME_MAX - strlen("000000000:")));
if ((doc_fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, DEFAULT_PERMISSION)) >= if ((doc_fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, afl->perm)) >= 0) {
0) {
if (write(doc_fd, *mem, len) != len) if (write(doc_fd, *mem, len) != len)
PFATAL("write to mutation file failed: %s", fn); PFATAL("write to mutation file failed: %s", fn);
if (afl->chown_needed) {
if (fchown(doc_fd, -1, afl->fsrv.gid) == -1) {
PFATAL("fchown() failed");
}
}
close(doc_fd); close(doc_fd);
} }
@ -386,19 +396,23 @@ static void write_with_gap(afl_state_t *afl, u8 *mem, u32 len, u32 skip_at,
if (unlikely(afl->no_unlink)) { if (unlikely(afl->no_unlink)) {
fd = open(afl->fsrv.out_file, O_WRONLY | O_CREAT | O_TRUNC, fd = open(afl->fsrv.out_file, O_WRONLY | O_CREAT | O_TRUNC, afl->perm);
DEFAULT_PERMISSION);
} else { } else {
unlink(afl->fsrv.out_file); /* Ignore errors. */ unlink(afl->fsrv.out_file); /* Ignore errors. */
fd = open(afl->fsrv.out_file, O_WRONLY | O_CREAT | O_EXCL, fd = open(afl->fsrv.out_file, O_WRONLY | O_CREAT | O_EXCL, afl->perm);
DEFAULT_PERMISSION);
} }
if (fd < 0) { PFATAL("Unable to create '%s'", afl->fsrv.out_file); } if (fd < 0) { PFATAL("Unable to create '%s'", afl->fsrv.out_file); }
if (afl->chown_needed) {
if (fchown(fd, -1, afl->fsrv.gid) == -1) { PFATAL("fchown() failed"); }
}
} else { } else {
lseek(fd, 0, SEEK_SET); lseek(fd, 0, SEEK_SET);
@ -895,10 +909,16 @@ void sync_fuzzers(afl_state_t *afl) {
sprintf(qd_synced_path, "%s/.synced/%s", afl->out_dir, sd_ent->d_name); sprintf(qd_synced_path, "%s/.synced/%s", afl->out_dir, sd_ent->d_name);
id_fd = open(qd_synced_path, O_RDWR | O_CREAT, DEFAULT_PERMISSION); id_fd = open(qd_synced_path, O_RDWR | O_CREAT, afl->perm);
if (id_fd < 0) { PFATAL("Unable to create '%s'", qd_synced_path); } if (id_fd < 0) { PFATAL("Unable to create '%s'", qd_synced_path); }
if (afl->chown_needed) {
if (fchown(id_fd, -1, afl->fsrv.gid) == -1) { PFATAL("fchown() failed"); }
}
if (read(id_fd, &min_accept, sizeof(u32)) == sizeof(u32)) { if (read(id_fd, &min_accept, sizeof(u32)) == sizeof(u32)) {
next_min_accept = min_accept; next_min_accept = min_accept;
@ -1296,7 +1316,7 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
if (unlikely(afl->no_unlink)) { if (unlikely(afl->no_unlink)) {
fd = open(q->fname, O_WRONLY | O_CREAT | O_TRUNC, DEFAULT_PERMISSION); fd = open(q->fname, O_WRONLY | O_CREAT | O_TRUNC, afl->perm);
if (fd < 0) { PFATAL("Unable to create '%s'", q->fname); } if (fd < 0) { PFATAL("Unable to create '%s'", q->fname); }
@ -1311,7 +1331,7 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
} else { } else {
unlink(q->fname); /* ignore errors */ unlink(q->fname); /* ignore errors */
fd = open(q->fname, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION); fd = open(q->fname, O_WRONLY | O_CREAT | O_EXCL, afl->perm);
if (fd < 0) { PFATAL("Unable to create '%s'", q->fname); } if (fd < 0) { PFATAL("Unable to create '%s'", q->fname); }
@ -1319,6 +1339,12 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
} }
if (afl->chown_needed) {
if (fchown(fd, -1, afl->fsrv.gid) == -1) { PFATAL("fchown() failed"); }
}
close(fd); close(fd);
queue_testcase_retake_mem(afl, q, in_buf, q->len, orig_len); queue_testcase_retake_mem(afl, q, in_buf, q->len, orig_len);

View File

@ -683,6 +683,89 @@ void read_afl_environment(afl_state_t *afl, char **envp) {
afl->afl_env.afl_sha1_filenames = afl->afl_env.afl_sha1_filenames =
get_afl_env(afl_environment_variables[i]) ? 1 : 0; get_afl_env(afl_environment_variables[i]) ? 1 : 0;
} else if (!strncmp(env, "AFL_FORKSRV_UID",
afl_environment_variable_len)) {
u8 *uid_str = (u8 *)get_afl_env(afl_environment_variables[i]);
char *ret;
int uid = strtol(uid_str, &ret, 10);
if (*ret != '\0') {
WARNF("Incorrect value given to AFL_FORKSRV_UID\n");
} else {
afl->afl_env.afl_forksrv_uid_set = 1;
afl->afl_env.afl_forksrv_uid = uid;
}
} else if (!strncmp(env, "AFL_FORKSRV_GID",
afl_environment_variable_len)) {
u8 *gid_str = (u8 *)get_afl_env(afl_environment_variables[i]);
// Count the number of supplementary GIDs
// and prepare the string for the next loop
afl->afl_env.afl_forksrv_nb_supl_gids = 0;
for (u32 i = 0; gid_str[i] != '\0'; i++) {
if (gid_str[i] == ',') {
afl->afl_env.afl_forksrv_nb_supl_gids++;
gid_str[i] = '\0';
}
}
if (afl->afl_env.afl_forksrv_nb_supl_gids > 0) {
afl->afl_env.afl_forksrv_supl_gids = ck_alloc(
sizeof(gid_t) * afl->afl_env.afl_forksrv_nb_supl_gids);
}
for (u16 i = 0; i < afl->afl_env.afl_forksrv_nb_supl_gids + 1;
i++) {
char *ret;
int gid = strtol(gid_str, &ret, 10);
if (*ret != '\0') {
WARNF("Incorrect value given to AFL_FORKSRV_GID\n");
afl->afl_env.afl_forksrv_gid_set = 0;
afl->afl_env.afl_forksrv_gid = 0;
free(afl->afl_env.afl_forksrv_supl_gids);
break;
} else {
// First GID is the effective one, others are supplementary
// ones.
if (i == 0) {
afl->afl_env.afl_forksrv_gid_set = 1;
afl->afl_env.afl_forksrv_gid = gid;
} else {
afl->afl_env.afl_forksrv_supl_gids[i - 1] = gid;
}
// Jump to next GID
gid_str = ret + 1;
}
}
} }
} else { } else {
@ -808,6 +891,8 @@ void afl_state_deinit(afl_state_t *afl) {
ck_free(afl->skipdet_g); ck_free(afl->skipdet_g);
ck_free(afl->havoc_prof); ck_free(afl->havoc_prof);
ck_free(afl->afl_env.afl_forksrv_supl_gids);
list_remove(&afl_states, afl); list_remove(&afl_states, afl);
} }

View File

@ -86,7 +86,13 @@ void write_setup_file(afl_state_t *afl, u32 argc, char **argv) {
u8 fn[PATH_MAX], fn2[PATH_MAX]; u8 fn[PATH_MAX], fn2[PATH_MAX];
snprintf(fn2, PATH_MAX, "%s/target_hash", afl->out_dir); snprintf(fn2, PATH_MAX, "%s/target_hash", afl->out_dir);
FILE *f2 = create_ffile(fn2); FILE *f2 = create_ffile(fn2, afl->perm);
if (afl->chown_needed) {
if (chown(fn2, -1, afl->fsrv.gid) == -1) { PFATAL("chown() failed"); }
}
#ifdef __linux__ #ifdef __linux__
if (afl->fsrv.nyx_mode) { if (afl->fsrv.nyx_mode) {
@ -106,9 +112,15 @@ void write_setup_file(afl_state_t *afl, u32 argc, char **argv) {
fclose(f2); fclose(f2);
snprintf(fn, PATH_MAX, "%s/fuzzer_setup", afl->out_dir); snprintf(fn, PATH_MAX, "%s/fuzzer_setup", afl->out_dir);
FILE *f = create_ffile(fn); FILE *f = create_ffile(fn, afl->perm);
u32 i; u32 i;
if (afl->chown_needed) {
if (chown(fn, -1, afl->fsrv.gid) == -1) { PFATAL("chown() failed"); }
}
fprintf(f, "# environment variables:\n"); fprintf(f, "# environment variables:\n");
u32 s_afl_env = (u32)sizeof(afl_environment_variables) / u32 s_afl_env = (u32)sizeof(afl_environment_variables) /
sizeof(afl_environment_variables[0]) - sizeof(afl_environment_variables[0]) -
@ -323,7 +335,13 @@ void write_stats_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg,
snprintf(fn_tmp, PATH_MAX, "%s/.fuzzer_stats_tmp", afl->out_dir); snprintf(fn_tmp, PATH_MAX, "%s/.fuzzer_stats_tmp", afl->out_dir);
snprintf(fn_final, PATH_MAX, "%s/fuzzer_stats", afl->out_dir); snprintf(fn_final, PATH_MAX, "%s/fuzzer_stats", afl->out_dir);
f = create_ffile(fn_tmp); f = create_ffile(fn_tmp, afl->perm);
if (afl->chown_needed) {
if (chown(fn_tmp, -1, afl->fsrv.gid) == -1) { PFATAL("fchown() failed"); }
}
/* Keep last values in case we're called from another context /* Keep last values in case we're called from another context
where exec/sec stats and such are not readily available. */ where exec/sec stats and such are not readily available. */

View File

@ -602,6 +602,49 @@ int main(int argc, char **argv_orig, char **envp) {
if (debug) { afl->fsrv.debug = true; } if (debug) { afl->fsrv.debug = true; }
read_afl_environment(afl, envp); read_afl_environment(afl, envp);
if (afl->shm.map_size) { afl->fsrv.map_size = afl->shm.map_size; } if (afl->shm.map_size) { afl->fsrv.map_size = afl->shm.map_size; }
if (afl->afl_env.afl_forksrv_uid_set) {
afl->fsrv.uid_set = 1;
afl->fsrv.uid = afl->afl_env.afl_forksrv_uid;
}
if (afl->afl_env.afl_forksrv_gid_set) {
afl->fsrv.gid_set = 1;
afl->fsrv.gid = afl->afl_env.afl_forksrv_gid;
afl->fsrv.nb_supl_gids = afl->afl_env.afl_forksrv_nb_supl_gids;
afl->fsrv.supl_gids = afl->afl_env.afl_forksrv_supl_gids;
}
if (afl->fsrv.uid_set) {
/* If the UID is modified, allow group to open files and dirs */
afl->perm = DEFAULT_PERMISSION | 0060;
afl->fsrv.perm = afl->perm;
afl->dir_perm = DEFAULT_DIRS_PERMISSION | 0070;
/* Ensure permissions will be really set*/
umask(~(afl->perm | afl->dir_perm));
/* If the GID is also modified, then change the group of files and dirs */
if (afl->fsrv.gid_set) {
afl->chown_needed = 1;
afl->fsrv.chown_needed = 1;
}
} else {
afl->perm = DEFAULT_PERMISSION;
afl->fsrv.perm = afl->perm;
afl->dir_perm = DEFAULT_DIRS_PERMISSION;
}
exit_1 = !!afl->afl_env.afl_bench_just_one; exit_1 = !!afl->afl_env.afl_bench_just_one;
SAYF(cCYA "afl-fuzz" VERSION cRST SAYF(cCYA "afl-fuzz" VERSION cRST
@ -2505,7 +2548,8 @@ int main(int argc, char **argv_orig, char **envp) {
afl->argv = use_argv; afl->argv = use_argv;
afl->fsrv.trace_bits = afl->fsrv.trace_bits =
afl_shm_init(&afl->shm, afl->fsrv.map_size, afl->non_instrumented_mode); afl_shm_init(&afl->shm, afl->fsrv.map_size, afl->non_instrumented_mode,
afl->perm, afl->chown_needed ? afl->fsrv.gid : -1);
if (!afl->non_instrumented_mode && !afl->fsrv.qemu_mode && if (!afl->non_instrumented_mode && !afl->fsrv.qemu_mode &&
!afl->unicorn_mode && !afl->fsrv.frida_mode && !afl->fsrv.cs_mode && !afl->unicorn_mode && !afl->fsrv.frida_mode && !afl->fsrv.cs_mode &&
@ -2533,7 +2577,8 @@ int main(int argc, char **argv_orig, char **envp) {
afl_shm_deinit(&afl->shm); afl_shm_deinit(&afl->shm);
afl->fsrv.map_size = new_map_size; afl->fsrv.map_size = new_map_size;
afl->fsrv.trace_bits = afl->fsrv.trace_bits =
afl_shm_init(&afl->shm, new_map_size, afl->non_instrumented_mode); afl_shm_init(&afl->shm, new_map_size, afl->non_instrumented_mode,
afl->perm, afl->chown_needed ? afl->fsrv.gid : -1);
setenv("AFL_NO_AUTODICT", "1", 1); // loaded already setenv("AFL_NO_AUTODICT", "1", 1); // loaded already
afl_fsrv_start(&afl->fsrv, afl->argv, &afl->stop_soon, afl_fsrv_start(&afl->fsrv, afl->argv, &afl->stop_soon,
afl->afl_env.afl_debug_child); afl->afl_env.afl_debug_child);
@ -2630,7 +2675,8 @@ int main(int argc, char **argv_orig, char **envp) {
setenv("AFL_NO_AUTODICT", "1", 1); // loaded already setenv("AFL_NO_AUTODICT", "1", 1); // loaded already
afl->fsrv.trace_bits = afl->fsrv.trace_bits =
afl_shm_init(&afl->shm, new_map_size, afl->non_instrumented_mode); afl_shm_init(&afl->shm, new_map_size, afl->non_instrumented_mode,
afl->perm, afl->chown_needed ? afl->fsrv.gid : -1);
ck_free(afl->san_fsrvs[i].trace_bits); ck_free(afl->san_fsrvs[i].trace_bits);
afl->san_fsrvs[i].trace_bits = ck_alloc(afl->fsrv.map_size + 8); afl->san_fsrvs[i].trace_bits = ck_alloc(afl->fsrv.map_size + 8);
afl->san_fsrvs[i].map_size = afl->fsrv.map_size; afl->san_fsrvs[i].map_size = afl->fsrv.map_size;
@ -2696,7 +2742,8 @@ int main(int argc, char **argv_orig, char **envp) {
setenv("AFL_NO_AUTODICT", "1", 1); // loaded already setenv("AFL_NO_AUTODICT", "1", 1); // loaded already
afl->fsrv.trace_bits = afl->fsrv.trace_bits =
afl_shm_init(&afl->shm, new_map_size, afl->non_instrumented_mode); afl_shm_init(&afl->shm, new_map_size, afl->non_instrumented_mode,
afl->perm, afl->chown_needed ? afl->fsrv.gid : -1);
afl->cmplog_fsrv.trace_bits = afl->fsrv.trace_bits; afl->cmplog_fsrv.trace_bits = afl->fsrv.trace_bits;
afl_fsrv_start(&afl->fsrv, afl->argv, &afl->stop_soon, afl_fsrv_start(&afl->fsrv, afl->argv, &afl->stop_soon,
afl->afl_env.afl_debug_child); afl->afl_env.afl_debug_child);
@ -3446,8 +3493,17 @@ stop_fuzzing:
if ((fr_fd = ZLIBOPEN(fr, "wb9")) != NULL) { if ((fr_fd = ZLIBOPEN(fr, "wb9")) != NULL) {
#else #else
if ((fr_fd = open(fr, O_WRONLY | O_TRUNC | O_CREAT, DEFAULT_PERMISSION)) >= if ((fr_fd = open(fr, O_WRONLY | O_TRUNC | O_CREAT, afl->perm)) >= 0) {
0) {
if (afl->chown_needed) {
if (fchown(fr_fd, -1, afl->fsrv.gid) == -1) {
PFATAL("fchown() failed");
}
}
#endif #endif

View File

@ -142,7 +142,8 @@ void afl_shm_deinit(sharedmem_t *shm) {
*/ */
u8 *afl_shm_init(sharedmem_t *shm, size_t map_size, u8 *afl_shm_init(sharedmem_t *shm, size_t map_size,
unsigned char non_instrumented_mode) { unsigned char non_instrumented_mode, mode_t permission,
int gid) {
shm->map_size = 0; shm->map_size = 0;
@ -181,7 +182,13 @@ u8 *afl_shm_init(sharedmem_t *shm, size_t map_size,
shm->g_shm_fd = shm->g_shm_fd =
shm_create_largepage(shm->g_shm_file_path, shmflags, i, shm_create_largepage(shm->g_shm_file_path, shmflags, i,
SHM_LARGEPAGE_ALLOC_DEFAULT, DEFAULT_PERMISSION); SHM_LARGEPAGE_ALLOC_DEFAULT, permission);
if (gid != -1 && shm->g_shm_fd != -1) {
if (fchown(shm->g_shm_fd, -1, gid) == -1) { PFATAL("fchown() failed"); }
}
} }
@ -193,7 +200,13 @@ u8 *afl_shm_init(sharedmem_t *shm, size_t map_size,
if (shm->g_shm_fd == -1) { if (shm->g_shm_fd == -1) {
shm->g_shm_fd = shm->g_shm_fd =
shm_open(shm->g_shm_file_path, shmflags | O_CREAT, DEFAULT_PERMISSION); shm_open(shm->g_shm_file_path, shmflags | O_CREAT, permission);
if (gid != -1 && shm->g_shm_fd != -1) {
if (fchown(shm->g_shm_fd, -1, gid) == -1) { PFATAL("fchown() failed"); }
}
} }
@ -234,10 +247,14 @@ u8 *afl_shm_init(sharedmem_t *shm, size_t map_size,
getpid(), random()); getpid(), random());
/* create the shared memory segment as if it was a file */ /* create the shared memory segment as if it was a file */
shm->cmplog_g_shm_fd = shm->cmplog_g_shm_fd = shm_open(shm->cmplog_g_shm_file_path,
shm_open(shm->cmplog_g_shm_file_path, O_CREAT | O_RDWR | O_EXCL, O_CREAT | O_RDWR | O_EXCL, permission);
DEFAULT_PERMISSION);
if (shm->cmplog_g_shm_fd == -1) { PFATAL("shm_open() failed"); } if (shm->cmplog_g_shm_fd == -1) { PFATAL("shm_open() failed"); }
if (gid != -1) {
if (fchown(shm->g_shm_fd, -1, gid) == -1) { PFATAL("fchown() failed"); }
}
/* configure the size of the shared memory segment */ /* configure the size of the shared memory segment */
if (ftruncate(shm->cmplog_g_shm_fd, sizeof(struct cmp_map))) { if (ftruncate(shm->cmplog_g_shm_fd, sizeof(struct cmp_map))) {
@ -274,22 +291,40 @@ u8 *afl_shm_init(sharedmem_t *shm, size_t map_size,
#else #else
u8 *shm_str; u8 *shm_str;
struct shmid_ds shmid_ds;
// for qemu+unicorn we have to increase by 8 to account for potential // for qemu+unicorn we have to increase by 8 to account for potential
// compcov map overwrite // compcov map overwrite
shm->shm_id = shm->shm_id =
shmget(IPC_PRIVATE, map_size == MAP_SIZE ? map_size + 8 : map_size, shmget(IPC_PRIVATE, map_size == MAP_SIZE ? map_size + 8 : map_size,
IPC_CREAT | IPC_EXCL | DEFAULT_PERMISSION); IPC_CREAT | IPC_EXCL | permission);
if (shm->shm_id < 0) { if (shm->shm_id < 0) {
PFATAL("shmget() failed, try running afl-system-config"); PFATAL("shmget() failed, try running afl-system-config");
} }
if (gid != -1) {
if (shmctl(shm->shm_id, IPC_STAT, &shmid_ds) == -1) {
PFATAL("shmctl(IPC_STAT) failed");
}
shmid_ds.shm_perm.gid = (gid_t)gid;
if (shmctl(shm->shm_id, IPC_SET, &shmid_ds) == -1) {
PFATAL("shmctl(IPC_SET) failed");
}
}
if (shm->cmplog_mode) { if (shm->cmplog_mode) {
shm->cmplog_shm_id = shmget(IPC_PRIVATE, sizeof(struct cmp_map), shm->cmplog_shm_id = shmget(IPC_PRIVATE, sizeof(struct cmp_map),
IPC_CREAT | IPC_EXCL | DEFAULT_PERMISSION); IPC_CREAT | IPC_EXCL | permission);
if (shm->cmplog_shm_id < 0) { if (shm->cmplog_shm_id < 0) {
@ -298,6 +333,23 @@ u8 *afl_shm_init(sharedmem_t *shm, size_t map_size,
} }
if (gid != -1) {
if (shmctl(shm->cmplog_shm_id, IPC_STAT, &shmid_ds) == -1) {
PFATAL("shmctl(IPC_STAT) failed");
}
shmid_ds.shm_perm.gid = (gid_t)gid;
if (shmctl(shm->cmplog_shm_id, IPC_SET, &shmid_ds) == -1) {
PFATAL("shmctl(IPC_SET) failed");
}
}
} }
if (!non_instrumented_mode) { if (!non_instrumented_mode) {

View File

@ -1348,7 +1348,7 @@ int main(int argc, char **argv_orig, char **envp) {
fsrv->target_path = find_binary(argv[optind]); fsrv->target_path = find_binary(argv[optind]);
#endif #endif
fsrv->trace_bits = afl_shm_init(&shm, map_size, 0); fsrv->trace_bits = afl_shm_init(&shm, map_size, 0, DEFAULT_PERMISSION, -1);
if (!quiet_mode) { if (!quiet_mode) {
@ -1488,7 +1488,8 @@ int main(int argc, char **argv_orig, char **envp) {
atexit(at_exit_handler); atexit(at_exit_handler);
size_t shm_fuzz_map_size = SHM_FUZZ_MAP_SIZE_DEFAULT; size_t shm_fuzz_map_size = SHM_FUZZ_MAP_SIZE_DEFAULT;
u8 *map = afl_shm_init(shm_fuzz, shm_fuzz_map_size, 1); u8 *map = afl_shm_init(shm_fuzz, SHM_FUZZ_MAP_SIZE_DEFAULT, 1,
DEFAULT_PERMISSION, -1);
shm_fuzz->shmemfuzz_mode = true; shm_fuzz->shmemfuzz_mode = true;
if (!map) { FATAL("BUG: Zero return from afl_shm_init."); } if (!map) { FATAL("BUG: Zero return from afl_shm_init."); }
@ -1550,7 +1551,8 @@ int main(int argc, char **argv_orig, char **envp) {
afl_shm_deinit(&shm); afl_shm_deinit(&shm);
afl_fsrv_kill(fsrv); afl_fsrv_kill(fsrv);
fsrv->map_size = new_map_size; fsrv->map_size = new_map_size;
fsrv->trace_bits = afl_shm_init(&shm, new_map_size, 0); fsrv->trace_bits =
afl_shm_init(&shm, new_map_size, 0, DEFAULT_PERMISSION, -1);
} }

View File

@ -1332,7 +1332,7 @@ int main(int argc, char **argv_orig, char **envp) {
fsrv->target_path = find_binary(argv[optind]); fsrv->target_path = find_binary(argv[optind]);
#endif #endif
fsrv->trace_bits = afl_shm_init(&shm, map_size, 0); fsrv->trace_bits = afl_shm_init(&shm, map_size, 0, DEFAULT_PERMISSION, -1);
detect_file_args(argv + optind, out_file, &fsrv->use_stdin); detect_file_args(argv + optind, out_file, &fsrv->use_stdin);
signal(SIGALRM, kill_child); signal(SIGALRM, kill_child);
@ -1431,7 +1431,8 @@ int main(int argc, char **argv_orig, char **envp) {
shm_fuzz->cmplog_mode = 0; shm_fuzz->cmplog_mode = 0;
size_t shm_fuzz_map_size = SHM_FUZZ_MAP_SIZE_DEFAULT; size_t shm_fuzz_map_size = SHM_FUZZ_MAP_SIZE_DEFAULT;
u8 *map = afl_shm_init(shm_fuzz, shm_fuzz_map_size, 1); u8 *map = afl_shm_init(shm_fuzz, SHM_FUZZ_MAP_SIZE_DEFAULT, 1,
DEFAULT_PERMISSION, -1);
shm_fuzz->shmemfuzz_mode = 1; shm_fuzz->shmemfuzz_mode = 1;
if (!map) { FATAL("BUG: Zero return from afl_shm_init."); } if (!map) { FATAL("BUG: Zero return from afl_shm_init."); }
@ -1502,7 +1503,8 @@ int main(int argc, char **argv_orig, char **envp) {
afl_shm_deinit(&shm); afl_shm_deinit(&shm);
afl_fsrv_kill(fsrv); afl_fsrv_kill(fsrv);
fsrv->map_size = new_map_size; fsrv->map_size = new_map_size;
fsrv->trace_bits = afl_shm_init(&shm, new_map_size, 0); fsrv->trace_bits =
afl_shm_init(&shm, new_map_size, 0, DEFAULT_PERMISSION, -1);
afl_fsrv_start(fsrv, use_argv, &stop_soon, afl_fsrv_start(fsrv, use_argv, &stop_soon,
(get_afl_env("AFL_DEBUG_CHILD") || (get_afl_env("AFL_DEBUG_CHILD") ||
get_afl_env("AFL_DEBUG_CHILD_OUTPUT")) get_afl_env("AFL_DEBUG_CHILD_OUTPUT"))