New crash handling for usermode

This commit is contained in:
Andrea Fioraldi 2023-11-30 21:50:21 +01:00
parent deb4d6cd80
commit b85a54516d

View File

@ -698,22 +698,6 @@ void cpu_loop_exit_sigbus(CPUState *cpu, target_ulong addr,
cpu_loop_exit_restore(cpu, ra); cpu_loop_exit_restore(cpu, ra);
} }
//// --- Begin LibAFL code ---
void (*libafl_dump_core_hook)(int target_sig);
/* abort execution with signal */
static G_NORETURN
void die_with_signal_nodfl(int host_sig)
{
kill(getpid(), host_sig);
/* unreachable */
_exit(EXIT_FAILURE);
}
//// --- End LibAFL code ---
/* abort execution with signal */ /* abort execution with signal */
static G_NORETURN static G_NORETURN
void die_with_signal(int host_sig) void die_with_signal(int host_sig)
@ -742,6 +726,12 @@ void die_with_signal(int host_sig)
_exit(EXIT_FAILURE); _exit(EXIT_FAILURE);
} }
//// --- Begin LibAFL code ---
void (*libafl_dump_core_hook)(int host_sig);
//// --- End LibAFL code ---
static G_NORETURN static G_NORETURN
void dump_core_and_abort(CPUArchState *env, int target_sig) void dump_core_and_abort(CPUArchState *env, int target_sig)
{ {
@ -779,13 +769,13 @@ void dump_core_and_abort(CPUArchState *env, int target_sig)
//// --- Begin LibAFL code --- //// --- Begin LibAFL code ---
if (libafl_dump_core_hook) libafl_dump_core_hook(target_sig); if (libafl_dump_core_hook) libafl_dump_core_hook(host_sig);
die_with_signal_nodfl(host_sig); // to trigger LibAFL sig handler // die_with_signal_nodfl(host_sig); // to trigger LibAFL sig handler
//// --- End LibAFL code --- //// --- End LibAFL code ---
// die_with_signal(host_sig); die_with_signal(host_sig);
} }
/* queue a signal so that it will be send to the virtual CPU as soon /* queue a signal so that it will be send to the virtual CPU as soon
@ -897,6 +887,13 @@ void die_from_signal(siginfo_t *info)
error_report("QEMU internal SIG%s {code=%s, addr=%p}", error_report("QEMU internal SIG%s {code=%s, addr=%p}",
sig, code, info->si_addr); sig, code, info->si_addr);
//// --- Begin LibAFL code ---
if (libafl_dump_core_hook) libafl_dump_core_hook(info->si_signo);
//// --- End LibAFL code ---
die_with_signal(info->si_signo); die_with_signal(info->si_signo);
} }
@ -976,9 +973,36 @@ static void host_sigbus_handler(CPUState *cpu, siginfo_t *info,
//// --- Begin LibAFL code --- //// --- Begin LibAFL code ---
int libafl_qemu_handle_crash(int host_sig, siginfo_t *info, void *puc); // int libafl_qemu_is_tb_protected_write(int host_sig, siginfo_t *info,
// host_sigcontext *uc);
void libafl_qemu_handle_crash(int host_sig, siginfo_t *info, void *puc);
int libafl_qemu_handle_crash(int host_sig, siginfo_t *info, void *puc) /* int libafl_qemu_is_tb_protected_write(int host_sig, siginfo_t *info,
host_sigcontext *uc)
{
CPUState *cpu = thread_cpu;
uintptr_t host_addr = (uintptr_t)info->si_addr;
bool is_valid = h2g_valid(host_addr);
abi_ptr guest_addr = h2g_nocheck(host_addr);
uintptr_t pc = host_signal_pc(uc);
bool is_write = host_signal_write(info, uc);
MMUAccessType access_type = adjust_signal_pc(&pc, is_write);
return is_write
&& is_valid
&& info->si_code == SEGV_ACCERR
&& handle_sigsegv_accerr_write(cpu, host_signal_mask(uc),
pc, guest_addr);
} */
void libafl_qemu_handle_crash(int host_sig, siginfo_t *info, void *puc) {
host_signal_handler(host_sig, info, puc);
}
//// --- End LibAFL code ---
static void host_signal_handler(int host_sig, siginfo_t *info, void *puc)
{ {
CPUState *cpu = thread_cpu; CPUState *cpu = thread_cpu;
CPUArchState *env = cpu_env(cpu); CPUArchState *env = cpu_env(cpu);
@ -1001,7 +1025,7 @@ int libafl_qemu_handle_crash(int host_sig, siginfo_t *info, void *puc)
case SIGSEGV: case SIGSEGV:
/* Only returns on handle_sigsegv_accerr_write success. */ /* Only returns on handle_sigsegv_accerr_write success. */
host_sigsegv_handler(cpu, info, uc); host_sigsegv_handler(cpu, info, uc);
return 0; return;
case SIGBUS: case SIGBUS:
host_sigbus_handler(cpu, info, uc); host_sigbus_handler(cpu, info, uc);
sync_sig = true; sync_sig = true;
@ -1016,7 +1040,7 @@ int libafl_qemu_handle_crash(int host_sig, siginfo_t *info, void *puc)
/* get target signal number */ /* get target signal number */
guest_sig = host_to_target_signal(host_sig); guest_sig = host_to_target_signal(host_sig);
if (guest_sig < 1 || guest_sig > TARGET_NSIG) { if (guest_sig < 1 || guest_sig > TARGET_NSIG) {
return 0; return;
} }
trace_user_host_signal(env, host_sig, guest_sig); trace_user_host_signal(env, host_sig, guest_sig);
@ -1058,17 +1082,8 @@ int libafl_qemu_handle_crash(int host_sig, siginfo_t *info, void *puc)
/* interrupt the virtual CPU as soon as possible */ /* interrupt the virtual CPU as soon as possible */
cpu_exit(thread_cpu); cpu_exit(thread_cpu);
return 1;
} }
static void host_signal_handler(int host_sig, siginfo_t *info, void *puc)
{
libafl_qemu_handle_crash(host_sig, info, puc);
}
//// --- End LibAFL code ---
/* do_sigaltstack() returns target values and errnos. */ /* do_sigaltstack() returns target values and errnos. */
/* compare linux/kernel/signal.c:do_sigaltstack() */ /* compare linux/kernel/signal.c:do_sigaltstack() */
abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr,
@ -1238,15 +1253,14 @@ static void handle_pending_signal(CPUArchState *cpu_env, int sig,
//// --- Start LibAFL code --- //// --- Start LibAFL code ---
int ignore_handling = 0;
if (libafl_force_dfl && (sig == SIGABRT || sig == SIGABRT|| sig == SIGSEGV if (libafl_force_dfl && (sig == SIGABRT || sig == SIGABRT|| sig == SIGSEGV
|| sig == SIGILL || sig == SIGBUS)) { || sig == SIGILL || sig == SIGBUS)) {
ignore_handling = 1; handler = TARGET_SIG_DFL;
} }
//// --- End LibAFL code --- //// --- End LibAFL code ---
if (handler == TARGET_SIG_DFL || ignore_handling) { if (handler == TARGET_SIG_DFL) {
/* default handler : ignore some signal. The other are job control or fatal */ /* default handler : ignore some signal. The other are job control or fatal */
if (sig == TARGET_SIGTSTP || sig == TARGET_SIGTTIN || sig == TARGET_SIGTTOU) { if (sig == TARGET_SIGTSTP || sig == TARGET_SIGTTIN || sig == TARGET_SIGTTOU) {
kill(getpid(),SIGSTOP); kill(getpid(),SIGSTOP);