Re: [Qemu-devel] [RFC 19/19] fuzz: Add documentation about the fuzzer to docs/

2019-07-26 Thread Stefan Hajnoczi
On Thu, Jul 25, 2019 at 03:24:00AM +, Oleinik, Alexander wrote:
> +== Main Modifications required for Fuzzing ==
> +
> +Fuzzing is enabled with the -enable-fuzzing flag, which adds the needed 
> cflags
> +to enable Libfuzzer and AddressSanitizer. In the code, most of the changes to
> +existing qemu source are surrounded by #ifdef CONFIG_FUZZ statements. Here 
> are
> +the key areas that are changed:
> +
> +=== General Changes ===

The audience of this file are people wishing to run existing fuzz tests
and/or add new fuzz tests.  Changes are of limited use to someone who
wants to write fuzz tests but isn't familiar with QEMU internals.

Instead I suggest documenting fuzzing in terms of:

1. How to run existing fuzz tests.
2. How to add new fuzz tests.
3. Advice on achieving good code coverage and explanation of the fuzz
   test development cycle.

Focus less on the fuzz infrastructure internals and more on how to use
fuzzing.


signature.asc
Description: PGP signature


[Qemu-devel] [RFC 19/19] fuzz: Add documentation about the fuzzer to docs/

2019-07-24 Thread Oleinik, Alexander
Signed-off-by: Alexander Oleinik 
---
 docs/devel/fuzzing.txt | 145 +
 1 file changed, 145 insertions(+)
 create mode 100644 docs/devel/fuzzing.txt

diff --git a/docs/devel/fuzzing.txt b/docs/devel/fuzzing.txt
new file mode 100644
index 00..321e005e8c
--- /dev/null
+++ b/docs/devel/fuzzing.txt
@@ -0,0 +1,145 @@
+= Fuzzing =
+
+== Introduction ==
+
+This document describes the fuzzing infrastructure in QEMU and how to use it
+to add additional fuzzing targets.
+
+== Basics ==
+
+Fuzzing operates by passing inputs to an entry point/target function. The
+fuzzer tracks the code coverage triggered by the input. Based on these
+findings, the fuzzer mutates the input and repeats the fuzzing. 
+
+To fuzz QEMU, we rely on libfuzzer. Unlike other fuzzers such as AFL, libfuzzer
+is an _in-process_ fuzzer. For the developer, this means that it is their
+responsibility to ensure that state is reset between fuzzing-runs.
+
+libfuzzer provides its own main() and expects the developer to implement the
+entrypoint "LLVMFuzzerTestOneInput".
+
+Currently, Fuzz targets are built out to fuzz virtual-devices from guests. The
+fuzz targets can use qtest and qos functions to pass inputs to virtual devices.
+
+== Main Modifications required for Fuzzing ==
+
+Fuzzing is enabled with the -enable-fuzzing flag, which adds the needed cflags
+to enable Libfuzzer and AddressSanitizer. In the code, most of the changes to
+existing qemu source are surrounded by #ifdef CONFIG_FUZZ statements. Here are
+the key areas that are changed:
+
+=== General Changes ===
+
+vl.c:main renamed to real_main to avoid conflicts when libfuzzer is linked in.
+Also, real_main returns where it would normally call main_loop. 
+
+The fuzzer adds an accelerator. The accelerator does not do anything, much
+like the qtest accelerator.
+
+=== Changes to SaveVM ===
+
+There aren't any particular changes to SaveVM, but the fuzzer adds a type
+of file "ramfile" implemented in test/fuzz/ramfile.c which allocates a buffer
+on the heap to which it saves the vmstate.
+
+=== Changes to QTest ===
+
+QEMU-fuzz modifies the qtest server(qtest.c) and qtest client
+(tests/libqtest.c) so that they communicate within the same QEMU process. In
+the qtest server, there is a qtest_init_fuzz function to initialize the
+QTestState. Normally, qtest commands are passed to socket_send which
+communicates the command to the server/QEMU process over a socket. The fuzzer,
+instead, directly calls the qtest server recieve function with the the command
+string as an argument. The server usually responds to commands with an "OK"
+command. To support this, there is an added qtest_client_recv function in
+libqtest.c, which the server calls directly.
+
+At the moment, qtest's qmp wrapper functions are not supported.
+
+=== Chages to QOS ===
+
+QOS tests are usually linked against the compiled tests/qos-test.c. The main
+function in this file initializes the QOS graph and uses some QMP commands to
+query the qtest server for the available devices. It also registers the tests
+implemented in all of the linked qos test-case files. Then it uses a DFS walker
+to iterate over QOS graph and determine the required QEMU devices/arguments and
+device initialization functions to perform each test.
+
+The fuzzer doesn't link against qos-test, but re-uses most of the functionality
+in test/fuzz/qos_helpers.c The major changes are that the walker simply saves
+the last QGraph path for later use in the fuzzer. The
+qos_set_machines_devices_available function is changed to directly used qmp_*
+commands. Note that to populate the QGraph, the fuzzer still needs to be linked
+against the devices described in test/libqos/*.o
+
+== The Fuzzer's Lifecycle ==
+
+The fuzzer has two entrypoints that libfuzzer calls.
+
+LLVMFuzzerInitialize: called prior to fuzzing. Used to initialize all of the
+necessary state
+
+LLVMFuzzerTestOneInput: called for each fuzzing run. Processes the input and
+resets the state at the end of each run.
+
+In more detail:
+
+LLVMFuzzerInitialize parses the arguments to the fuzzer (must start with two
+dashes, so they are ignored by libfuzzer main()). Currently, the arguments
+select the fuzz target. Then, the qtest client is initialized. If the target
+requires qos, qgraph is set up and the QOM/LIBQOS modules are initailized.
+Then the QGraph is walked and the QEMU cmd_line is determined and saved.
+
+After this, the vl.c:real_main is called to set up the guest. After this, the
+fuzzer saves the initial vm/device state to ram, after which the initilization
+is complete.
+
+LLVMFuzzerTestOneInput: Uses qtest/qos functions to act based on the fuzz
+input. It is also responsible for manually calling the main loop/main_loop_wait
+to ensure that bottom halves are executed. Finally, it calls reset() which
+restores state from the ramfile and/or resets the guest.
+
+
+Since the same process is reused for many fuzzing runs, QEMU state needs to
+be reset a