From e61d1f93b0d8b7ce42a2d2ec46ad5896f09b0481 Mon Sep 17 00:00:00 2001 From: Andrea Fioraldi Date: Wed, 22 Nov 2023 14:25:03 +0100 Subject: [PATCH] Refactor hooks and multiple newthread/syscalls hooks --- accel/tcg/translate-all.c | 573 +------------------------------------- accel/tcg/translator.c | 36 +-- cpu-target.c | 166 +---------- gdbstub/gdbstub.c | 4 +- gdbstub/internals.h | 2 +- gdbstub/system.c | 2 +- gdbstub/user-target.c | 2 +- libafl_extras/exit.c | 38 +++ libafl_extras/exit.h | 13 + libafl_extras/hook.c | 560 +++++++++++++++++++++++++++++++++++++ libafl_extras/hook.h | 198 +++++++++++++ libafl_extras/meson.build | 2 +- linux-user/syscall.c | 84 +++--- 13 files changed, 873 insertions(+), 807 deletions(-) create mode 100644 libafl_extras/hook.c create mode 100644 libafl_extras/hook.h diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c index c524124b9e..63ff70bcfe 100644 --- a/accel/tcg/translate-all.c +++ b/accel/tcg/translate-all.c @@ -68,558 +68,7 @@ //// --- Begin LibAFL code --- -#include "tcg/tcg-op.h" -#include "tcg/tcg-internal.h" -#include "exec/helper-head.h" - -#include "tcg/tcg-temp-internal.h" - -#ifndef TARGET_LONG_BITS -#error "TARGET_LONG_BITS not defined" -#endif - -void tcg_gen_callN(TCGHelperInfo *info, TCGTemp *ret, TCGTemp **args); - -target_ulong libafl_gen_cur_pc; - -TranslationBlock *libafl_gen_edge(CPUState *cpu, target_ulong src_block, - target_ulong dst_block, int exit_n, - target_ulong cs_base, uint32_t flags, - int cflags); -void libafl_gen_read(TCGTemp *addr, MemOpIdx oi); -void libafl_gen_write(TCGTemp *addr, MemOpIdx oi); -void libafl_gen_cmp(target_ulong pc, TCGv op0, TCGv op1, MemOp ot); -void libafl_gen_backdoor(target_ulong pc); - -static TCGHelperInfo libafl_exec_edge_hook_info = { - .func = NULL, .name = "libafl_exec_edge_hook", \ - .flags = dh_callflag(void), \ - .typemask = dh_typemask(void, 0) | dh_typemask(i64, 1) | dh_typemask(i64, 2) -}; - -struct libafl_edge_hook { - uint64_t (*gen)(target_ulong src, target_ulong dst, uint64_t data); - void (*exec)(uint64_t id, uint64_t data); - uint64_t data; - uint64_t cur_id; - TCGHelperInfo helper_info; - struct libafl_edge_hook* next; -}; - -struct libafl_edge_hook* libafl_edge_hooks; - -void libafl_add_edge_hook(uint64_t (*gen)(target_ulong src, target_ulong dst, uint64_t data), - void (*exec)(uint64_t id, uint64_t data), - uint64_t data); -void libafl_add_edge_hook(uint64_t (*gen)(target_ulong src, target_ulong dst, uint64_t data), - void (*exec)(uint64_t id, uint64_t data), - uint64_t data) -{ - CPUState *cpu; - CPU_FOREACH(cpu) { - tb_flush(cpu); - } - - struct libafl_edge_hook* hook = malloc(sizeof(struct libafl_edge_hook)); - hook->gen = gen; - hook->exec = exec; - hook->data = data; - hook->next = libafl_edge_hooks; - libafl_edge_hooks = hook; - - if (exec) { - memcpy(&hook->helper_info, &libafl_exec_edge_hook_info, sizeof(TCGHelperInfo)); - hook->helper_info.func = exec; - } -} - -static TCGHelperInfo libafl_exec_block_hook_info = { - .func = NULL, .name = "libafl_exec_block_hook", \ - .flags = dh_callflag(void), \ - .typemask = dh_typemask(void, 0) | dh_typemask(i64, 1) | dh_typemask(i64, 2) -}; - -struct libafl_block_hook { - uint64_t (*gen)(target_ulong pc, uint64_t data); - void (*post_gen)(target_ulong pc, target_ulong block_length, uint64_t data); - void (*exec)(uint64_t id, uint64_t data); - uint64_t data; - TCGHelperInfo helper_info; - struct libafl_block_hook* next; -}; - -struct libafl_block_hook* libafl_block_hooks; - -void libafl_add_block_hook(uint64_t (*gen)(target_ulong pc, uint64_t data), - void (*post_gen)(target_ulong pc, target_ulong block_length, uint64_t data), - void (*exec)(uint64_t id, uint64_t data), uint64_t data); -void libafl_add_block_hook(uint64_t (*gen)(target_ulong pc, uint64_t data), - void (*post_gen)(target_ulong pc, target_ulong block_length, uint64_t data), - void (*exec)(uint64_t id, uint64_t data), uint64_t data) -{ - CPUState *cpu; - CPU_FOREACH(cpu) { - tb_flush(cpu); - } - - struct libafl_block_hook* hook = malloc(sizeof(struct libafl_block_hook)); - hook->gen = gen; - hook->post_gen = post_gen; - hook->exec = exec; - hook->data = data; - hook->next = libafl_block_hooks; - libafl_block_hooks = hook; - - if (exec) { - memcpy(&hook->helper_info, &libafl_exec_block_hook_info, sizeof(TCGHelperInfo)); - hook->helper_info.func = exec; - } -} - -static TCGHelperInfo libafl_exec_read_hook1_info = { - .func = NULL, .name = "libafl_exec_read_hook1", \ - .flags = dh_callflag(void), \ - .typemask = dh_typemask(void, 0) | dh_typemask(i64, 1) | dh_typemask(tl, 2) | dh_typemask(i64, 3) -}; -static TCGHelperInfo libafl_exec_read_hook2_info = { - .func = NULL, .name = "libafl_exec_read_hook2", \ - .flags = dh_callflag(void), \ - .typemask = dh_typemask(void, 0) | dh_typemask(i64, 1) | dh_typemask(tl, 2) | dh_typemask(i64, 3) -}; -static TCGHelperInfo libafl_exec_read_hook4_info = { - .func = NULL, .name = "libafl_exec_read_hook4", \ - .flags = dh_callflag(void), \ - .typemask = dh_typemask(void, 0) | dh_typemask(i64, 1) | dh_typemask(tl, 2) | dh_typemask(i64, 3) -}; -static TCGHelperInfo libafl_exec_read_hook8_info = { - .func = NULL, .name = "libafl_exec_read_hook8", \ - .flags = dh_callflag(void), \ - .typemask = dh_typemask(void, 0) | dh_typemask(i64, 1) | dh_typemask(tl, 2) | dh_typemask(i64, 3) -}; -static TCGHelperInfo libafl_exec_read_hookN_info = { - .func = NULL, .name = "libafl_exec_read_hookN", \ - .flags = dh_callflag(void), \ - .typemask = dh_typemask(void, 0) | dh_typemask(i64, 1) | dh_typemask(tl, 2) - | dh_typemask(i64, 3) | dh_typemask(i64, 4) -}; -static TCGHelperInfo libafl_exec_write_hook1_info = { - .func = NULL, .name = "libafl_exec_write_hook1", \ - .flags = dh_callflag(void), \ - .typemask = dh_typemask(void, 0) | dh_typemask(i64, 1) | dh_typemask(tl, 2) | dh_typemask(i64, 3) -}; -static TCGHelperInfo libafl_exec_write_hook2_info = { - .func = NULL, .name = "libafl_exec_write_hook2", \ - .flags = dh_callflag(void), \ - .typemask = dh_typemask(void, 0) | dh_typemask(i64, 1) | dh_typemask(tl, 2) | dh_typemask(i64, 3) -}; -static TCGHelperInfo libafl_exec_write_hook4_info = { - .func = NULL, .name = "libafl_exec_write_hook4", \ - .flags = dh_callflag(void), \ - .typemask = dh_typemask(void, 0) | dh_typemask(i64, 1) | dh_typemask(tl, 2) | dh_typemask(i64, 3) -}; -static TCGHelperInfo libafl_exec_write_hook8_info = { - .func = NULL, .name = "libafl_exec_write_hook8", \ - .flags = dh_callflag(void), \ - .typemask = dh_typemask(void, 0) | dh_typemask(i64, 1) | dh_typemask(tl, 2) | dh_typemask(i64, 3) -}; -static TCGHelperInfo libafl_exec_write_hookN_info = { - .func = NULL, .name = "libafl_exec_write_hookN", \ - .flags = dh_callflag(void), \ - .typemask = dh_typemask(void, 0) | dh_typemask(i64, 1) | dh_typemask(tl, 2) - | dh_typemask(i64, 3) | dh_typemask(i64, 4) -}; - -struct libafl_rw_hook { - uint64_t (*gen)(target_ulong pc, MemOpIdx oi, uint64_t data); - void (*exec1)(uint64_t id, target_ulong addr, uint64_t data); - void (*exec2)(uint64_t id, target_ulong addr, uint64_t data); - void (*exec4)(uint64_t id, target_ulong addr, uint64_t data); - void (*exec8)(uint64_t id, target_ulong addr, uint64_t data); - void (*execN)(uint64_t id, target_ulong addr, size_t size, uint64_t data); - uint64_t data; - TCGHelperInfo helper_info1; - TCGHelperInfo helper_info2; - TCGHelperInfo helper_info4; - TCGHelperInfo helper_info8; - TCGHelperInfo helper_infoN; - struct libafl_rw_hook* next; -}; - -struct libafl_rw_hook* libafl_read_hooks; - -void libafl_add_read_hook(uint64_t (*gen)(target_ulong pc, MemOpIdx oi, uint64_t data), - void (*exec1)(uint64_t id, target_ulong addr, uint64_t data), - void (*exec2)(uint64_t id, target_ulong addr, uint64_t data), - void (*exec4)(uint64_t id, target_ulong addr, uint64_t data), - void (*exec8)(uint64_t id, target_ulong addr, uint64_t data), - void (*execN)(uint64_t id, target_ulong addr, size_t size, uint64_t data), - uint64_t data); -void libafl_add_read_hook(uint64_t (*gen)(target_ulong pc, MemOpIdx oi, uint64_t data), - void (*exec1)(uint64_t id, target_ulong addr, uint64_t data), - void (*exec2)(uint64_t id, target_ulong addr, uint64_t data), - void (*exec4)(uint64_t id, target_ulong addr, uint64_t data), - void (*exec8)(uint64_t id, target_ulong addr, uint64_t data), - void (*execN)(uint64_t id, target_ulong addr, size_t size, uint64_t data), - uint64_t data) -{ - CPUState *cpu; - CPU_FOREACH(cpu) { - tb_flush(cpu); - } - - struct libafl_rw_hook* hook = malloc(sizeof(struct libafl_rw_hook)); - hook->gen = gen; - hook->exec1 = exec1; - hook->exec2 = exec2; - hook->exec4 = exec4; - hook->exec8 = exec8; - hook->execN = execN; - hook->data = data; - hook->next = libafl_read_hooks; - libafl_read_hooks = hook; - - if (exec1) { - memcpy(&hook->helper_info1, &libafl_exec_read_hook1_info, sizeof(TCGHelperInfo)); - hook->helper_info1.func = exec1; - } - if (exec2) { - memcpy(&hook->helper_info2, &libafl_exec_read_hook2_info, sizeof(TCGHelperInfo)); - hook->helper_info2.func = exec2; - } - if (exec4) { - memcpy(&hook->helper_info4, &libafl_exec_read_hook4_info, sizeof(TCGHelperInfo)); - hook->helper_info4.func = exec4; - } - if (exec8) { - memcpy(&hook->helper_info8, &libafl_exec_read_hook8_info, sizeof(TCGHelperInfo)); - hook->helper_info8.func = exec8; - } - if (execN) { - memcpy(&hook->helper_infoN, &libafl_exec_read_hookN_info, sizeof(TCGHelperInfo)); - hook->helper_infoN.func = execN; - } -} - -void libafl_gen_read(TCGTemp *addr, MemOpIdx oi) -{ - size_t size = memop_size(get_memop(oi)); - - struct libafl_rw_hook* hook = libafl_read_hooks; - while (hook) { - uint64_t cur_id = 0; - if (hook->gen) - cur_id = hook->gen(libafl_gen_cur_pc, oi, hook->data); - TCGHelperInfo* info = NULL; - if (size == 1 && hook->exec1) info = &hook->helper_info1; - else if (size == 2 && hook->exec2) info = &hook->helper_info2; - else if (size == 4 && hook->exec4) info = &hook->helper_info4; - else if (size == 8 && hook->exec8) info = &hook->helper_info8; - if (cur_id != (uint64_t)-1) { - if (info) { - TCGv_i64 tmp0 = tcg_constant_i64(cur_id); - TCGv_i64 tmp1 = tcg_constant_i64(hook->data); - TCGTemp *tmp2[3] = { tcgv_i64_temp(tmp0), - addr, - tcgv_i64_temp(tmp1) }; - tcg_gen_callN(info, NULL, tmp2); - tcg_temp_free_i64(tmp0); - tcg_temp_free_i64(tmp1); - } else if (hook->execN) { - TCGv_i64 tmp0 = tcg_constant_i64(cur_id); - TCGv tmp1 = tcg_constant_tl(size); - TCGv_i64 tmp2 = tcg_constant_i64(hook->data); - TCGTemp *tmp3[4] = { tcgv_i64_temp(tmp0), - addr, -#if TARGET_LONG_BITS == 32 - tcgv_i32_temp(tmp1), -#else - tcgv_i64_temp(tmp1), -#endif - tcgv_i64_temp(tmp2) }; - tcg_gen_callN(&hook->helper_infoN, NULL, tmp3); - tcg_temp_free_i64(tmp0); -#if TARGET_LONG_BITS == 32 - tcg_temp_free_i32(tmp1); -#else - tcg_temp_free_i64(tmp1); -#endif - tcg_temp_free_i64(tmp2); - } - } - hook = hook->next; - } -} - -struct libafl_rw_hook* libafl_write_hooks; - -void libafl_add_write_hook(uint64_t (*gen)(target_ulong pc, MemOpIdx oi, uint64_t data), - void (*exec1)(uint64_t id, target_ulong addr, uint64_t data), - void (*exec2)(uint64_t id, target_ulong addr, uint64_t data), - void (*exec4)(uint64_t id, target_ulong addr, uint64_t data), - void (*exec8)(uint64_t id, target_ulong addr, uint64_t data), - void (*execN)(uint64_t id, target_ulong addr, size_t size, uint64_t data), - uint64_t data); -void libafl_add_write_hook(uint64_t (*gen)(target_ulong pc, MemOpIdx oi, uint64_t data), - void (*exec1)(uint64_t id, target_ulong addr, uint64_t data), - void (*exec2)(uint64_t id, target_ulong addr, uint64_t data), - void (*exec4)(uint64_t id, target_ulong addr, uint64_t data), - void (*exec8)(uint64_t id, target_ulong addr, uint64_t data), - void (*execN)(uint64_t id, target_ulong addr, size_t size, uint64_t data), - uint64_t data) -{ - CPUState *cpu; - CPU_FOREACH(cpu) { - tb_flush(cpu); - } - - struct libafl_rw_hook* hook = malloc(sizeof(struct libafl_rw_hook)); - hook->gen = gen; - hook->exec1 = exec1; - hook->exec2 = exec2; - hook->exec4 = exec4; - hook->exec8 = exec8; - hook->execN = execN; - hook->data = data; - hook->next = libafl_write_hooks; - libafl_write_hooks = hook; - - if (exec1) { - memcpy(&hook->helper_info1, &libafl_exec_write_hook1_info, sizeof(TCGHelperInfo)); - hook->helper_info1.func = exec1; - } - if (exec2) { - memcpy(&hook->helper_info2, &libafl_exec_write_hook2_info, sizeof(TCGHelperInfo)); - hook->helper_info2.func = exec2; - } - if (exec4) { - memcpy(&hook->helper_info4, &libafl_exec_write_hook4_info, sizeof(TCGHelperInfo)); - hook->helper_info4.func = exec4; - } - if (exec8) { - memcpy(&hook->helper_info8, &libafl_exec_write_hook8_info, sizeof(TCGHelperInfo)); - hook->helper_info8.func = exec8; - } - if (execN) { - memcpy(&hook->helper_infoN, &libafl_exec_write_hookN_info, sizeof(TCGHelperInfo)); - hook->helper_infoN.func = execN; - } -} - -void libafl_gen_write(TCGTemp *addr, MemOpIdx oi) -{ - size_t size = memop_size(get_memop(oi)); - - struct libafl_rw_hook* hook = libafl_write_hooks; - while (hook) { - uint64_t cur_id = 0; - if (hook->gen) - cur_id = hook->gen(libafl_gen_cur_pc, oi, hook->data); - TCGHelperInfo* info = NULL; - if (size == 1 && hook->exec1) info = &hook->helper_info1; - else if (size == 2 && hook->exec2) info = &hook->helper_info2; - else if (size == 4 && hook->exec4) info = &hook->helper_info4; - else if (size == 8 && hook->exec8) info = &hook->helper_info8; - if (cur_id != (uint64_t)-1) { - if (info) { - TCGv_i64 tmp0 = tcg_constant_i64(cur_id); - TCGv_i64 tmp1 = tcg_constant_i64(hook->data); - TCGTemp *tmp2[3] = { tcgv_i64_temp(tmp0), - addr, - tcgv_i64_temp(tmp1) }; - tcg_gen_callN(info, NULL, tmp2); - tcg_temp_free_i64(tmp0); - tcg_temp_free_i64(tmp1); - } else if (hook->execN) { - TCGv_i64 tmp0 = tcg_constant_i64(cur_id); - TCGv tmp1 = tcg_constant_tl(size); - TCGv_i64 tmp2 = tcg_constant_i64(hook->data); - TCGTemp *tmp3[4] = { tcgv_i64_temp(tmp0), - addr, -#if TARGET_LONG_BITS == 32 - tcgv_i32_temp(tmp1), -#else - tcgv_i64_temp(tmp1), -#endif - tcgv_i64_temp(tmp2) }; - tcg_gen_callN(&hook->helper_infoN, NULL, tmp3); - tcg_temp_free_i64(tmp0); -#if TARGET_LONG_BITS == 32 - tcg_temp_free_i32(tmp1); -#else - tcg_temp_free_i64(tmp1); -#endif - tcg_temp_free_i64(tmp2); - } - } - hook = hook->next; - } -} - -static TCGHelperInfo libafl_exec_cmp_hook1_info = { - .func = NULL, .name = "libafl_exec_cmp_hook1", \ - .flags = dh_callflag(void), \ - .typemask = dh_typemask(void, 0) | dh_typemask(i64, 1) - | dh_typemask(tl, 2) | dh_typemask(tl, 3) | dh_typemask(i64, 4) -}; -static TCGHelperInfo libafl_exec_cmp_hook2_info = { - .func = NULL, .name = "libafl_exec_cmp_hook2", \ - .flags = dh_callflag(void), \ - .typemask = dh_typemask(void, 0) | dh_typemask(i64, 1) - | dh_typemask(tl, 2) | dh_typemask(tl, 3) | dh_typemask(i64, 4) -}; -static TCGHelperInfo libafl_exec_cmp_hook4_info = { - .func = NULL, .name = "libafl_exec_cmp_hook4", \ - .flags = dh_callflag(void), \ - .typemask = dh_typemask(void, 0) | dh_typemask(i64, 1) - | dh_typemask(tl, 2) | dh_typemask(tl, 3) | dh_typemask(i64, 4) -}; -static TCGHelperInfo libafl_exec_cmp_hook8_info = { - .func = NULL, .name = "libafl_exec_cmp_hook8", \ - .flags = dh_callflag(void), \ - .typemask = dh_typemask(void, 0) | dh_typemask(i64, 1) - | dh_typemask(tl, 2) | dh_typemask(tl, 3) | dh_typemask(i64, 4) -}; - -struct libafl_cmp_hook { - uint64_t (*gen)(target_ulong pc, size_t size, uint64_t data); - void (*exec1)(uint64_t id, uint8_t v0, uint8_t v1, uint64_t data); - void (*exec2)(uint64_t id, uint16_t v0, uint16_t v1, uint64_t data); - void (*exec4)(uint64_t id, uint32_t v0, uint32_t v1, uint64_t data); - void (*exec8)(uint64_t id, uint64_t v0, uint64_t v1, uint64_t data); - uint64_t data; - TCGHelperInfo helper_info1; - TCGHelperInfo helper_info2; - TCGHelperInfo helper_info4; - TCGHelperInfo helper_info8; - struct libafl_cmp_hook* next; -}; - -struct libafl_cmp_hook* libafl_cmp_hooks; - -void libafl_add_cmp_hook(uint64_t (*gen)(target_ulong pc, size_t size, uint64_t data), - void (*exec1)(uint64_t id, uint8_t v0, uint8_t v1, uint64_t data), - void (*exec2)(uint64_t id, uint16_t v0, uint16_t v1, uint64_t data), - void (*exec4)(uint64_t id, uint32_t v0, uint32_t v1, uint64_t data), - void (*exec8)(uint64_t id, uint64_t v0, uint64_t v1, uint64_t data), - uint64_t data); -void libafl_add_cmp_hook(uint64_t (*gen)(target_ulong pc, size_t size, uint64_t data), - void (*exec1)(uint64_t id, uint8_t v0, uint8_t v1, uint64_t data), - void (*exec2)(uint64_t id, uint16_t v0, uint16_t v1, uint64_t data), - void (*exec4)(uint64_t id, uint32_t v0, uint32_t v1, uint64_t data), - void (*exec8)(uint64_t id, uint64_t v0, uint64_t v1, uint64_t data), - uint64_t data) -{ - CPUState *cpu; - CPU_FOREACH(cpu) { - tb_flush(cpu); - } - - struct libafl_cmp_hook* hook = malloc(sizeof(struct libafl_cmp_hook)); - hook->gen = gen; - hook->exec1 = exec1; - hook->exec2 = exec2; - hook->exec4 = exec4; - hook->exec8 = exec8; - hook->data = data; - hook->next = libafl_cmp_hooks; - libafl_cmp_hooks = hook; - - if (exec1) { - memcpy(&hook->helper_info1, &libafl_exec_cmp_hook1_info, sizeof(TCGHelperInfo)); - hook->helper_info1.func = exec1; - } - if (exec2) { - memcpy(&hook->helper_info2, &libafl_exec_cmp_hook2_info, sizeof(TCGHelperInfo)); - hook->helper_info2.func = exec2; - } - if (exec4) { - memcpy(&hook->helper_info4, &libafl_exec_cmp_hook4_info, sizeof(TCGHelperInfo)); - hook->helper_info4.func = exec4; - } - if (exec8) { - memcpy(&hook->helper_info8, &libafl_exec_cmp_hook8_info, sizeof(TCGHelperInfo)); - hook->helper_info8.func = exec8; - } -} - - -void libafl_gen_cmp(target_ulong pc, TCGv op0, TCGv op1, MemOp ot) -{ - size_t size = 0; - switch (ot & MO_SIZE) { - case MO_64: - size = 8; - break; - case MO_32: - size = 4; - break; - case MO_16: - size = 2; - break; - case MO_8: - size = 1; - break; - default: - return; - } - - struct libafl_cmp_hook* hook = libafl_cmp_hooks; - while (hook) { - uint64_t cur_id = 0; - if (hook->gen) - cur_id = hook->gen(pc, size, hook->data); - TCGHelperInfo* info = NULL; - if (size == 1 && hook->exec1) info = &hook->helper_info1; - else if (size == 2 && hook->exec2) info = &hook->helper_info2; - else if (size == 4 && hook->exec4) info = &hook->helper_info4; - else if (size == 8 && hook->exec8) info = &hook->helper_info8; - if (cur_id != (uint64_t)-1 && info) { - TCGv_i64 tmp0 = tcg_constant_i64(cur_id); - TCGv_i64 tmp1 = tcg_constant_i64(hook->data); - TCGTemp *tmp2[4] = { tcgv_i64_temp(tmp0), -#if TARGET_LONG_BITS == 32 - tcgv_i32_temp(op0), tcgv_i32_temp(op1), -#else - tcgv_i64_temp(op0), tcgv_i64_temp(op1), -#endif - tcgv_i64_temp(tmp1) }; - tcg_gen_callN(info, NULL, tmp2); - tcg_temp_free_i64(tmp0); - tcg_temp_free_i64(tmp1); - } - hook = hook->next; - } -} - -static TCGHelperInfo libafl_exec_backdoor_hook_info = { - .func = NULL, .name = "libafl_exec_backdoor_hook", \ - .flags = dh_callflag(void), \ - .typemask = dh_typemask(void, 0) | dh_typemask(tl, 1) | dh_typemask(i64, 2) -}; - -struct libafl_backdoor_hook { - void (*exec)(target_ulong pc, uint64_t data); - uint64_t data; - TCGHelperInfo helper_info; - struct libafl_backdoor_hook* next; -}; - -struct libafl_backdoor_hook* libafl_backdoor_hooks; - -void libafl_add_backdoor_hook(void (*exec)(target_ulong pc, uint64_t data), - uint64_t data); -void libafl_add_backdoor_hook(void (*exec)(target_ulong id, uint64_t data), - uint64_t data) -{ - struct libafl_backdoor_hook* hook = malloc(sizeof(struct libafl_backdoor_hook)); - hook->exec = exec; - hook->data = data; - hook->next = libafl_backdoor_hooks; - libafl_backdoor_hooks = hook; - - memcpy(&hook->helper_info, &libafl_exec_backdoor_hook_info, sizeof(TCGHelperInfo)); - hook->helper_info.func = exec; -} +#include "libafl_extras/hook.h" //// --- End LibAFL code --- @@ -840,10 +289,10 @@ static int setjmp_gen_code(CPUArchState *env, TranslationBlock *tb, while (hook) { uint64_t cur_id = 0; if (hook->gen) - cur_id = hook->gen(pc, hook->data); - if (cur_id != (uint64_t)-1 && hook->exec) { - TCGv_i64 tmp0 = tcg_constant_i64(cur_id); - TCGv_i64 tmp1 = tcg_constant_i64(hook->data); + 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); TCGTemp *tmp2[2] = { tcgv_i64_temp(tmp0), tcgv_i64_temp(tmp1) }; tcg_gen_callN(&hook->helper_info, NULL, tmp2); tcg_temp_free_i64(tmp0); @@ -912,8 +361,8 @@ TranslationBlock *libafl_gen_edge(CPUState *cpu, target_ulong src_block, while (hook) { hook->cur_id = 0; if (hook->gen) - hook->cur_id = hook->gen(src_block, dst_block, hook->data); - if (hook->cur_id != (uint64_t)-1 && hook->exec) + hook->cur_id = hook->gen(hook->data, src_block, dst_block); + if (hook->cur_id != (uint64_t)-1 && hook->helper_info.func) no_exec_hook = 0; hook = hook->next; } @@ -970,10 +419,10 @@ TranslationBlock *libafl_gen_edge(CPUState *cpu, target_ulong src_block, hook = libafl_edge_hooks; size_t hcount = 0; while (hook) { - if (hook->cur_id != (uint64_t)-1 && hook->exec) { + if (hook->cur_id != (uint64_t)-1 && hook->helper_info.func) { hcount++; - TCGv_i64 tmp0 = tcg_constant_i64(hook->cur_id); - TCGv_i64 tmp1 = tcg_constant_i64(hook->data); + 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, NULL, tmp2); tcg_temp_free_i64(tmp0); @@ -1193,7 +642,7 @@ TranslationBlock *tb_gen_code(CPUState *cpu, while (hook) { if (hook->post_gen) - hook->post_gen(pc, tb->size, hook->data); + hook->post_gen(hook->data, pc, tb->size); hook = hook->next; } diff --git a/accel/tcg/translator.c b/accel/tcg/translator.c index e32b2e0789..5fddf18bf9 100644 --- a/accel/tcg/translator.c +++ b/accel/tcg/translator.c @@ -114,45 +114,13 @@ static void gen_tb_end(const TranslationBlock *tb, uint32_t cflags, //// --- Begin LibAFL code --- -#include "tcg/tcg-internal.h" -#include "tcg/tcg-temp-internal.h" +#include "libafl_extras/exit.h" +#include "libafl_extras/hook.h" #ifndef TARGET_LONG_BITS #error "TARGET_LONG_BITS not defined" #endif -void tcg_gen_callN(TCGHelperInfo *info, TCGTemp *ret, TCGTemp **args); - -extern target_ulong libafl_gen_cur_pc; - -struct libafl_breakpoint { - target_ulong addr; - struct libafl_breakpoint* next; -}; - -extern struct libafl_breakpoint* libafl_qemu_breakpoints; - -struct libafl_hook { - target_ulong addr; - void (*callback)(uint64_t); - uint64_t data; - TCGHelperInfo helper_info; - struct libafl_hook* next; -}; - -extern struct libafl_hook* libafl_qemu_hooks; - -struct libafl_hook* libafl_search_hook(target_ulong addr); - -struct libafl_backdoor_hook { - void (*exec)(target_ulong pc, uint64_t data); - uint64_t data; - TCGHelperInfo helper_info; - struct libafl_backdoor_hook* next; -}; - -extern struct libafl_backdoor_hook* libafl_backdoor_hooks; - //// --- End LibAFL code --- bool translator_use_goto_tb(DisasContextBase *db, vaddr dest) diff --git a/cpu-target.c b/cpu-target.c index 8b8c90327c..52a2516b37 100644 --- a/cpu-target.c +++ b/cpu-target.c @@ -45,32 +45,8 @@ //// --- Begin LibAFL code --- -#include "tcg/tcg-op.h" -#include "tcg/tcg-internal.h" -#include "exec/helper-head.h" #include "libafl_extras/exit.h" - -#define LIBAFL_TABLES_SIZE 16384 -#define LIBAFL_TABLES_HASH(p) (((13*((size_t)(p))) ^ (((size_t)(p)) >> 15)) % LIBAFL_TABLES_SIZE) - -struct libafl_breakpoint { - target_ulong addr; - struct libafl_breakpoint* next; -}; - -struct libafl_breakpoint* libafl_qemu_breakpoints = NULL; - -struct libafl_hook { - target_ulong addr; - void (*callback)(target_ulong, uint64_t); - uint64_t data; - TCGHelperInfo helper_info; - size_t num; - struct libafl_hook* next; -}; - -struct libafl_hook* libafl_qemu_hooks[LIBAFL_TABLES_SIZE]; -size_t libafl_qemu_hooks_num = 0; +#include "libafl_extras/hook.h" static __thread GByteArray *libafl_qemu_mem_buf = NULL; @@ -85,13 +61,6 @@ int libafl_qemu_write_reg(CPUState* cpu, int reg, uint8_t* val); int libafl_qemu_read_reg(CPUState* cpu, int reg, uint8_t* val); int libafl_qemu_num_regs(CPUState* cpu); -int libafl_qemu_set_breakpoint(target_ulong addr); -int libafl_qemu_remove_breakpoint(target_ulong addr); -size_t libafl_qemu_set_hook(target_ulong pc, void (*callback)(target_ulong, uint64_t), - uint64_t data, int invalidate); -size_t libafl_qemu_remove_hooks_at(target_ulong addr, int invalidate); -int libafl_qemu_remove_hook(size_t num, int invalidate); -struct libafl_hook* libafl_search_hook(target_ulong addr); void libafl_flush_jit(void); extern int libafl_restoring_devices; @@ -184,139 +153,6 @@ int libafl_qemu_num_regs(CPUState* cpu) return cc->gdb_num_core_regs; } -void libafl_breakpoint_invalidate(CPUState *cpu, target_ulong pc); - -int libafl_qemu_set_breakpoint(target_ulong pc) -{ - CPUState *cpu; - - CPU_FOREACH(cpu) { - libafl_breakpoint_invalidate(cpu, pc); - } - - struct libafl_breakpoint* bp = calloc(sizeof(struct libafl_breakpoint), 1); - bp->addr = pc; - bp->next = libafl_qemu_breakpoints; - libafl_qemu_breakpoints = bp; - return 1; -} - -int libafl_qemu_remove_breakpoint(target_ulong pc) -{ - CPUState *cpu; - int r = 0; - - struct libafl_breakpoint** bp = &libafl_qemu_breakpoints; - while (*bp) { - if ((*bp)->addr == pc) { - CPU_FOREACH(cpu) { - libafl_breakpoint_invalidate(cpu, pc); - } - - *bp = (*bp)->next; - r = 1; - } else { - bp = &(*bp)->next; - } - } - return r; -} - -size_t libafl_qemu_set_hook(target_ulong pc, void (*callback)(target_ulong, uint64_t), - uint64_t data, int invalidate) -{ - CPUState *cpu; - - if (invalidate) { - CPU_FOREACH(cpu) { - libafl_breakpoint_invalidate(cpu, pc); - } - } - - size_t idx = LIBAFL_TABLES_HASH(pc); - - struct libafl_hook* hk = calloc(sizeof(struct libafl_hook), 1); - hk->addr = pc; - hk->callback = callback; - hk->data = data; - hk->helper_info.func = callback; - hk->helper_info.name = "libafl_hook"; - hk->helper_info.flags = dh_callflag(void); - hk->helper_info.typemask = dh_typemask(void, 0) | dh_typemask(tl, 1) | dh_typemask(i64, 2); - hk->num = libafl_qemu_hooks_num++; - hk->next = libafl_qemu_hooks[idx]; - libafl_qemu_hooks[idx] = hk; - return hk->num; -} - -size_t libafl_qemu_remove_hooks_at(target_ulong addr, int invalidate) -{ - CPUState *cpu; - size_t r = 0; - - size_t idx = LIBAFL_TABLES_HASH(addr); - struct libafl_hook** hk = &libafl_qemu_hooks[idx]; - while (*hk) { - if ((*hk)->addr == addr) { - if (invalidate) { - CPU_FOREACH(cpu) { - libafl_breakpoint_invalidate(cpu, addr); - } - } - - void *tmp = *hk; - *hk = (*hk)->next; - free(tmp); - r++; - } else { - hk = &(*hk)->next; - } - } - return r; -} - -int libafl_qemu_remove_hook(size_t num, int invalidate) -{ - CPUState *cpu; - size_t idx; - - for (idx = 0; idx < LIBAFL_TABLES_SIZE; ++idx) { - struct libafl_hook** hk = &libafl_qemu_hooks[idx]; - while (*hk) { - if ((*hk)->num == num) { - if (invalidate) { - CPU_FOREACH(cpu) { - libafl_breakpoint_invalidate(cpu, (*hk)->addr); - } - } - - void *tmp = *hk; - *hk = (*hk)->next; - free(tmp); - return 1; - } else { - hk = &(*hk)->next; - } - } - } - return 0; -} - -struct libafl_hook* libafl_search_hook(target_ulong addr) -{ - size_t idx = LIBAFL_TABLES_HASH(addr); - - struct libafl_hook* hk = libafl_qemu_hooks[idx]; - while (hk) { - if (hk->addr == addr) { - return hk; - } - hk = hk->next; - } - - return NULL; -} - void libafl_flush_jit(void) { CPUState *cpu; diff --git a/gdbstub/gdbstub.c b/gdbstub/gdbstub.c index c4e1139eae..01363a525b 100644 --- a/gdbstub/gdbstub.c +++ b/gdbstub/gdbstub.c @@ -1601,8 +1601,8 @@ static void handle_query_thread_extra(GArray *params, void *user_ctx) struct libafl_custom_gdb_cmd* libafl_qemu_gdb_cmds; -void libafl_qemu_add_gdb_cmd(int (*callback)(uint8_t*, size_t, void*), void* data); -void libafl_qemu_add_gdb_cmd(int (*callback)(uint8_t*, size_t, void*), void* data) +void libafl_qemu_add_gdb_cmd(int (*callback)(void*, uint8_t*, size_t), void* data); +void libafl_qemu_add_gdb_cmd(int (*callback)(void*, uint8_t*, size_t), void* data) { struct libafl_custom_gdb_cmd* c = malloc(sizeof(struct libafl_custom_gdb_cmd)); c->callback = callback; diff --git a/gdbstub/internals.h b/gdbstub/internals.h index e2022cfa30..e5e822a9a4 100644 --- a/gdbstub/internals.h +++ b/gdbstub/internals.h @@ -236,7 +236,7 @@ int gdb_target_memory_rw_debug(CPUState *cs, hwaddr addr, //// --- Begin LibAFL code --- struct libafl_custom_gdb_cmd { - int (*callback)(uint8_t*, size_t, void*); + int (*callback)(void*, uint8_t*, size_t); void* data; struct libafl_custom_gdb_cmd* next; }; diff --git a/gdbstub/system.c b/gdbstub/system.c index 6e9ecc138d..0f0bd920cf 100644 --- a/gdbstub/system.c +++ b/gdbstub/system.c @@ -534,7 +534,7 @@ void gdb_handle_query_rcmd(GArray *params, void *user_ctx) struct libafl_custom_gdb_cmd** c = &libafl_qemu_gdb_cmds; int recognized = 0; while (*c) { - recognized |= (*c)->callback(gdbserver_state.mem_buf->data, gdbserver_state.mem_buf->len, (*c)->data); + recognized |= (*c)->callback((*c)->data, gdbserver_state.mem_buf->data, gdbserver_state.mem_buf->len); c = &(*c)->next; } diff --git a/gdbstub/user-target.c b/gdbstub/user-target.c index ec686cca2c..e44710724d 100644 --- a/gdbstub/user-target.c +++ b/gdbstub/user-target.c @@ -311,7 +311,7 @@ void gdb_handle_query_rcmd(GArray *params, void *user_ctx) struct libafl_custom_gdb_cmd** c = &libafl_qemu_gdb_cmds; int recognized = 0; while (*c) { - recognized |= (*c)->callback(gdbserver_state.mem_buf->data, gdbserver_state.mem_buf->len, (*c)->data); + recognized |= (*c)->callback((*c)->data, gdbserver_state.mem_buf->data, gdbserver_state.mem_buf->len); c = &(*c)->next; } diff --git a/libafl_extras/exit.c b/libafl_extras/exit.c index d5e4549cac..430f088ec9 100644 --- a/libafl_extras/exit.c +++ b/libafl_extras/exit.c @@ -9,6 +9,44 @@ #define THREAD_MODIFIER #endif +struct libafl_breakpoint* libafl_qemu_breakpoints = NULL; + +int libafl_qemu_set_breakpoint(target_ulong pc) +{ + CPUState *cpu; + + CPU_FOREACH(cpu) { + libafl_breakpoint_invalidate(cpu, pc); + } + + struct libafl_breakpoint* bp = calloc(sizeof(struct libafl_breakpoint), 1); + bp->addr = pc; + bp->next = libafl_qemu_breakpoints; + libafl_qemu_breakpoints = bp; + return 1; +} + +int libafl_qemu_remove_breakpoint(target_ulong pc) +{ + CPUState *cpu; + int r = 0; + + struct libafl_breakpoint** bp = &libafl_qemu_breakpoints; + while (*bp) { + if ((*bp)->addr == pc) { + CPU_FOREACH(cpu) { + libafl_breakpoint_invalidate(cpu, pc); + } + + *bp = (*bp)->next; + r = 1; + } else { + bp = &(*bp)->next; + } + } + return r; +} + static THREAD_MODIFIER struct libafl_exit_reason last_exit_reason; static THREAD_MODIFIER bool expected_exit = false; diff --git a/libafl_extras/exit.h b/libafl_extras/exit.h index af72d9b2b6..9f4d35ea67 100644 --- a/libafl_extras/exit.h +++ b/libafl_extras/exit.h @@ -5,6 +5,19 @@ #define EXCP_LIBAFL_EXIT 0xf4775747 +struct libafl_breakpoint { + target_ulong addr; + struct libafl_breakpoint* next; +}; + +extern struct libafl_breakpoint* libafl_qemu_breakpoints; + +// in cpu-target.c +void libafl_breakpoint_invalidate(CPUState *cpu, target_ulong pc); + +int libafl_qemu_set_breakpoint(target_ulong pc); +int libafl_qemu_remove_breakpoint(target_ulong pc); + enum libafl_exit_reason_kind { BREAKPOINT = 0, SYNC_BACKDOOR = 1 diff --git a/libafl_extras/hook.c b/libafl_extras/hook.c new file mode 100644 index 0000000000..272ecaf736 --- /dev/null +++ b/libafl_extras/hook.c @@ -0,0 +1,560 @@ +#include "qemu/osdep.h" +#include "qapi/error.h" + +#include "exec/exec-all.h" +#include "exec/tb-flush.h" + +#include "hook.h" +#include "exit.h" + +#ifndef TARGET_LONG_BITS +#error "TARGET_LONG_BITS not defined" +#endif + +target_ulong libafl_gen_cur_pc; + +struct libafl_hook* libafl_qemu_hooks[LIBAFL_TABLES_SIZE]; +size_t libafl_qemu_hooks_num = 0; + +size_t libafl_qemu_set_hook(target_ulong pc, void (*callback)(uint64_t, target_ulong), + uint64_t data, int invalidate) +{ + CPUState *cpu; + + if (invalidate) { + CPU_FOREACH(cpu) { + libafl_breakpoint_invalidate(cpu, pc); + } + } + + size_t idx = LIBAFL_TABLES_HASH(pc); + + struct libafl_hook* hk = calloc(sizeof(struct libafl_hook), 1); + hk->addr = pc; + // hk->callback = callback; + hk->data = data; + hk->helper_info.func = callback; + hk->helper_info.name = "libafl_hook"; + hk->helper_info.flags = dh_callflag(void); + hk->helper_info.typemask = dh_typemask(void, 0) | dh_typemask(tl, 1) | dh_typemask(i64, 2); + hk->num = libafl_qemu_hooks_num++; + hk->next = libafl_qemu_hooks[idx]; + libafl_qemu_hooks[idx] = hk; + return hk->num; +} + +size_t libafl_qemu_remove_hooks_at(target_ulong addr, int invalidate) +{ + CPUState *cpu; + size_t r = 0; + + size_t idx = LIBAFL_TABLES_HASH(addr); + struct libafl_hook** hk = &libafl_qemu_hooks[idx]; + while (*hk) { + if ((*hk)->addr == addr) { + if (invalidate) { + CPU_FOREACH(cpu) { + libafl_breakpoint_invalidate(cpu, addr); + } + } + + void *tmp = *hk; + *hk = (*hk)->next; + free(tmp); + r++; + } else { + hk = &(*hk)->next; + } + } + return r; +} + +int libafl_qemu_remove_hook(size_t num, int invalidate) +{ + CPUState *cpu; + size_t idx; + + for (idx = 0; idx < LIBAFL_TABLES_SIZE; ++idx) { + struct libafl_hook** hk = &libafl_qemu_hooks[idx]; + while (*hk) { + if ((*hk)->num == num) { + if (invalidate) { + CPU_FOREACH(cpu) { + libafl_breakpoint_invalidate(cpu, (*hk)->addr); + } + } + + void *tmp = *hk; + *hk = (*hk)->next; + free(tmp); + return 1; + } else { + hk = &(*hk)->next; + } + } + } + return 0; +} + +struct libafl_hook* libafl_search_hook(target_ulong addr) +{ + size_t idx = LIBAFL_TABLES_HASH(addr); + + struct libafl_hook* hk = libafl_qemu_hooks[idx]; + while (hk) { + if (hk->addr == addr) { + return hk; + } + hk = hk->next; + } + + return NULL; +} + +static TCGHelperInfo libafl_exec_backdoor_hook_info = { + .func = NULL, .name = "libafl_exec_backdoor_hook", \ + .flags = dh_callflag(void), \ + .typemask = dh_typemask(void, 0) | dh_typemask(tl, 1) | dh_typemask(i64, 2) +}; + +struct libafl_backdoor_hook* libafl_backdoor_hooks; + +void libafl_add_backdoor_hook(void (*exec)(target_ulong id, uint64_t data), + uint64_t data) +{ + struct libafl_backdoor_hook* hook = calloc(sizeof(struct libafl_backdoor_hook), 1); + // hook->exec = exec; + hook->data = data; + hook->next = libafl_backdoor_hooks; + libafl_backdoor_hooks = hook; + + memcpy(&hook->helper_info, &libafl_exec_backdoor_hook_info, sizeof(TCGHelperInfo)); + hook->helper_info.func = exec; +} + +static TCGHelperInfo libafl_exec_edge_hook_info = { + .func = NULL, .name = "libafl_exec_edge_hook", \ + .flags = dh_callflag(void), \ + .typemask = dh_typemask(void, 0) | dh_typemask(i64, 1) | dh_typemask(i64, 2) +}; + +struct libafl_edge_hook* libafl_edge_hooks; + +void libafl_add_edge_hook(uint64_t (*gen)(uint64_t data, target_ulong src, target_ulong dst), + void (*exec)(uint64_t data, uint64_t id), + uint64_t data) +{ + CPUState *cpu; + CPU_FOREACH(cpu) { + tb_flush(cpu); + } + + struct libafl_edge_hook* hook = calloc(sizeof(struct libafl_edge_hook), 1); + hook->gen = gen; + // hook->exec = exec; + hook->data = data; + hook->next = libafl_edge_hooks; + libafl_edge_hooks = hook; + + if (exec) { + memcpy(&hook->helper_info, &libafl_exec_edge_hook_info, sizeof(TCGHelperInfo)); + hook->helper_info.func = exec; + } +} + +static TCGHelperInfo libafl_exec_block_hook_info = { + .func = NULL, .name = "libafl_exec_block_hook", \ + .flags = dh_callflag(void), \ + .typemask = dh_typemask(void, 0) | dh_typemask(i64, 1) | dh_typemask(i64, 2) +}; + +struct libafl_block_hook* libafl_block_hooks; + +void libafl_add_block_hook(uint64_t (*gen)(uint64_t data, target_ulong pc), + void (*post_gen)(uint64_t data, target_ulong pc, target_ulong block_length), + void (*exec)(uint64_t data, uint64_t id), uint64_t data) +{ + CPUState *cpu; + CPU_FOREACH(cpu) { + tb_flush(cpu); + } + + struct libafl_block_hook* hook = calloc(sizeof(struct libafl_block_hook), 1); + hook->gen = gen; + hook->post_gen = post_gen; + // hook->exec = exec; + hook->data = data; + hook->next = libafl_block_hooks; + libafl_block_hooks = hook; + + if (exec) { + memcpy(&hook->helper_info, &libafl_exec_block_hook_info, sizeof(TCGHelperInfo)); + hook->helper_info.func = exec; + } +} + +static TCGHelperInfo libafl_exec_read_hook1_info = { + .func = NULL, .name = "libafl_exec_read_hook1", \ + .flags = dh_callflag(void), \ + .typemask = dh_typemask(void, 0) | dh_typemask(i64, 1) | dh_typemask(i64, 2) | dh_typemask(tl, 3) +}; +static TCGHelperInfo libafl_exec_read_hook2_info = { + .func = NULL, .name = "libafl_exec_read_hook2", \ + .flags = dh_callflag(void), \ + .typemask = dh_typemask(void, 0) | dh_typemask(i64, 1) | dh_typemask(i64, 2) | dh_typemask(tl, 3) +}; +static TCGHelperInfo libafl_exec_read_hook4_info = { + .func = NULL, .name = "libafl_exec_read_hook4", \ + .flags = dh_callflag(void), \ + .typemask = dh_typemask(void, 0) | dh_typemask(i64, 1) | dh_typemask(i64, 2) | dh_typemask(tl, 3) +}; +static TCGHelperInfo libafl_exec_read_hook8_info = { + .func = NULL, .name = "libafl_exec_read_hook8", \ + .flags = dh_callflag(void), \ + .typemask = dh_typemask(void, 0) | dh_typemask(i64, 1) | dh_typemask(i64, 2) | dh_typemask(tl, 3) +}; +static TCGHelperInfo libafl_exec_read_hookN_info = { + .func = NULL, .name = "libafl_exec_read_hookN", \ + .flags = dh_callflag(void), \ + .typemask = dh_typemask(void, 0) | dh_typemask(i64, 1) | dh_typemask(i64, 2) + | dh_typemask(tl, 3) | dh_typemask(i64, 4) +}; +static TCGHelperInfo libafl_exec_write_hook1_info = { + .func = NULL, .name = "libafl_exec_write_hook1", \ + .flags = dh_callflag(void), \ + .typemask = dh_typemask(void, 0) | dh_typemask(i64, 1) | dh_typemask(i64, 2) | dh_typemask(tl, 3) +}; +static TCGHelperInfo libafl_exec_write_hook2_info = { + .func = NULL, .name = "libafl_exec_write_hook2", \ + .flags = dh_callflag(void), \ + .typemask = dh_typemask(void, 0) | dh_typemask(i64, 1) | dh_typemask(i64, 2) | dh_typemask(tl, 3) +}; +static TCGHelperInfo libafl_exec_write_hook4_info = { + .func = NULL, .name = "libafl_exec_write_hook4", \ + .flags = dh_callflag(void), \ + .typemask = dh_typemask(void, 0) | dh_typemask(i64, 1) | dh_typemask(i64, 2) | dh_typemask(tl, 3) +}; +static TCGHelperInfo libafl_exec_write_hook8_info = { + .func = NULL, .name = "libafl_exec_write_hook8", \ + .flags = dh_callflag(void), \ + .typemask = dh_typemask(void, 0) | dh_typemask(i64, 1) | dh_typemask(i64, 2) | dh_typemask(tl, 3) +}; +static TCGHelperInfo libafl_exec_write_hookN_info = { + .func = NULL, .name = "libafl_exec_write_hookN", \ + .flags = dh_callflag(void), \ + .typemask = dh_typemask(void, 0) | dh_typemask(i64, 1) | dh_typemask(i64, 2) + | dh_typemask(tl, 3) | dh_typemask(i64, 4) +}; + +struct libafl_rw_hook* libafl_read_hooks; + +void libafl_add_read_hook(uint64_t (*gen)(uint64_t data, target_ulong pc, MemOpIdx oi), + void (*exec1)(uint64_t data, uint64_t id, target_ulong addr), + void (*exec2)(uint64_t data, uint64_t id, target_ulong addr), + void (*exec4)(uint64_t data, uint64_t id, target_ulong addr), + void (*exec8)(uint64_t data, uint64_t id, target_ulong addr), + void (*execN)(uint64_t data, uint64_t id, target_ulong addr, size_t size), + uint64_t data) +{ + CPUState *cpu; + CPU_FOREACH(cpu) { + tb_flush(cpu); + } + + struct libafl_rw_hook* hook = calloc(sizeof(struct libafl_rw_hook), 1); + hook->gen = gen; + /*hook->exec1 = exec1; + hook->exec2 = exec2; + hook->exec4 = exec4; + hook->exec8 = exec8; + hook->execN = execN;*/ + hook->data = data; + hook->next = libafl_read_hooks; + libafl_read_hooks = hook; + + if (exec1) { + memcpy(&hook->helper_info1, &libafl_exec_read_hook1_info, sizeof(TCGHelperInfo)); + hook->helper_info1.func = exec1; + } + if (exec2) { + memcpy(&hook->helper_info2, &libafl_exec_read_hook2_info, sizeof(TCGHelperInfo)); + hook->helper_info2.func = exec2; + } + if (exec4) { + memcpy(&hook->helper_info4, &libafl_exec_read_hook4_info, sizeof(TCGHelperInfo)); + hook->helper_info4.func = exec4; + } + if (exec8) { + memcpy(&hook->helper_info8, &libafl_exec_read_hook8_info, sizeof(TCGHelperInfo)); + hook->helper_info8.func = exec8; + } + if (execN) { + memcpy(&hook->helper_infoN, &libafl_exec_read_hookN_info, sizeof(TCGHelperInfo)); + hook->helper_infoN.func = execN; + } +} + +struct libafl_rw_hook* libafl_write_hooks; + +void libafl_add_write_hook(uint64_t (*gen)(uint64_t data, target_ulong pc, MemOpIdx oi), + void (*exec1)(uint64_t data, uint64_t id, target_ulong addr), + void (*exec2)(uint64_t data, uint64_t id, target_ulong addr), + void (*exec4)(uint64_t data, uint64_t id, target_ulong addr), + void (*exec8)(uint64_t data, uint64_t id, target_ulong addr), + void (*execN)(uint64_t data, uint64_t id, target_ulong addr, size_t size), + uint64_t data) +{ + CPUState *cpu; + CPU_FOREACH(cpu) { + tb_flush(cpu); + } + + struct libafl_rw_hook* hook = calloc(sizeof(struct libafl_rw_hook), 1); + hook->gen = gen; + /*hook->exec1 = exec1; + hook->exec2 = exec2; + hook->exec4 = exec4; + hook->exec8 = exec8; + hook->execN = execN;*/ + hook->data = data; + hook->next = libafl_write_hooks; + libafl_write_hooks = hook; + + if (exec1) { + memcpy(&hook->helper_info1, &libafl_exec_write_hook1_info, sizeof(TCGHelperInfo)); + hook->helper_info1.func = exec1; + } + if (exec2) { + memcpy(&hook->helper_info2, &libafl_exec_write_hook2_info, sizeof(TCGHelperInfo)); + hook->helper_info2.func = exec2; + } + if (exec4) { + memcpy(&hook->helper_info4, &libafl_exec_write_hook4_info, sizeof(TCGHelperInfo)); + hook->helper_info4.func = exec4; + } + if (exec8) { + memcpy(&hook->helper_info8, &libafl_exec_write_hook8_info, sizeof(TCGHelperInfo)); + hook->helper_info8.func = exec8; + } + if (execN) { + memcpy(&hook->helper_infoN, &libafl_exec_write_hookN_info, sizeof(TCGHelperInfo)); + hook->helper_infoN.func = execN; + } +} + +static void libafl_gen_rw(TCGTemp *addr, MemOpIdx oi, struct libafl_rw_hook* hook) +{ + size_t size = memop_size(get_memop(oi)); + + while (hook) { + uint64_t cur_id = 0; + if (hook->gen) + cur_id = hook->gen(hook->data, libafl_gen_cur_pc, oi); + TCGHelperInfo* info = NULL; + if (size == 1 && hook->helper_info1.func) info = &hook->helper_info1; + else if (size == 2 && hook->helper_info2.func) info = &hook->helper_info2; + else if (size == 4 && hook->helper_info4.func) info = &hook->helper_info4; + else if (size == 8 && hook->helper_info8.func) info = &hook->helper_info8; + if (cur_id != (uint64_t)-1) { + if (info) { + TCGv_i64 tmp0 = tcg_constant_i64(hook->data); + TCGv_i64 tmp1 = tcg_constant_i64(cur_id); + TCGTemp *tmp2[3] = { tcgv_i64_temp(tmp0), + tcgv_i64_temp(tmp1), + addr }; + tcg_gen_callN(info, NULL, tmp2); + tcg_temp_free_i64(tmp0); + tcg_temp_free_i64(tmp1); + } else if (hook->helper_infoN.func) { + TCGv_i64 tmp0 = tcg_constant_i64(hook->data); + TCGv_i64 tmp1 = tcg_constant_i64(cur_id); + TCGv tmp2 = tcg_constant_tl(size); + TCGTemp *tmp3[4] = { tcgv_i64_temp(tmp0), + tcgv_i64_temp(tmp1), + addr, +#if TARGET_LONG_BITS == 32 + tcgv_i32_temp(tmp2) }; +#else + tcgv_i64_temp(tmp2) }; +#endif + tcg_gen_callN(&hook->helper_infoN, NULL, tmp3); + tcg_temp_free_i64(tmp0); + tcg_temp_free_i64(tmp1); +#if TARGET_LONG_BITS == 32 + tcg_temp_free_i32(tmp2); +#else + tcg_temp_free_i64(tmp2); +#endif + } + } + hook = hook->next; + } +} + +void libafl_gen_read(TCGTemp *addr, MemOpIdx oi) +{ + libafl_gen_rw(addr, oi, libafl_read_hooks); +} + +void libafl_gen_write(TCGTemp *addr, MemOpIdx oi) +{ + libafl_gen_rw(addr, oi, libafl_write_hooks); +} + +static TCGHelperInfo libafl_exec_cmp_hook1_info = { + .func = NULL, .name = "libafl_exec_cmp_hook1", \ + .flags = dh_callflag(void), \ + .typemask = dh_typemask(void, 0) | dh_typemask(i64, 1) + | dh_typemask(i64, 2) | dh_typemask(tl, 3) | dh_typemask(tl, 4) +}; +static TCGHelperInfo libafl_exec_cmp_hook2_info = { + .func = NULL, .name = "libafl_exec_cmp_hook2", \ + .flags = dh_callflag(void), \ + .typemask = dh_typemask(void, 0) | dh_typemask(i64, 1) + | dh_typemask(i64, 2) | dh_typemask(tl, 3) | dh_typemask(tl, 4) +}; +static TCGHelperInfo libafl_exec_cmp_hook4_info = { + .func = NULL, .name = "libafl_exec_cmp_hook4", \ + .flags = dh_callflag(void), \ + .typemask = dh_typemask(void, 0) | dh_typemask(i64, 1) + | dh_typemask(i64, 2) | dh_typemask(tl, 3) | dh_typemask(tl, 4) +}; +static TCGHelperInfo libafl_exec_cmp_hook8_info = { + .func = NULL, .name = "libafl_exec_cmp_hook8", \ + .flags = dh_callflag(void), \ + .typemask = dh_typemask(void, 0) | dh_typemask(i64, 1) + | dh_typemask(i64, 2) | dh_typemask(i64, 3) | dh_typemask(i64, 4) +}; + +struct libafl_cmp_hook* libafl_cmp_hooks; + +void libafl_add_cmp_hook(uint64_t (*gen)(uint64_t data, target_ulong pc, size_t size), + void (*exec1)(uint64_t data, uint64_t id, uint8_t v0, uint8_t v1), + void (*exec2)(uint64_t data, uint64_t id, uint16_t v0, uint16_t v1), + void (*exec4)(uint64_t data, uint64_t id, uint32_t v0, uint32_t v1), + void (*exec8)(uint64_t data, uint64_t id, uint64_t v0, uint64_t v1), + uint64_t data) +{ + CPUState *cpu; + CPU_FOREACH(cpu) { + tb_flush(cpu); + } + + struct libafl_cmp_hook* hook = calloc(sizeof(struct libafl_cmp_hook), 1); + hook->gen = gen; + /*hook->exec1 = exec1; + hook->exec2 = exec2; + hook->exec4 = exec4; + hook->exec8 = exec8;*/ + hook->data = data; + hook->next = libafl_cmp_hooks; + libafl_cmp_hooks = hook; + + if (exec1) { + memcpy(&hook->helper_info1, &libafl_exec_cmp_hook1_info, sizeof(TCGHelperInfo)); + hook->helper_info1.func = exec1; + } + if (exec2) { + memcpy(&hook->helper_info2, &libafl_exec_cmp_hook2_info, sizeof(TCGHelperInfo)); + hook->helper_info2.func = exec2; + } + if (exec4) { + memcpy(&hook->helper_info4, &libafl_exec_cmp_hook4_info, sizeof(TCGHelperInfo)); + hook->helper_info4.func = exec4; + } + if (exec8) { + memcpy(&hook->helper_info8, &libafl_exec_cmp_hook8_info, sizeof(TCGHelperInfo)); + hook->helper_info8.func = exec8; + } +} + +void libafl_gen_cmp(target_ulong pc, TCGv op0, TCGv op1, MemOp ot) +{ + size_t size = 0; + switch (ot & MO_SIZE) { + case MO_64: + size = 8; + break; + case MO_32: + size = 4; + break; + case MO_16: + size = 2; + break; + case MO_8: + size = 1; + break; + default: + return; + } + + struct libafl_cmp_hook* hook = libafl_cmp_hooks; + while (hook) { + uint64_t cur_id = 0; + if (hook->gen) + cur_id = hook->gen(hook->data, pc, size); + TCGHelperInfo* info = NULL; + if (size == 1 && hook->helper_info1.func) info = &hook->helper_info1; + else if (size == 2 && hook->helper_info2.func) info = &hook->helper_info2; + else if (size == 4 && hook->helper_info4.func) info = &hook->helper_info4; + else if (size == 8 && hook->helper_info8.func) info = &hook->helper_info8; + if (cur_id != (uint64_t)-1 && info) { + TCGv_i64 tmp0 = tcg_constant_i64(hook->data); + TCGv_i64 tmp1 = tcg_constant_i64(cur_id); + TCGTemp *tmp2[4] = { tcgv_i64_temp(tmp0), tcgv_i64_temp(tmp1), +#if TARGET_LONG_BITS == 32 + tcgv_i32_temp(op0), tcgv_i32_temp(op1) }; +#else + tcgv_i64_temp(op0), tcgv_i64_temp(op1) }; +#endif + tcg_gen_callN(info, NULL, tmp2); + tcg_temp_free_i64(tmp0); + tcg_temp_free_i64(tmp1); + } + hook = hook->next; + } +} + +struct libafl_pre_syscall_hook* libafl_pre_syscall_hooks; +struct libafl_post_syscall_hook* libafl_post_syscall_hooks; + +void libafl_add_pre_syscall_hook(struct syshook_ret (*callback)( + uint64_t data, int sys_num, target_ulong arg0, + target_ulong arg1, target_ulong arg2, + target_ulong arg3, target_ulong arg4, + target_ulong arg5, target_ulong arg6, + target_ulong arg7), + uint64_t data) +{ + struct libafl_pre_syscall_hook* hook = calloc(sizeof(struct libafl_pre_syscall_hook), 1); + hook->callback = callback; + hook->data = data; + hook->next = libafl_pre_syscall_hooks; + libafl_pre_syscall_hooks = hook; +} + +void libafl_add_post_syscall_hook(target_ulong (*callback)( + uint64_t data, target_ulong ret, int sys_num, + target_ulong arg0, target_ulong arg1, + target_ulong arg2, target_ulong arg3, + target_ulong arg4, target_ulong arg5, + target_ulong arg6, target_ulong arg7), + uint64_t data) +{ + struct libafl_post_syscall_hook* hook = calloc(sizeof(struct libafl_post_syscall_hook), 1); + hook->callback = callback; + hook->data = data; + hook->next = libafl_post_syscall_hooks; + libafl_post_syscall_hooks = hook; +} + +struct libafl_new_thread_hook* libafl_new_thread_hooks; + +void libafl_add_new_thread_hook(bool (*callback)(uint64_t data, uint32_t tid), + uint64_t data) { + struct libafl_new_thread_hook* hook = calloc(sizeof(struct libafl_new_thread_hook), 1); + hook->callback = callback; + hook->data = data; + hook->next = libafl_new_thread_hooks; + libafl_new_thread_hooks = hook; +} diff --git a/libafl_extras/hook.h b/libafl_extras/hook.h new file mode 100644 index 0000000000..108ae7fbec --- /dev/null +++ b/libafl_extras/hook.h @@ -0,0 +1,198 @@ +#pragma once + +#include "qemu/osdep.h" +#include "qapi/error.h" + +#include "tcg/tcg-op.h" +#include "tcg/tcg-internal.h" +#include "tcg/tcg-temp-internal.h" + +#define LIBAFL_TABLES_SIZE 16384 +#define LIBAFL_TABLES_HASH(p) (((13*((size_t)(p))) ^ (((size_t)(p)) >> 15)) % LIBAFL_TABLES_SIZE) + +void tcg_gen_callN(TCGHelperInfo *info, TCGTemp *ret, TCGTemp **args); + +TranslationBlock *libafl_gen_edge(CPUState *cpu, target_ulong src_block, + target_ulong dst_block, int exit_n, + target_ulong cs_base, uint32_t flags, + int cflags); + +void libafl_gen_cmp(target_ulong pc, TCGv op0, TCGv op1, MemOp ot); +void libafl_gen_backdoor(target_ulong pc); + +extern target_ulong libafl_gen_cur_pc; + +struct libafl_hook { + target_ulong addr; + // void (*callback)(uint64_t, target_ulong); + uint64_t data; + size_t num; + TCGHelperInfo helper_info; + struct libafl_hook* next; +}; + +extern struct libafl_hook* libafl_qemu_hooks[LIBAFL_TABLES_SIZE]; +extern size_t libafl_qemu_hooks_num; + +size_t libafl_qemu_set_hook(target_ulong pc, void (*callback)(uint64_t, target_ulong), + uint64_t data, int invalidate); +size_t libafl_qemu_remove_hooks_at(target_ulong addr, int invalidate); +int libafl_qemu_remove_hook(size_t num, int invalidate); +struct libafl_hook* libafl_search_hook(target_ulong addr); + +struct libafl_backdoor_hook { + void (*exec)(target_ulong pc, uint64_t data); + uint64_t data; + TCGHelperInfo helper_info; + struct libafl_backdoor_hook* next; +}; + +extern struct libafl_backdoor_hook* libafl_backdoor_hooks; + +void libafl_add_backdoor_hook(void (*exec)(target_ulong pc, uint64_t data), + uint64_t data); + +struct libafl_edge_hook { + uint64_t (*gen)(uint64_t data, target_ulong src, target_ulong dst); + // void (*exec)(uint64_t data, uint64_t id); + uint64_t data; + uint64_t cur_id; + TCGHelperInfo helper_info; + struct libafl_edge_hook* next; +}; + +extern struct libafl_edge_hook* libafl_edge_hooks; + +void libafl_add_edge_hook(uint64_t (*gen)(uint64_t data, target_ulong src, target_ulong dst), + void (*exec)(uint64_t data, uint64_t id), + uint64_t data); + +struct libafl_block_hook { + uint64_t (*gen)(uint64_t data, target_ulong pc); + void (*post_gen)(uint64_t data, target_ulong pc, target_ulong block_length); + // void (*exec)(uint64_t data, uint64_t id); + uint64_t data; + TCGHelperInfo helper_info; + struct libafl_block_hook* next; +}; + +extern struct libafl_block_hook* libafl_block_hooks; + +void libafl_add_block_hook(uint64_t (*gen)(uint64_t data, target_ulong pc), + void (*post_gen)(uint64_t data, target_ulong pc, target_ulong block_length), + void (*exec)(uint64_t data, uint64_t id), uint64_t data); + +struct libafl_rw_hook { + uint64_t (*gen)(uint64_t data, target_ulong pc, MemOpIdx oi); + /*void (*exec1)(uint64_t data, uint64_t id, target_ulong addr); + void (*exec2)(uint64_t data, uint64_t id, target_ulong addr); + void (*exec4)(uint64_t data, uint64_t id, target_ulong addr); + void (*exec8)(uint64_t data, uint64_t id, target_ulong addr); + void (*execN)(uint64_t data, uint64_t id, target_ulong addr, size_t size);*/ + uint64_t data; + TCGHelperInfo helper_info1; + TCGHelperInfo helper_info2; + TCGHelperInfo helper_info4; + TCGHelperInfo helper_info8; + TCGHelperInfo helper_infoN; + struct libafl_rw_hook* next; +}; + +extern struct libafl_rw_hook* libafl_read_hooks; +extern struct libafl_rw_hook* libafl_write_hooks; + +void libafl_add_read_hook(uint64_t (*gen)(uint64_t data, target_ulong pc, MemOpIdx oi), + void (*exec1)(uint64_t data, uint64_t id, target_ulong addr), + void (*exec2)(uint64_t data, uint64_t id, target_ulong addr), + void (*exec4)(uint64_t data, uint64_t id, target_ulong addr), + void (*exec8)(uint64_t data, uint64_t id, target_ulong addr), + void (*execN)(uint64_t data, uint64_t id, target_ulong addr, size_t size), + uint64_t data); +void libafl_add_write_hook(uint64_t (*gen)(uint64_t data, target_ulong pc, MemOpIdx oi), + void (*exec1)(uint64_t data, uint64_t id, target_ulong addr), + void (*exec2)(uint64_t data, uint64_t id, target_ulong addr), + void (*exec4)(uint64_t data, uint64_t id, target_ulong addr), + void (*exec8)(uint64_t data, uint64_t id, target_ulong addr), + void (*execN)(uint64_t data, uint64_t id, target_ulong addr, size_t size), + uint64_t data); + +void libafl_gen_read(TCGTemp *addr, MemOpIdx oi); +void libafl_gen_write(TCGTemp *addr, MemOpIdx oi); + +struct libafl_cmp_hook { + uint64_t (*gen)(uint64_t data, target_ulong pc, size_t size); + /*void (*exec1)(uint64_t data, uint64_t id, uint8_t v0, uint8_t v1); + void (*exec2)(uint64_t data, uint64_t id, uint16_t v0, uint16_t v1); + void (*exec4)(uint64_t data, uint64_t id, uint32_t v0, uint32_t v1); + void (*exec8)(uint64_t data, uint64_t id, uint64_t v0, uint64_t v1);*/ + uint64_t data; + TCGHelperInfo helper_info1; + TCGHelperInfo helper_info2; + TCGHelperInfo helper_info4; + TCGHelperInfo helper_info8; + struct libafl_cmp_hook* next; +}; + +extern struct libafl_cmp_hook* libafl_cmp_hooks; + +void libafl_add_cmp_hook(uint64_t (*gen)(uint64_t data, target_ulong pc, size_t size), + void (*exec1)(uint64_t data, uint64_t id, uint8_t v0, uint8_t v1), + void (*exec2)(uint64_t data, uint64_t id, uint16_t v0, uint16_t v1), + void (*exec4)(uint64_t data, uint64_t id, uint32_t v0, uint32_t v1), + void (*exec8)(uint64_t data, uint64_t id, uint64_t v0, uint64_t v1), + uint64_t data); + +struct syshook_ret { + target_ulong retval; + bool skip_syscall; +}; + +struct libafl_pre_syscall_hook { + struct syshook_ret (*callback)(uint64_t data, int sys_num, target_ulong arg0, + target_ulong arg1, target_ulong arg2, + target_ulong arg3, target_ulong arg4, + target_ulong arg5, target_ulong arg6, + target_ulong arg7); + uint64_t data; + struct libafl_pre_syscall_hook* next; +}; + +struct libafl_post_syscall_hook { + target_ulong (*callback)(uint64_t data, target_ulong ret, int sys_num, + target_ulong arg0, target_ulong arg1, + target_ulong arg2, target_ulong arg3, + target_ulong arg4, target_ulong arg5, + target_ulong arg6, target_ulong arg7); + uint64_t data; + struct libafl_post_syscall_hook* next; +}; + +extern struct libafl_pre_syscall_hook* libafl_pre_syscall_hooks; +extern struct libafl_post_syscall_hook* libafl_post_syscall_hooks; + +void libafl_add_pre_syscall_hook(struct syshook_ret (*callback)( + uint64_t data, int sys_num, target_ulong arg0, + target_ulong arg1, target_ulong arg2, + target_ulong arg3, target_ulong arg4, + target_ulong arg5, target_ulong arg6, + target_ulong arg7), + uint64_t data); +void libafl_add_post_syscall_hook(target_ulong (*callback)( + uint64_t data, target_ulong ret, int sys_num, + target_ulong arg0, target_ulong arg1, + target_ulong arg2, target_ulong arg3, + target_ulong arg4, target_ulong arg5, + target_ulong arg6, target_ulong arg7), + uint64_t data); + +struct libafl_new_thread_hook { + bool (*callback)(uint64_t data, uint32_t tid); + uint64_t data; + struct libafl_new_thread_hook* next; +}; + +extern struct libafl_new_thread_hook* libafl_new_thread_hooks; + +void libafl_add_new_thread_hook(bool (*callback)(uint64_t data, uint32_t tid), + uint64_t data); + diff --git a/libafl_extras/meson.build b/libafl_extras/meson.build index da410afc86..faf24f01e2 100644 --- a/libafl_extras/meson.build +++ b/libafl_extras/meson.build @@ -3,4 +3,4 @@ specific_ss.add(when: 'CONFIG_SOFTMMU', if_true: [files( 'syx-snapshot/syx-snapshot.c', 'syx-snapshot/channel-buffer-writeback.c', )]) -specific_ss.add(files('exit.c')) +specific_ss.add(files('exit.c', 'hook.c')) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index eae9883f7e..5772a1c444 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -6522,8 +6522,9 @@ typedef struct { //// --- Begin LibAFL code --- +#include "libafl_extras/hook.h" + extern __thread CPUArchState *libafl_qemu_env; -void (*libafl_on_thread_hook)(uint32_t); //// --- End LibAFL code --- @@ -6560,8 +6561,14 @@ static void *clone_func(void *arg) //// --- Begin LibAFL code --- libafl_qemu_env = env; - if (libafl_on_thread_hook) { - libafl_on_thread_hook(info->tid); + if (libafl_new_thread_hooks) { + bool continue_execution = true; + struct libafl_new_thread_hook* h = libafl_new_thread_hooks; + while (h) { + continue_execution = h->callback(h->data, info->tid) && continue_execution; + h = h->next; + } + if (continue_execution) cpu_loop(env); } else { cpu_loop(env); } @@ -13706,17 +13713,6 @@ IntervalTreeNode * libafl_maps_next(IntervalTreeNode *node, struct libafl_mapinf } } -struct syshook_ret { - uint64_t retval; - bool skip_syscall; -}; -struct syshook_ret (*libafl_pre_syscall_hook)(int, uint64_t, uint64_t, uint64_t, - uint64_t, uint64_t, uint64_t, - uint64_t, uint64_t); -uint64_t (*libafl_post_syscall_hook)(uint64_t, int, uint64_t, uint64_t, - uint64_t, uint64_t, uint64_t, uint64_t, - uint64_t, uint64_t); - //// --- End LibAFL code --- abi_long do_syscall(CPUArchState *cpu_env, int num, abi_long arg1, @@ -13750,21 +13746,26 @@ abi_long do_syscall(CPUArchState *cpu_env, int num, abi_long arg1, //// --- Begin LibAFL code --- - if (libafl_pre_syscall_hook) { - struct syshook_ret hook_ret = libafl_pre_syscall_hook(num, - (uint64_t)arg1, - (uint64_t)arg2, - (uint64_t)arg3, - (uint64_t)arg4, - (uint64_t)arg5, - (uint64_t)arg6, - (uint64_t)arg7, - (uint64_t)arg8); - if (hook_ret.skip_syscall) { - ret = (abi_ulong)hook_ret.retval; - goto after_syscall; - } + bool skip_syscall = false; + struct libafl_pre_syscall_hook* h = libafl_pre_syscall_hooks; + while (h) { + // no null check + struct syshook_ret hook_ret = h->callback(h->data, num, + (target_ulong)arg1, + (target_ulong)arg2, + (target_ulong)arg3, + (target_ulong)arg4, + (target_ulong)arg5, + (target_ulong)arg6, + (target_ulong)arg7, + (target_ulong)arg8); + if (hook_ret.skip_syscall) { + skip_syscall = true; + ret = (abi_ulong)hook_ret.retval; + } + h = h->next; } + if (skip_syscall) goto after_syscall; //// --- End LibAFL code --- @@ -13773,19 +13774,22 @@ abi_long do_syscall(CPUArchState *cpu_env, int num, abi_long arg1, //// --- Begin LibAFL code --- -after_syscall: - if (libafl_post_syscall_hook) { - ret = (abi_ulong)libafl_post_syscall_hook((uint64_t)ret, num, - (uint64_t)arg1, - (uint64_t)arg2, - (uint64_t)arg3, - (uint64_t)arg4, - (uint64_t)arg5, - (uint64_t)arg6, - (uint64_t)arg7, - (uint64_t)arg8); +after_syscall:; + struct libafl_post_syscall_hook* p = libafl_post_syscall_hooks; + while (p) { + // no null check + ret = (abi_ulong)p->callback(p->data, (target_ulong)ret, num, + (target_ulong)arg1, + (target_ulong)arg2, + (target_ulong)arg3, + (target_ulong)arg4, + (target_ulong)arg5, + (target_ulong)arg6, + (target_ulong)arg7, + (target_ulong)arg8); + p = p->next; } - + //// --- End LibAFL code --- if (unlikely(qemu_loglevel_mask(LOG_STRACE))) {