AFLplusplus / LibAFL

Advanced Fuzzing Library - Slot your Fuzzer together in Rust! Scales across cores and machines. For Windows, Android, MacOS, Linux, no_std, ...
Other
1.99k stars 306 forks source link

Allow building libafl_qemu with several arches #2314

Open twizmwazin opened 3 months ago

twizmwazin commented 3 months ago

Is your feature request related to a problem? Please describe. Right now, libafl_qemu only allows building with a single arch and endianness. This conflicting behavior is problematic when used in conjunction with cargo workspaces. For example, if you have two variants of a fuzzer targeting two different arches, cargo's feature resolver will try and be "smart" and build libafl_qemu with sum of the features from the crates that use it.

Describe the solution you'd like Ideally, it would be nice to be able to build a libafl_qemu that can support multiple arches from a single build, perhaps with a runtime switch passed when the Qemu struct is initialized.

Describe alternatives you've considered I've played around with alternative build configurations that work with different drawbacks. For example, individual crates in the workspace can be built via separate cargo invocations with the -p flag. This works but now I have to call cargo a dozen times for each build, and rust-analyzer fails. Another option is to have a single crate with several binaries which can be built one-by-one, this is the best option but now cargo build does effectively nothing. To build for a single arch the call looks like cargo build --bin fuzzer-aarch64 --features libafl_qemu/aarch64, it has to be called a dozen times as well. cargo make helps automate this, but now we're introducing another layer, and the Makefile.toml ends up really, really large once the debug, release, testing tasks are all added in, and the invocations end up being barely shorter than doing it manually.

Additional context I don't know too much about the qemu internals, for all I know this might be a limitation on the qemu side rather than the libafl_qemu side. I know there are projects like unicorn that have built a derivative of qemu that can emulate various arches from a single binary, but it is possible that this was such a large change to the overall architecture of qemu that it would make more sense to create and maintain a libafl_unicorn rather than try and rebase that effort onto the qemu fork (I saw that someone had previously began a unicorn integration effort in #1054).

domenukk commented 3 months ago

Unicorn specifically adds a qemu/uc pointer that gets passed around that includes the relevant information and all variables that would otherwise be global. Qemu by itself cannot even run the same architecture twice at the same time.

The only thing we might be able to do for qemu is to load multiple libafl_qemu libraries into the same process dynamically using dlmopen (?), maybe you can nerdsnipe @rmalmain to try? But probably it'd be way easier to implement an extra runner with a thing IPC layer, then..

Other than that, yeah, unicorn is your best bet. #1054 would be the way to do it