Skip to content

Commit 285e0f5

Browse files
Merge pull request #16 from realmadsci/afl-exclude-ranges
Add AFL_QEMU_EXCLUDE_RANGES
2 parents e36a30e + b68b4d7 commit 285e0f5

File tree

2 files changed

+82
-52
lines changed

2 files changed

+82
-52
lines changed

accel/tcg/cpu-exec.c

Lines changed: 69 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#include "exec/tb-lookup.h"
3636
#include "exec/log.h"
3737
#include "qemu/main-loop.h"
38+
#include "qemu/selfmap.h"
3839
#if defined(TARGET_I386) && !defined(CONFIG_USER_ONLY)
3940
#include "hw/i386/apic.h"
4041
#endif
@@ -373,12 +374,11 @@ void afl_setup(void) {
373374
if (getenv("AFL_CODE_END"))
374375
afl_end_code = strtoll(getenv("AFL_CODE_END"), NULL, 16);
375376

377+
int have_names = 0;
376378
if (getenv("AFL_QEMU_INST_RANGES")) {
377-
378379
char *str = getenv("AFL_QEMU_INST_RANGES");
379380
char *saveptr1, *saveptr2 = NULL;
380381
char *pt1, *pt2, *pt3 = NULL;
381-
int have_names = 0;
382382

383383
while (1) {
384384

@@ -389,7 +389,7 @@ void afl_setup(void) {
389389
pt2 = strtok_r(pt1, "-", &saveptr2);
390390
pt3 = strtok_r(NULL, "-", &saveptr2);
391391

392-
struct vmrange* n = malloc(sizeof(struct vmrange));
392+
struct vmrange* n = calloc(1, sizeof(struct vmrange));
393393
n->next = afl_instr_code;
394394

395395
if (pt3 == NULL) { // filename
@@ -406,69 +406,91 @@ void afl_setup(void) {
406406
afl_instr_code = n;
407407

408408
}
409-
410-
if (have_names) {
411-
412-
FILE *fp;
413-
char *line = NULL;
414-
size_t len = 0;
415-
ssize_t read;
416-
417-
fp = fopen("/proc/self/maps", "r");
418-
if (fp == NULL) {
419-
fprintf(stderr, "[AFL] ERROR: cannot open /proc/self/maps\n");
420-
exit(1);
409+
}
410+
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;
421438
}
422-
423-
while ((read = getline(&line, &len, fp)) != -1) {
424-
425-
int fields, dev_maj, dev_min, inode;
426-
uint64_t min, max, offset;
427-
char flag_r, flag_w, flag_x, flag_p;
428-
char path[512] = "";
429-
430-
fields = sscanf(line, "%"PRIx64"-%"PRIx64" %c%c%c%c %"PRIx64" %x:%x %d"
431-
" %512s", &min, &max, &flag_r, &flag_w, &flag_x,
432-
&flag_p, &offset, &dev_maj, &dev_min, &inode, path);
433-
434-
if ((fields < 10) || (fields > 11) || !flag_x || !h2g_valid(min))
435-
continue;
436-
439+
440+
afl_instr_code = n;
441+
442+
}
443+
}
444+
445+
if (have_names) {
446+
GSList *map_info = read_self_maps();
447+
for (GSList *s = map_info; s; s = g_slist_next(s)) {
448+
MapInfo *e = (MapInfo *) s->data;
449+
450+
if (h2g_valid(e->start)) {
451+
unsigned long min = e->start;
452+
unsigned long max = e->end;
437453
int flags = page_get_flags(h2g(min));
438-
439-
max = h2g_valid(max - 1) ? max : (uintptr_t)AFL_G2H(GUEST_ADDR_MAX) + 1;
440-
if (page_check_range(h2g(min), max - min, flags) == -1)
441-
continue;
442-
454+
455+
max = h2g_valid(max - 1) ? max : (uintptr_t) AFL_G2H(GUEST_ADDR_MAX) + 1;
456+
457+
if (page_check_range(h2g(min), max - min, flags) == -1) {
458+
continue;
459+
}
460+
461+
// Now that we have a valid guest address region, compare its
462+
// name against the names we care about:
443463
target_ulong gmin = h2g(min);
444464
target_ulong gmax = h2g(max);
445-
465+
446466
struct vmrange* n = afl_instr_code;
447467
while (n) {
448-
if (n->name && strstr(path, n->name)) {
468+
if (n->name && strstr(e->path, n->name)) {
449469
if (gmin < n->start) n->start = gmin;
450470
if (gmax > n->end) n->end = gmax;
451471
break;
452472
}
453473
n = n->next;
454474
}
455-
456475
}
457-
458-
fclose(fp);
459-
460476
}
461-
462-
if (getenv("AFL_DEBUG") && afl_instr_code) {
463-
struct vmrange* n = afl_instr_code;
464-
while (n) {
477+
free_self_maps(map_info);
478+
}
479+
480+
if (getenv("AFL_DEBUG") && afl_instr_code) {
481+
struct vmrange* n = afl_instr_code;
482+
while (n) {
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 {
465488
fprintf(stderr, "Instrument range: 0x%lx-0x%lx (%s)\n",
466489
(unsigned long)n->start, (unsigned long)n->end,
467490
n->name ? n->name : "<noname>");
468-
n = n->next;
469491
}
492+
n = n->next;
470493
}
471-
472494
}
473495

474496
/* Maintain for compatibility */

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)