Skip to content

Commit b68b4d7

Browse files
committed
cpu-exec: Add AFL_QEMU_EXCLUDE_RANGES
This environment variable allows rejection of specific regions from instrumentation. It takes priority over AFL_INST_LIBS and AFL_QEMU_INST_RANGES, so it can be used to poke a "hole" in previously included sections.
1 parent fe6a8da commit b68b4d7

File tree

2 files changed

+56
-8
lines changed

2 files changed

+56
-8
lines changed

accel/tcg/cpu-exec.c

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,40 @@ void afl_setup(void) {
408408
}
409409
}
410410

411+
if (getenv("AFL_QEMU_EXCLUDE_RANGES")) {
412+
char *str = getenv("AFL_QEMU_EXCLUDE_RANGES");
413+
char *saveptr1, *saveptr2 = NULL;
414+
char *pt1, *pt2, *pt3 = NULL;
415+
416+
while (1) {
417+
418+
pt1 = strtok_r(str, ",", &saveptr1);
419+
if (pt1 == NULL) break;
420+
str = NULL;
421+
422+
pt2 = strtok_r(pt1, "-", &saveptr2);
423+
pt3 = strtok_r(NULL, "-", &saveptr2);
424+
425+
struct vmrange* n = calloc(1, sizeof(struct vmrange));
426+
n->exclude = true; // These are "exclusion" regions.
427+
n->next = afl_instr_code;
428+
429+
if (pt3 == NULL) { // filename
430+
have_names = 1;
431+
n->start = (target_ulong)-1;
432+
n->end = 0;
433+
n->name = strdup(pt1);
434+
} else {
435+
n->start = strtoull(pt2, NULL, 16);
436+
n->end = strtoull(pt3, NULL, 16);
437+
n->name = NULL;
438+
}
439+
440+
afl_instr_code = n;
441+
442+
}
443+
}
444+
411445
if (have_names) {
412446
GSList *map_info = read_self_maps();
413447
for (GSList *s = map_info; s; s = g_slist_next(s)) {
@@ -446,9 +480,15 @@ void afl_setup(void) {
446480
if (getenv("AFL_DEBUG") && afl_instr_code) {
447481
struct vmrange* n = afl_instr_code;
448482
while (n) {
449-
fprintf(stderr, "Instrument range: 0x%lx-0x%lx (%s)\n",
450-
(unsigned long)n->start, (unsigned long)n->end,
451-
n->name ? n->name : "<noname>");
483+
if (n->exclude) {
484+
fprintf(stderr, "Exclude range: 0x%lx-0x%lx (%s)\n",
485+
(unsigned long)n->start, (unsigned long)n->end,
486+
n->name ? n->name : "<noname>");
487+
} else {
488+
fprintf(stderr, "Instrument range: 0x%lx-0x%lx (%s)\n",
489+
(unsigned long)n->start, (unsigned long)n->end,
490+
n->name ? n->name : "<noname>");
491+
}
452492
n = n->next;
453493
}
454494
}

qemuafl/common.h

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,12 @@ typedef void (*afl_persistent_hook_fn)(struct api_regs *regs,
7676

7777
/* Declared in afl-qemu-cpu-inl.h */
7878

79+
// This structure is used for tracking which
80+
// code is to be instrumented via afl_instr_code.
7981
struct vmrange {
8082
target_ulong start, end;
8183
char* name;
84+
bool exclude; // Exclude this region rather than include it
8285
struct vmrange* next;
8386
};
8487

@@ -164,14 +167,19 @@ static inline int is_valid_addr(target_ulong addr) {
164167

165168
static inline int afl_must_instrument(target_ulong addr) {
166169

170+
// Reject any exclusion regions
171+
for (struct vmrange* n = afl_instr_code; n; n = n->next) {
172+
if (n->exclude && addr < n->end && addr >= n->start)
173+
return 0;
174+
}
175+
176+
// Check for inclusion in instrumentation regions
167177
if (addr < afl_end_code && addr >= afl_start_code)
168178
return 1;
169-
170-
struct vmrange* n = afl_instr_code;
171-
while(n) {
172-
if (addr < n->end && addr >= n->start)
179+
180+
for (struct vmrange* n = afl_instr_code; n; n = n->next) {
181+
if (!n->exclude && addr < n->end && addr >= n->start)
173182
return 1;
174-
n = n->next;
175183
}
176184

177185
return 0;

0 commit comments

Comments
 (0)