Skip to content

Commit

Permalink
Early return from libafl edge generation if no exec hooks (#85)
Browse files Browse the repository at this point in the history
* bug with edges in systemmode, not fixed yet

* timeout request only for systemmode
  • Loading branch information
rmalmain authored Sep 20, 2024
1 parent f58a685 commit d663793
Show file tree
Hide file tree
Showing 8 changed files with 68 additions and 26 deletions.
8 changes: 4 additions & 4 deletions accel/tcg/cpu-exec.c
Original file line number Diff line number Diff line change
Expand Up @@ -1039,13 +1039,13 @@ cpu_exec_loop(CPUState *cpu, SyncClocks *sc)

//// --- Begin LibAFL code ---

int has_libafl_edge = 0;
bool libafl_edge_generated = false;
TranslationBlock *edge;

/* See if we can patch the calling TB. */
if (last_tb) {
// tb_add_jump(last_tb, tb_exit, tb);

if (last_tb->jmp_reset_offset[1] != TB_JMP_OFFSET_INVALID) {
mmap_lock();
edge = libafl_gen_edge(cpu, last_tb->pc, pc, tb_exit, cs_base, flags, cflags);
Expand All @@ -1054,7 +1054,7 @@ cpu_exec_loop(CPUState *cpu, SyncClocks *sc)
if (edge) {
tb_add_jump(last_tb, tb_exit, edge);
tb_add_jump(edge, 0, tb);
has_libafl_edge = 1;
libafl_edge_generated = true;
} else {
tb_add_jump(last_tb, tb_exit, tb);
}
Expand All @@ -1063,7 +1063,7 @@ cpu_exec_loop(CPUState *cpu, SyncClocks *sc)
}
}

if (has_libafl_edge) {
if (libafl_edge_generated) {
// execute the edge to make sure to log it the first execution
// the edge will then jump to the translated block
cpu_loop_exec_tb(cpu, edge, pc, &last_tb, &tb_exit);
Expand Down
14 changes: 9 additions & 5 deletions accel/tcg/translate-all.c
Original file line number Diff line number Diff line change
Expand Up @@ -378,11 +378,20 @@ TranslationBlock *libafl_gen_edge(CPUState *cpu, target_ulong src_block,
int64_t ti;
void *host_pc;

// edge hooks generation callbacks
// early check if it should be skipped or not
bool no_exec_hook = libafl_qemu_hook_edge_gen(src_block, dst_block);
if (no_exec_hook) {
// no exec hooks to run for edges, not point in generating a TB
return NULL;
}

target_ulong pc = src_block ^ reverse_bits((target_ulong)exit_n);

assert_memory_lock();
qemu_thread_jit_write();

// TODO: this (get_page_addr_code_hostp) is a bottleneck in systemmode, investigate why
phys_pc = get_page_addr_code_hostp(env, src_block, &host_pc);
phys_pc ^= reverse_bits((tb_page_addr_t)exit_n);

Expand All @@ -401,11 +410,6 @@ TranslationBlock *libafl_gen_edge(CPUState *cpu, target_ulong src_block,
}
QEMU_BUILD_BUG_ON(CF_COUNT_MASK + 1 != TCG_MAX_INSNS);

// edge hooks generation callbacks
bool no_exec_hook = libafl_qemu_hook_edge_gen(src_block, dst_block);
if (no_exec_hook)
return NULL;

buffer_overflow:
assert_no_pages_locked();
tb = tcg_tb_alloc(tcg_ctx);
Expand Down
31 changes: 20 additions & 11 deletions include/libafl/exit.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,13 @@ enum libafl_exit_reason_kind {
INTERNAL = 0,
BREAKPOINT = 1,
SYNC_EXIT = 2,
TIMEOUT = 3,
};

// QEMU exited on its own for some reason.
struct libafl_exit_reason_internal {
ShutdownCause cause;
int signal; // valid if cause == SHUTDOWN_CAUSE_HOST_SIGNAL
};

// A breakpoint has been triggered.
Expand All @@ -29,23 +36,20 @@ struct libafl_exit_reason_breakpoint {
};

// A synchronous exit has been triggered.
struct libafl_exit_reason_sync_exit {
};
struct libafl_exit_reason_sync_exit {};

// QEMU exited on its own for some reason.
struct libafl_exit_reason_internal {
ShutdownCause cause;
int signal; // valid if cause == SHUTDOWN_CAUSE_HOST_SIGNAL
};
// A timeout occured and we were asked to exit on timeout
struct libafl_exit_reason_timeout {};

struct libafl_exit_reason {
enum libafl_exit_reason_kind kind;
CPUState* cpu; // CPU that triggered an exit.
vaddr next_pc; // The PC that should be stored in the CPU when re-entering.
union {
struct libafl_exit_reason_internal internal;
struct libafl_exit_reason_breakpoint breakpoint; // kind == BREAKPOINT
struct libafl_exit_reason_sync_exit sync_exit; // kind == SYNC_EXIT
struct libafl_exit_reason_internal internal; // kind == INTERNAL
struct libafl_exit_reason_breakpoint breakpoint; // kind == BREAKPOINT
struct libafl_exit_reason_sync_exit sync_exit; // kind == SYNC_EXIT
struct libafl_exit_reason_timeout timeout; // kind == TIMEOUT
} data;
};

Expand All @@ -59,6 +63,11 @@ void libafl_sync_exit_cpu(void);

void libafl_exit_request_internal(CPUState* cpu, uint64_t pc,
ShutdownCause cause, int signal);
void libafl_exit_request_sync_backdoor(CPUState* cpu, target_ulong pc);
void libafl_exit_request_breakpoint(CPUState* cpu, target_ulong pc);
void libafl_exit_request_sync_backdoor(CPUState* cpu, target_ulong pc);

#ifndef CONFIG_USER_ONLY
void libafl_exit_request_timeout(void);
#endif

struct libafl_exit_reason* libafl_get_exit_reason(void);
12 changes: 12 additions & 0 deletions libafl/exit.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ static void prepare_qemu_exit(CPUState* cpu, target_ulong next_pc)
qemu_system_debug_request();
cpu->stopped = true; // TODO check if still needed
#endif

// in usermode, this may be called from the syscall hook, thus already out
// of the cpu_exec but still in the cpu_loop
if (cpu->running) {
Expand Down Expand Up @@ -125,6 +126,17 @@ void libafl_exit_request_breakpoint(CPUState* cpu, target_ulong pc)
prepare_qemu_exit(cpu, pc);
}

#ifndef CONFIG_USER_ONLY
void libafl_exit_request_timeout(void)
{
expected_exit = true;
last_exit_reason.kind = TIMEOUT;
last_exit_reason.cpu = current_cpu;

qemu_system_debug_request();
}
#endif

void libafl_qemu_trigger_breakpoint(CPUState* cpu)
{
CPUClass* cc = CPU_GET_CLASS(cpu);
Expand Down
7 changes: 6 additions & 1 deletion libafl/hooks/tcg/block.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,11 @@ void libafl_qemu_hook_block_run(target_ulong pc)

while (hook) {
uint64_t cur_id = 0;
if (hook->gen)

if (hook->gen) {
cur_id = hook->gen(hook->data, pc);
}

if (cur_id != (uint64_t)-1 && hook->helper_info.func) {
TCGv_i64 tmp0 = tcg_constant_i64(hook->data);
TCGv_i64 tmp1 = tcg_constant_i64(cur_id);
Expand All @@ -81,9 +84,11 @@ void libafl_qemu_hook_block_run(target_ulong pc)
tcg_temp_free_i64(tmp0);
tcg_temp_free_i64(tmp1);
}

if (cur_id != (uint64_t)-1 && hook->jit) {
hook->jit(hook->data, cur_id);
}

hook = hook->next;
}
}
11 changes: 9 additions & 2 deletions libafl/hooks/tcg/edge.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,15 +56,22 @@ bool libafl_qemu_hook_edge_gen(target_ulong src_block, target_ulong dst_block)
{
struct libafl_edge_hook* hook = libafl_edge_hooks;
bool no_exec_hook = true;

while (hook) {
hook->cur_id = 0;
if (hook->gen)

if (hook->gen) {
hook->cur_id = hook->gen(hook->data, src_block, dst_block);
}

if (hook->cur_id != (uint64_t)-1 &&
(hook->helper_info.func || hook->jit))
(hook->helper_info.func || hook->jit)) {
no_exec_hook = false;
}

hook = hook->next;
}

return no_exec_hook;
}

Expand Down
4 changes: 2 additions & 2 deletions libafl/syx-snapshot/syx-snapshot.c
Original file line number Diff line number Diff line change
Expand Up @@ -713,8 +713,8 @@ SyxSnapshotCheckResult syx_snapshot_check(SyxSnapshot* ref_snapshot)
void syx_snapshot_root_restore(SyxSnapshot* snapshot)
{
// health check.
CPUState* cpu;
CPU_FOREACH(cpu) { assert(cpu->stopped); }
// CPUState* cpu;
// CPU_FOREACH(cpu) { assert(cpu->stopped); }

bool must_unlock_bql = false;

Expand Down
7 changes: 6 additions & 1 deletion subprojects/libvduse/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,18 @@ add_project_arguments(cc.get_supported_arguments('-Wsign-compare',
'-Wstrict-aliasing'),
native: false, language: 'c')

#### --- Begin LibAFL code ---
keyval = import('keyval')
config_host = keyval.load(meson.global_build_root() / 'config-host.mak')
#### --- End LibAFL code ---

libvduse = static_library('vduse',
files('libvduse.c'),
c_args: '-D_GNU_SOURCE',
pic: 'AS_SHARED_LIB' in config_host)
#### --- Begin LibAFL code ---
pic: 'AS_SHARED_LIB' in config_host
#### --- End LibAFL code ---
)

libvduse_dep = declare_dependency(link_with: libvduse,
include_directories: include_directories('.'))

0 comments on commit d663793

Please sign in to comment.