On 11/01/19 16:41, Max Moroz wrote: > > > On Fri, Jan 11, 2019 at 7:34 AM Paolo Bonzini <pbonz...@redhat.com > <mailto:pbonz...@redhat.com>> wrote: > > On 11/01/19 16:04, Max Moroz wrote: > > We usually have a single fuzzing process, it starts with a fuzzing > > engine's main function and is calling LLVMFuzzerTestOneInput with > > various inputs and keep mutating them based on the coverage feedback. > > Running a second process which you don't care too much about might be > > fine, but the fuzzing process should be "replacing" or should I say > > "imitating" the process whose coverage you're interested in. > > What do you mean by replacing or imitating? > > To give you an example, when we fuzz ffmpeg, we do not run ffmpeg's main > function. We write LLVMFuzzerTestOneInput that would do the necessary > initialization, reset the state, etc, and then would pass (data, size) > provided by a fuzzing engine to the API(s) we're trying to fuzz. So, in > your case, there should not be a regular QEMU process, and instead the > fuzz target (i.e. LLVMFuzzerTestOneInput) should be doing certain > initialization (which is usually done by the QEMU process) and then call > the API you want to fuzz.
The main issue is that we are not really testing an API and QEMU has a lot of global state. Of course there are C functions to do the elementary I/O operations, but there are two problems. The first and smaller is that one input would correspond to a sequence of invocations of the functions, not just one function invocation; the larger, is that the knowledge of the guest (memory map, placement of devices, etc.) is not easy to consume from within QEMU. We do have a library that includes that knowledge, and it would be easy to use it from a mutator or input postprocessor, but I'm afraid that it would be very very intrusive to embed that library into QEMU, replacing all of main() etc. The simplest way would be to test the input by fork()-ing QEMU, followed by waitpid() in the parent and invoking the original main() in the child. But that wouldn't buy much and would probably even be slower than an efficient deferred fork server. Paolo > > > > Avoiding fork would probably be hard. I'm mostly afraid that some state > guest state is not resetted properly across runs, and this would result > in non-reproducible crashes. > > It seems to me that the task can be approached with AFL and a test case > postprocessor to generate the qtest input; however, my knowledge of > libFuzzer is very very limited. > > Paolo >