Add systemmode hw_breakpoint libafl set/remove fns (#93)

* Add systemmode hw_breakpoint libafl set/remove fns

* very bad kvm breakpoint hook yolo

* cleanup

* Prevent GDB from using HW breakpoints

* fix: hw breakpoint add/rm no loop over CPUs
This commit is contained in:
Marco C. 2025-01-24 15:47:33 +01:00 committed by GitHub
parent 2b5e4bfcff
commit 30ad91fb4f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 58 additions and 1 deletions

View File

@ -61,7 +61,11 @@ static void *kvm_vcpu_thread_fn(void *arg)
if (cpu_can_run(cpu)) { if (cpu_can_run(cpu)) {
r = kvm_cpu_exec(cpu); r = kvm_cpu_exec(cpu);
if (r == EXCP_DEBUG) { if (r == EXCP_DEBUG) {
cpu_handle_guest_debug(cpu); //// --- Begin LibAFL code ---
// cpu_handle_guest_debug(cpu);
cpu->stopped = true;
libafl_qemu_trigger_breakpoint(cpu);
//// --- End LibAFL code ---
} }
} }
qemu_wait_io_event(cpu); qemu_wait_io_event(cpu);

View File

@ -33,6 +33,7 @@
//// --- Begin LibAFL code --- //// --- Begin LibAFL code ---
#include "libafl/gdb.h" #include "libafl/gdb.h"
#include "gdbstub/enums.h"
//// --- End LibAFL code --- //// --- End LibAFL code ---
/* System emulation specific state */ /* System emulation specific state */
@ -655,6 +656,12 @@ bool gdb_supports_guest_debug(void)
int gdb_breakpoint_insert(CPUState *cs, int type, vaddr addr, vaddr len) int gdb_breakpoint_insert(CPUState *cs, int type, vaddr addr, vaddr len)
{ {
const AccelOpsClass *ops = cpus_get_accel(); const AccelOpsClass *ops = cpus_get_accel();
//// --- Begin LibAFL code ---
// HW breakpoints are reserved for LibAFL
if (type == GDB_BREAKPOINT_HW) {
return -ENOSYS;
}
//// --- End LibAFL code ---
if (ops->insert_breakpoint) { if (ops->insert_breakpoint) {
return ops->insert_breakpoint(cs, type, addr, len); return ops->insert_breakpoint(cs, type, addr, len);
} }

View File

@ -1,3 +1,11 @@
#pragma once #pragma once
#include "hw/core/cpu.h"
#include "gdbstub/enums.h"
#include "sysemu/accel-ops.h"
#include "sysemu/cpus.h"
int libafl_qemu_set_hw_breakpoint(vaddr addr);
int libafl_qemu_remove_hw_breakpoint(vaddr addr);
void libafl_qemu_init(int argc, char** argv); void libafl_qemu_init(int argc, char** argv);

View File

@ -3,4 +3,42 @@
#include "libafl/system.h" #include "libafl/system.h"
int libafl_qemu_toggle_hw_breakpoint(vaddr addr, bool set);
void libafl_qemu_init(int argc, char** argv) { qemu_init(argc, argv); } void libafl_qemu_init(int argc, char** argv) { qemu_init(argc, argv); }
int libafl_qemu_set_hw_breakpoint(vaddr addr)
{
return libafl_qemu_toggle_hw_breakpoint(addr, true);
}
int libafl_qemu_remove_hw_breakpoint(vaddr addr)
{
return libafl_qemu_toggle_hw_breakpoint(addr, false);
}
int libafl_qemu_toggle_hw_breakpoint(vaddr addr, bool set) {
const int type = GDB_BREAKPOINT_HW;
const vaddr len = 1;
const AccelOpsClass *ops = cpus_get_accel();
CPUState *cs = first_cpu;
int ret = 0;
if (!ops->insert_breakpoint) {
return -ENOSYS;
}
// let's add/remove the breakpoint on the first CPU.
// Both TCG and KVM propagate it to all CPUs internally.
if (set) {
ret = ops->insert_breakpoint(cs, type, addr, len);
} else {
ret = ops->remove_breakpoint(cs, type, addr, len);
}
if (ret != 0) {
return ret;
}
return 0;
}