Skip to content
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

Open
wants to merge 7 commits into
base: main
Choose a base branch
from

Conversation

Marcondiro
Copy link

@Marcondiro Marcondiro commented Dec 9, 2024

reserve hw breakpoints for LibAFL, using them with GDB will return a graceful error. So far they are implemented only for kvm.

@Marcondiro Marcondiro marked this pull request as ready for review December 18, 2024 12:18
@Marcondiro
Copy link
Author

@rmalmain this should be ready

libafl/system.c Outdated
}

// let's add/remove the breakpoint on every CPU
CPU_FOREACH(cs) {
Copy link
Collaborator

Choose a reason for hiding this comment

The 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.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why? :)
Most likely we are going to have just one cpu anyway, so most of the times the parameter would just be annoying ?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

multiple reasons:

  • most of our api does not make assumption about CPU, and takes a CPU as parameter when necessary
  • it's not so straightforward to say we will always have to handle a single CPU, there are more tricky cases that could require multiple CPUs for a single fuzzing instance (think of a system using a coprocessor for instance).

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

most of our api does not make assumption about CPU, and takes a CPU as parameter when necessary

It doesn't look like it is the case for sw breakpoints int libafl_qemu_set_breakpoint(target_ulong pc);, do we want to have different signatures between hw and sw breakpoints?

it's not so straightforward to say we will always have to handle a single CPU, there are more tricky cases that could require multiple CPUs for a single fuzzing instance (think of a system using a coprocessor for instance).

mmm, are you sure the coprocessor would be included by the CPU_FOREACH macro? it looked more like a main cpu(s) cores iterator to me

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't look like it is the case for sw breakpoints int libafl_qemu_set_breakpoint(target_ulong pc);, do we want to have different signatures between hw and sw breakpoints?

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.
so in theory, we could choose which core should stop when the breakpoint is reached.

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.

mmm, are you sure the coprocessor would be included by the CPU_FOREACH macro? it looked more like a main cpu(s) cores iterator to me

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 CPU_FOREACH, it should be fine.

Copy link
Author

@Marcondiro Marcondiro Jan 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Good catch, this can actually be problematic, I removed my loop

@@ -61,7 +61,11 @@ static void *kvm_vcpu_thread_fn(void *arg)
if (cpu_can_run(cpu)) {
r = kvm_cpu_exec(cpu);
if (r == EXCP_DEBUG) {
cpu_handle_guest_debug(cpu);
//// --- Begin LibAFL code ---
// cpu_handle_guest_debug(cpu);
Copy link
Collaborator

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?

Copy link
Author

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

Copy link
Collaborator

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.

Copy link
Author

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?

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.

i try to avoid breaking QEMU features as much as possible to prevent future problems.

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

Copy link
Collaborator

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.

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 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

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.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants