-
Notifications
You must be signed in to change notification settings - Fork 46
Description
Currently, if the
emu.set_breakpoint(guest_addr):Feature is used to define a breakpoint, the execution is only yielded back if the same thread that set the breakpoint hits the target address. If another thread hits this breakpoint, this does stop this specific thread but does not yield execution to the rust wrapper code back.
The reason is likely inside libafl/exit.c prepare_qemu_exit, which is used by the breakpoint api to throw cpu_loop_exit:
static void prepare_qemu_exit(CPUState* cpu, target_ulong next_pc)
{
expected_exit = true;
last_exit_reason.cpu = cpu;
last_exit_reason.next_pc = next_pc;
#if !defined(CONFIG_USER_ONLY) && defined(AS_LIB)
qemu_system_return_request();
#endif
if (cpu->running) {
cpu->exception_index = EXCP_LIBAFL_EXIT;
cpu_loop_exit(cpu);
}
}A workaround seems to be available in iterating over all CPUs, which are in linux user-mode actually threads, and using qemu_cpu_kick to request a shutdown:
CPU_FOREACH(cpu) {
if (cpu->running) {
cpu->exception_index = EXCP_LIBAFL_EXIT;
qemu_cpu_kick(cpu);
}
}This does however suffer from race conditions. Calling cpu_loop_exit(cpu) while iterating over the different CPUs seems to result in memory failures, therefore I presume some kind of lock is needed.
@rmalmain I would be more than happy to contribute a fix for this, but would like to hear some input in what you would believe to be a good solution for this problem.