From 419ac6dafebc697b38018bd22ca7443cce86b57a Mon Sep 17 00:00:00 2001 From: Romain Malmain Date: Mon, 25 Nov 2024 13:07:18 +0100 Subject: [PATCH 1/4] first draft for nyx api support --- accel/tcg/tcg-runtime.c | 4 ++-- accel/tcg/tcg-runtime.h | 4 ++-- accel/tcg/translator.c | 2 +- include/libafl/exit.h | 32 ++++++++++++++++++++------------ libafl/exit.c | 10 +++++----- target/i386/tcg/translate.c | 15 +++++++++++++++ 6 files changed, 45 insertions(+), 22 deletions(-) diff --git a/accel/tcg/tcg-runtime.c b/accel/tcg/tcg-runtime.c index 7a1a189cdd0..96daaed958d 100644 --- a/accel/tcg/tcg-runtime.c +++ b/accel/tcg/tcg-runtime.c @@ -45,10 +45,10 @@ void HELPER(libafl_qemu_handle_breakpoint)(CPUArchState *env, uint64_t pc) libafl_exit_request_breakpoint(cpu, (target_ulong) pc); } -void HELPER(libafl_qemu_handle_sync_backdoor)(CPUArchState *env, uint64_t pc) +void HELPER(libafl_qemu_handle_custom_insn)(CPUArchState *env, uint64_t pc, uint32_t kind) { CPUState* cpu = env_cpu(env); - libafl_exit_request_sync_backdoor(cpu, (target_ulong) pc); + libafl_exit_request_custom_insn(cpu, (target_ulong) pc, (enum libafl_custom_insn_kind) kind); } //// --- End LibAFL code --- diff --git a/accel/tcg/tcg-runtime.h b/accel/tcg/tcg-runtime.h index 27668b61757..3f154ccf76c 100644 --- a/accel/tcg/tcg-runtime.h +++ b/accel/tcg/tcg-runtime.h @@ -329,7 +329,7 @@ DEF_HELPER_FLAGS_5(gvec_bitsel, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32) DEF_HELPER_FLAGS_2(libafl_qemu_handle_breakpoint, TCG_CALL_NO_RWG, void, env, i64) -DEF_HELPER_FLAGS_2(libafl_qemu_handle_sync_backdoor, TCG_CALL_NO_RWG, - void, env, i64) +DEF_HELPER_FLAGS_3(libafl_qemu_handle_custom_insn, TCG_CALL_NO_RWG, + void, env, i64, i32) //// --- End LibAFL code --- diff --git a/accel/tcg/translator.c b/accel/tcg/translator.c index 2f3944b08a3..ac49bcf27cd 100644 --- a/accel/tcg/translator.c +++ b/accel/tcg/translator.c @@ -200,7 +200,7 @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int *max_insns, db->pc_next += 4; TCGv_i64 tmp0 = tcg_constant_i64((uint64_t)db->pc_next); - gen_helper_libafl_qemu_handle_sync_backdoor(tcg_env, tmp0); + gen_helper_libafl_qemu_handle_custom_insn(tcg_env, tmp0, tcg_constant_i32(LIBAFL_CUSTOM_INSN_LIBAFL)); tcg_temp_free_i64(tmp0); } } diff --git a/include/libafl/exit.h b/include/libafl/exit.h index a9cc5c007a7..087e01e5d29 100644 --- a/include/libafl/exit.h +++ b/include/libafl/exit.h @@ -10,16 +10,17 @@ struct libafl_breakpoint { struct libafl_breakpoint* next; }; -int libafl_qemu_set_breakpoint(target_ulong pc); -int libafl_qemu_remove_breakpoint(target_ulong pc); -void libafl_qemu_trigger_breakpoint(CPUState* cpu); -void libafl_qemu_breakpoint_run(vaddr pc_next); - enum libafl_exit_reason_kind { - INTERNAL = 0, - BREAKPOINT = 1, - SYNC_EXIT = 2, - TIMEOUT = 3, + LIBAFL_EXIT_REASON_INTERNAL = 0, + LIBAFL_EXIT_REASON_BREAKPOINT = 1, + LIBAFL_EXIT_REASON_CUSTOM_INSN = 2, + LIBAFL_EXIT_REASON_TIMEOUT = 3, +}; + +enum libafl_custom_insn_kind { + LIBAFL_CUSTOM_INSN_UNDEFINED = 0, + LIBAFL_CUSTOM_INSN_LIBAFL = 1, + LIBAFL_CUSTOM_INSN_NYX = 2, }; // QEMU exited on its own for some reason. @@ -34,7 +35,9 @@ struct libafl_exit_reason_breakpoint { }; // A synchronous exit has been triggered. -struct libafl_exit_reason_sync_exit {}; +struct libafl_exit_reason_custom_insn { + enum libafl_custom_insn_kind kind; +}; // A timeout occured and we were asked to exit on timeout struct libafl_exit_reason_timeout {}; @@ -46,11 +49,16 @@ struct libafl_exit_reason { union { 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_custom_insn custom_insn; // kind == CUSTOM_INSN struct libafl_exit_reason_timeout timeout; // kind == TIMEOUT } data; }; +int libafl_qemu_set_breakpoint(target_ulong pc); +int libafl_qemu_remove_breakpoint(target_ulong pc); +void libafl_qemu_trigger_breakpoint(CPUState* cpu); +void libafl_qemu_breakpoint_run(vaddr pc_next); + // Only makes sense to call if an exit was expected // Will return NULL if there was no exit expected. CPUState* libafl_last_exit_cpu(void); @@ -62,7 +70,7 @@ void libafl_sync_exit_cpu(void); void libafl_exit_request_internal(CPUState* cpu, uint64_t pc, ShutdownCause cause, int signal); void libafl_exit_request_breakpoint(CPUState* cpu, target_ulong pc); -void libafl_exit_request_sync_backdoor(CPUState* cpu, target_ulong pc); +void libafl_exit_request_custom_insn(CPUState* cpu, target_ulong pc, enum libafl_custom_insn_kind kind); #ifndef CONFIG_USER_ONLY void libafl_exit_request_timeout(void); diff --git a/libafl/exit.c b/libafl/exit.c index 27d3444f5a4..e7f71cd8f87 100644 --- a/libafl/exit.c +++ b/libafl/exit.c @@ -101,7 +101,7 @@ CPUState* libafl_last_exit_cpu(void) void libafl_exit_request_internal(CPUState* cpu, uint64_t pc, ShutdownCause cause, int signal) { - last_exit_reason.kind = INTERNAL; + last_exit_reason.kind = LIBAFL_EXIT_REASON_INTERNAL; last_exit_reason.data.internal.cause = cause; last_exit_reason.data.internal.signal = signal; @@ -110,16 +110,16 @@ void libafl_exit_request_internal(CPUState* cpu, uint64_t pc, expected_exit = true; } -void libafl_exit_request_sync_backdoor(CPUState* cpu, target_ulong pc) +void libafl_exit_request_custom_insn(CPUState* cpu, target_ulong pc, enum libafl_custom_insn_kind kind) { - last_exit_reason.kind = SYNC_EXIT; + last_exit_reason.kind = LIBAFL_EXIT_REASON_CUSTOM_INSN; prepare_qemu_exit(cpu, pc); } void libafl_exit_request_breakpoint(CPUState* cpu, target_ulong pc) { - last_exit_reason.kind = BREAKPOINT; + last_exit_reason.kind = LIBAFL_EXIT_REASON_BREAKPOINT; last_exit_reason.data.breakpoint.addr = pc; prepare_qemu_exit(cpu, pc); @@ -129,7 +129,7 @@ void libafl_exit_request_breakpoint(CPUState* cpu, target_ulong pc) void libafl_exit_request_timeout(void) { expected_exit = true; - last_exit_reason.kind = TIMEOUT; + last_exit_reason.kind = LIBAFL_EXIT_REASON_TIMEOUT; last_exit_reason.cpu = current_cpu; qemu_system_debug_request(); diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c index e3172286162..988c640ba76 100644 --- a/target/i386/tcg/translate.c +++ b/target/i386/tcg/translate.c @@ -3287,6 +3287,21 @@ static void disas_insn_old(DisasContext *s, CPUState *cpu, int b) gen_op_st_v(s, CODE64(s) + MO_32, s->T0, s->A0); break; +//// --- Begin LibAFL code --- + case 0xc1: /* vmcall */ + // move pc to T0 + tcg_gen_movi_tl(s->T0, s->pc - s->cs_base); + + // gen jump to next insn + gen_op_jmp_v(s, s->T0); + gen_bnd_jmp(s); + s->base.is_jmp = DISAS_JUMP; + + // gen helper to signal to get out + gen_helper_libafl_qemu_handle_custom_insn(tcg_env, s->T0, tcg_constant_i32(LIBAFL_CUSTOM_INSN_NYX)); + break; +//// --- End LibAFL code --- + case 0xc8: /* monitor */ if (!(s->cpuid_ext_features & CPUID_EXT_MONITOR) || CPL(s) != 0) { goto illegal_op; From 823f5d9a221ea9318ea73bed871d6141c074aff6 Mon Sep 17 00:00:00 2001 From: Romain Malmain Date: Thu, 2 Jan 2025 11:01:57 +0100 Subject: [PATCH 2/4] add nyx support --- include/libafl/exit.h | 8 ++++---- libafl/exit.c | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/include/libafl/exit.h b/include/libafl/exit.h index 087e01e5d29..b79ed6c56f7 100644 --- a/include/libafl/exit.h +++ b/include/libafl/exit.h @@ -11,10 +11,10 @@ struct libafl_breakpoint { }; enum libafl_exit_reason_kind { - LIBAFL_EXIT_REASON_INTERNAL = 0, - LIBAFL_EXIT_REASON_BREAKPOINT = 1, - LIBAFL_EXIT_REASON_CUSTOM_INSN = 2, - LIBAFL_EXIT_REASON_TIMEOUT = 3, + INTERNAL = 0, + BREAKPOINT = 1, + CUSTOM_INSN = 2, + TIMEOUT = 3, }; enum libafl_custom_insn_kind { diff --git a/libafl/exit.c b/libafl/exit.c index e7f71cd8f87..5dfb4dedec6 100644 --- a/libafl/exit.c +++ b/libafl/exit.c @@ -101,7 +101,7 @@ CPUState* libafl_last_exit_cpu(void) void libafl_exit_request_internal(CPUState* cpu, uint64_t pc, ShutdownCause cause, int signal) { - last_exit_reason.kind = LIBAFL_EXIT_REASON_INTERNAL; + last_exit_reason.kind = INTERNAL; last_exit_reason.data.internal.cause = cause; last_exit_reason.data.internal.signal = signal; @@ -112,14 +112,14 @@ void libafl_exit_request_internal(CPUState* cpu, uint64_t pc, void libafl_exit_request_custom_insn(CPUState* cpu, target_ulong pc, enum libafl_custom_insn_kind kind) { - last_exit_reason.kind = LIBAFL_EXIT_REASON_CUSTOM_INSN; + last_exit_reason.kind = CUSTOM_INSN; prepare_qemu_exit(cpu, pc); } void libafl_exit_request_breakpoint(CPUState* cpu, target_ulong pc) { - last_exit_reason.kind = LIBAFL_EXIT_REASON_BREAKPOINT; + last_exit_reason.kind = BREAKPOINT; last_exit_reason.data.breakpoint.addr = pc; prepare_qemu_exit(cpu, pc); @@ -129,7 +129,7 @@ void libafl_exit_request_breakpoint(CPUState* cpu, target_ulong pc) void libafl_exit_request_timeout(void) { expected_exit = true; - last_exit_reason.kind = LIBAFL_EXIT_REASON_TIMEOUT; + last_exit_reason.kind = TIMEOUT; last_exit_reason.cpu = current_cpu; qemu_system_debug_request(); From 81e52dc60f83c3ae191c1a07b39bb255e633c234 Mon Sep 17 00:00:00 2001 From: Romain Malmain Date: Thu, 2 Jan 2025 11:06:12 +0100 Subject: [PATCH 3/4] formatting --- include/libafl/exit.h | 29 ++++++++++++++++------------- include/libafl/tcg.h | 4 ++-- libafl/exit.c | 3 ++- libafl/hooks/tcg/block.c | 3 ++- libafl/hooks/tcg/edge.c | 6 +++--- libafl/hooks/tcg/read_write.c | 3 ++- 6 files changed, 27 insertions(+), 21 deletions(-) diff --git a/include/libafl/exit.h b/include/libafl/exit.h index b79ed6c56f7..2e54c1b44fa 100644 --- a/include/libafl/exit.h +++ b/include/libafl/exit.h @@ -11,16 +11,16 @@ struct libafl_breakpoint { }; enum libafl_exit_reason_kind { - INTERNAL = 0, - BREAKPOINT = 1, - CUSTOM_INSN = 2, - TIMEOUT = 3, + INTERNAL = 0, + BREAKPOINT = 1, + CUSTOM_INSN = 2, + TIMEOUT = 3, }; enum libafl_custom_insn_kind { - LIBAFL_CUSTOM_INSN_UNDEFINED = 0, - LIBAFL_CUSTOM_INSN_LIBAFL = 1, - LIBAFL_CUSTOM_INSN_NYX = 2, + LIBAFL_CUSTOM_INSN_UNDEFINED = 0, + LIBAFL_CUSTOM_INSN_LIBAFL = 1, + LIBAFL_CUSTOM_INSN_NYX = 2, }; // QEMU exited on its own for some reason. @@ -40,17 +40,19 @@ struct libafl_exit_reason_custom_insn { }; // A timeout occured and we were asked to exit on timeout -struct libafl_exit_reason_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; // kind == INTERNAL - struct libafl_exit_reason_breakpoint breakpoint; // kind == BREAKPOINT - struct libafl_exit_reason_custom_insn custom_insn; // kind == CUSTOM_INSN - struct libafl_exit_reason_timeout timeout; // kind == TIMEOUT + struct libafl_exit_reason_internal internal; // kind == INTERNAL + struct libafl_exit_reason_breakpoint breakpoint; // kind == BREAKPOINT + struct libafl_exit_reason_custom_insn + custom_insn; // kind == CUSTOM_INSN + struct libafl_exit_reason_timeout timeout; // kind == TIMEOUT } data; }; @@ -70,7 +72,8 @@ void libafl_sync_exit_cpu(void); void libafl_exit_request_internal(CPUState* cpu, uint64_t pc, ShutdownCause cause, int signal); void libafl_exit_request_breakpoint(CPUState* cpu, target_ulong pc); -void libafl_exit_request_custom_insn(CPUState* cpu, target_ulong pc, enum libafl_custom_insn_kind kind); +void libafl_exit_request_custom_insn(CPUState* cpu, target_ulong pc, + enum libafl_custom_insn_kind kind); #ifndef CONFIG_USER_ONLY void libafl_exit_request_timeout(void); diff --git a/include/libafl/tcg.h b/include/libafl/tcg.h index ea62187094b..2320fb2f933 100644 --- a/include/libafl/tcg.h +++ b/include/libafl/tcg.h @@ -6,5 +6,5 @@ #include "tcg/tcg.h" #include "tcg/helper-info.h" -void tcg_gen_callN(void *func, TCGHelperInfo *info, - TCGTemp *ret, TCGTemp **args); +void tcg_gen_callN(void* func, TCGHelperInfo* info, TCGTemp* ret, + TCGTemp** args); diff --git a/libafl/exit.c b/libafl/exit.c index 5dfb4dedec6..63879d07ab2 100644 --- a/libafl/exit.c +++ b/libafl/exit.c @@ -110,7 +110,8 @@ void libafl_exit_request_internal(CPUState* cpu, uint64_t pc, expected_exit = true; } -void libafl_exit_request_custom_insn(CPUState* cpu, target_ulong pc, enum libafl_custom_insn_kind kind) +void libafl_exit_request_custom_insn(CPUState* cpu, target_ulong pc, + enum libafl_custom_insn_kind kind) { last_exit_reason.kind = CUSTOM_INSN; diff --git a/libafl/hooks/tcg/block.c b/libafl/hooks/tcg/block.c index f7aba26c8ea..465a2e245b0 100644 --- a/libafl/hooks/tcg/block.c +++ b/libafl/hooks/tcg/block.c @@ -81,7 +81,8 @@ void libafl_qemu_hook_block_run(target_ulong pc) TCGv_i64 tmp0 = tcg_constant_i64(hook->data); TCGv_i64 tmp1 = tcg_constant_i64(cur_id); TCGTemp* tmp2[2] = {tcgv_i64_temp(tmp0), tcgv_i64_temp(tmp1)}; - tcg_gen_callN(hook->helper_info.func, &hook->helper_info, NULL, tmp2); + tcg_gen_callN(hook->helper_info.func, &hook->helper_info, NULL, + tmp2); tcg_temp_free_i64(tmp0); tcg_temp_free_i64(tmp1); } diff --git a/libafl/hooks/tcg/edge.c b/libafl/hooks/tcg/edge.c index d5dd5d0bce5..0eadf7a38ca 100644 --- a/libafl/hooks/tcg/edge.c +++ b/libafl/hooks/tcg/edge.c @@ -9,8 +9,7 @@ static TCGHelperInfo libafl_exec_edge_hook_info = { .name = "libafl_exec_edge_hook", .flags = dh_callflag(void), .typemask = - dh_typemask(void, 0) | dh_typemask(i64, 1) | dh_typemask(i64, 2) -}; + dh_typemask(void, 0) | dh_typemask(i64, 1) | dh_typemask(i64, 2)}; GEN_REMOVE_HOOK(edge) @@ -86,7 +85,8 @@ void libafl_qemu_hook_edge_run(void) TCGv_i64 tmp0 = tcg_constant_i64(hook->data); TCGv_i64 tmp1 = tcg_constant_i64(hook->cur_id); TCGTemp* tmp2[2] = {tcgv_i64_temp(tmp0), tcgv_i64_temp(tmp1)}; - tcg_gen_callN(hook->helper_info.func, &hook->helper_info, NULL, tmp2); + tcg_gen_callN(hook->helper_info.func, &hook->helper_info, NULL, + tmp2); tcg_temp_free_i64(tmp0); tcg_temp_free_i64(tmp1); } diff --git a/libafl/hooks/tcg/read_write.c b/libafl/hooks/tcg/read_write.c index 27dc9f5f115..7ffe2c37f51 100644 --- a/libafl/hooks/tcg/read_write.c +++ b/libafl/hooks/tcg/read_write.c @@ -216,7 +216,8 @@ static void libafl_gen_rw(TCGTemp* addr, MemOpIdx oi, #else tcgv_i64_temp(tmp2)}; #endif - tcg_gen_callN(hook->helper_infoN.func, &hook->helper_infoN, NULL, tmp3); + tcg_gen_callN(hook->helper_infoN.func, &hook->helper_infoN, + NULL, tmp3); tcg_temp_free_i64(tmp0); tcg_temp_free_i64(tmp1); #if TARGET_LONG_BITS == 32 From e36195146f9e66d9e5d9a19e134518a36d3c6f6a Mon Sep 17 00:00:00 2001 From: Romain Malmain Date: Thu, 2 Jan 2025 14:46:44 +0100 Subject: [PATCH 4/4] target independent helper call. --- target/i386/tcg/translate.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c index 988c640ba76..7751a324502 100644 --- a/target/i386/tcg/translate.c +++ b/target/i386/tcg/translate.c @@ -3298,7 +3298,9 @@ static void disas_insn_old(DisasContext *s, CPUState *cpu, int b) s->base.is_jmp = DISAS_JUMP; // gen helper to signal to get out - gen_helper_libafl_qemu_handle_custom_insn(tcg_env, s->T0, tcg_constant_i32(LIBAFL_CUSTOM_INSN_NYX)); + TCGv_i64 new_pc = tcg_temp_new_i64(); + tcg_gen_extu_tl_i64(new_pc, s->T0); + gen_helper_libafl_qemu_handle_custom_insn(tcg_env, new_pc, tcg_constant_i32(LIBAFL_CUSTOM_INSN_NYX)); break; //// --- End LibAFL code ---