-
Notifications
You must be signed in to change notification settings - Fork 36
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add systemmode hw_breakpoint libafl set/remove fns #93
base: main
Are you sure you want to change the base?
Changes from 4 commits
3fd9610
379824c
fc8dcf4
5baf91b
f53a020
f122e3c
00e1d7a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,11 @@ | ||
#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); |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,4 +3,43 @@ | |
|
||
#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); } | ||
|
||
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; | ||
int ret = 0; | ||
|
||
if (!ops->insert_breakpoint) { | ||
return -ENOSYS; | ||
} | ||
|
||
// let's add/remove the breakpoint on every CPU | ||
CPU_FOREACH(cs) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i don't think it's a good idea to insert the hw bp for each CPU. better to take CPUState* as parameter and use it. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why? :) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. multiple reasons:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
It doesn't look like it is the case for sw breakpoints
mmm, are you sure the coprocessor would be included by the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
for sw breakpoints, it's a bit different. since we are not changing the architectural state of the CPU (we check if we triggered a breakpoint address or not independently of the core triggering the bp), we only need to call the bp callback whenever it gets hit (we give the CPUState of the core that triggered the bp there). for hw breakpoint, we actually change the state of the CPU(s) to select when a breakpoint should be triggered. nonetheless, qemu seems to inject the hw breakpoint to every running core as well. in that case, i guess we can keep the same behavior.
i think so, cpus are always added to the global list when they get realized. in any case, if qemu sets the hw breakpoints using There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Good catch, this can actually be problematic, I removed my loop |
||
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; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i didn't check yet, can we use normal hw breakpoints if this gets removed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure I understand what you mean by normal hw breakpoints, through gdb? If so, no, with this pr the hw breakpoints are reserved to libafl internal usage
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do we really need to make it impossible to use gdb hardware breakpoints?
i think we can add a very simple allocation system to differentiate libafl from normal breakpoints, with a bitmap or something similar.
in general, i try to avoid breaking QEMU features as much as possible to prevent future problems.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nah, but when I looked at it, it didn't look trivial to implement the breakpoint provenance tagging properly.
The question is more if it is worth it to keep compatibility and if it is a priority. For me no, considering that afaik gdb + libafl_qemu is already quite broken and imho if you want to use gdb is more convenient to do it with vanilla qemu and not with libafl_qemu.
In this case I think that implementing the breakpoint provenance tagging would increase the probability of having future problems since this PR's modifications are quite simple and not deep in QEMU's internals and convoluted as the tagging would be
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
there are some problems, true. i still use gdb with libafl qemu often to debug fuzzers. apart from breakpoints, i didn't encounter too many issues, and most of the common features seemed to work as expected.
in that case, i'd at least issue an error or print something in gdbstub for incoming hw breakpoints.
it would reduce the confusion when using guest gdb in the future.
we could put this somewhere around there, after checking we are handling a hardware bp.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yepp, it's already there :)
https://github.com/Marcondiro/qemu-libafl-bridge/blob/f53a020dc09236cd174357ea9ac2911a249d5edd/gdbstub/system.c#L659-L664