Skip to content

Commit

Permalink
Merge tag 'pr-2023-02-16' of https://gitlab.com/a1xndr/qemu into staging
Browse files Browse the repository at this point in the history
Replace fork-based fuzzing with reboots.
Now the fuzzers will reboot the guest between inputs.

# -----BEGIN PGP SIGNATURE-----
#
# iQIzBAABCgAdFiEE+tTiv4cTddY0BRfETmYd3lg6lk4FAmPu/LoACgkQTmYd3lg6
# lk6RHg/7BRGI5ZPXb1MmTNCC+SroQ6TT++lO4b0hbkN2HO6U+WVvfuA6+0wg+8qC
# 4bp+G1Tabpcq1MTYUuim6DBtWswgpqr0AbWNwn1eF7hya+3W9woH2POVYY2wwc7m
# S3EdwXCCKo9gGXlaNrotnbwIk+o8B4BzXOXLIlRtg26wGYhT5fkJA/BQcHKDXz37
# ctyWxlyjIM8pNCgfybMvjC7MYtp8DufPsv/rrKx9t0TM7f1jPVgXLek7t0+ZwjeY
# qz2Om2jiij1INgK9hTieWs4eHwpwre6vH2a+JKRkZ3sS7WYcj1auNKVJb3GvDqmc
# wy+Nz5Lz4+aPP19pkCYjfz5w3CqEEsSlSDn5UVRbfl2fbENSceoNwo9huMXsF1pB
# oO6NK2NxbOygmNpYxp+JEt45KFIXzUcIFQwbn8aCDODIl+0H2yu7/ll6XgELf1Pa
# P83THOaVxIxfcI9VOdt/FwDq1ZzmV5nk/BkIGJeIWNYMbU4Gze6YoaL3U8AHDxKH
# f6f3qDzcVJjqD0wKhvYcQ3kSPq+vHc/ioh6mYwos6VUEVYz/SLOY876MaSB/K4PE
# ofBV7y6HvJ6AMwg1TBg4YtOP08gWK+4sYH+I09oU40U3UcwEpkbkQTF72lPQHxFs
# 8UVRJrgWv/xzrwzXTX5ruQ633F8zuhqQTeERqksj1pPHJ3NdHps=
# =F6qI
# -----END PGP SIGNATURE-----
# gpg: Signature made Fri 17 Feb 2023 04:04:10 GMT
# gpg:                using RSA key FAD4E2BF871375D6340517C44E661DDE583A964E
# gpg: Good signature from "Alexander Bulekov <[email protected]>" [unknown]
# gpg: WARNING: This key is not certified with a trusted signature!
# gpg:          There is no indication that the signature belongs to the owner.
# Primary key fingerprint: FAD4 E2BF 8713 75D6 3405  17C4 4E66 1DDE 583A 964E

* tag 'pr-2023-02-16' of https://gitlab.com/a1xndr/qemu:
  docs/fuzz: remove mentions of fork-based fuzzing
  fuzz: remove fork-fuzzing scaffolding
  fuzz/i440fx: remove fork-based fuzzer
  fuzz/virtio-blk: remove fork-based fuzzer
  fuzz/virtio-net: remove fork-based fuzzer
  fuzz/virtio-scsi: remove fork-based fuzzer
  fuzz/generic-fuzz: add a limit on DMA bytes written
  fuzz/generic-fuzz: use reboots instead of forks to reset state
  fuzz: add fuzz_reset API
  hw/sparse-mem: clear memory on reset

Signed-off-by: Peter Maydell <[email protected]>
  • Loading branch information
pm215 committed Feb 21, 2023
2 parents 9b0699a + 7d9e5f1 commit 4919d0c
Show file tree
Hide file tree
Showing 14 changed files with 71 additions and 404 deletions.
22 changes: 2 additions & 20 deletions docs/devel/fuzzing.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,6 @@ responsibility to ensure that state is reset between fuzzing-runs.
Building the fuzzers
--------------------

*NOTE*: If possible, build a 32-bit binary. When forking, the 32-bit fuzzer is
much faster, since the page-map has a smaller size. This is due to the fact that
AddressSanitizer maps ~20TB of memory, as part of its detection. This results
in a large page-map, and a much slower ``fork()``.

To build the fuzzers, install a recent version of clang:
Configure with (substitute the clang binaries with the version you installed).
Here, enable-sanitizers, is optional but it allows us to reliably detect bugs
Expand Down Expand Up @@ -296,10 +291,9 @@ input. It is also responsible for manually calling ``main_loop_wait`` to ensure
that bottom halves are executed and any cleanup required before the next input.

Since the same process is reused for many fuzzing runs, QEMU state needs to
be reset at the end of each run. There are currently two implemented
options for resetting state:
be reset at the end of each run. For example, this can be done by rebooting the
VM, after each run.

- Reboot the guest between runs.
- *Pros*: Straightforward and fast for simple fuzz targets.

- *Cons*: Depending on the device, does not reset all device state. If the
Expand All @@ -308,15 +302,3 @@ options for resetting state:
reboot.

- *Example target*: ``i440fx-qtest-reboot-fuzz``

- Run each test case in a separate forked process and copy the coverage
information back to the parent. This is fairly similar to AFL's "deferred"
fork-server mode [3]

- *Pros*: Relatively fast. Devices only need to be initialized once. No need to
do slow reboots or vmloads.

- *Cons*: Not officially supported by libfuzzer. Does not work well for
devices that rely on dedicated threads.

- *Example target*: ``virtio-net-fork-fuzz``
13 changes: 12 additions & 1 deletion hw/mem/sparse-mem.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,13 @@ static void sparse_mem_write(void *opaque, hwaddr addr, uint64_t v,

}

static void sparse_mem_enter_reset(Object *obj, ResetType type)
{
SparseMemState *s = SPARSE_MEM(obj);
g_hash_table_remove_all(s->mapped);
return;
}

static const MemoryRegionOps sparse_mem_ops = {
.read = sparse_mem_read,
.write = sparse_mem_write,
Expand Down Expand Up @@ -123,20 +130,24 @@ static void sparse_mem_realize(DeviceState *dev, Error **errp)

assert(s->baseaddr + s->length > s->baseaddr);

s->mapped = g_hash_table_new(NULL, NULL);
s->mapped = g_hash_table_new_full(NULL, NULL, NULL,
(GDestroyNotify)g_free);
memory_region_init_io(&s->mmio, OBJECT(s), &sparse_mem_ops, s,
"sparse-mem", s->length);
sysbus_init_mmio(sbd, &s->mmio);
}

static void sparse_mem_class_init(ObjectClass *klass, void *data)
{
ResettableClass *rc = RESETTABLE_CLASS(klass);
DeviceClass *dc = DEVICE_CLASS(klass);

device_class_set_props(dc, sparse_mem_properties);

dc->desc = "Sparse Memory Device";
dc->realize = sparse_mem_realize;

rc->phases.enter = sparse_mem_enter_reset;
}

static const TypeInfo sparse_mem_types[] = {
Expand Down
4 changes: 0 additions & 4 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -215,10 +215,6 @@ endif
# Specify linker-script with add_project_link_arguments so that it is not placed
# within a linker --start-group/--end-group pair
if get_option('fuzzing')
add_project_link_arguments(['-Wl,-T,',
(meson.current_source_dir() / 'tests/qtest/fuzz/fork_fuzz.ld')],
native: false, language: all_languages)

# Specify a filter to only instrument code that is directly related to
# virtual-devices.
configure_file(output: 'instrumentation-filter',
Expand Down
41 changes: 0 additions & 41 deletions tests/qtest/fuzz/fork_fuzz.c

This file was deleted.

23 changes: 0 additions & 23 deletions tests/qtest/fuzz/fork_fuzz.h

This file was deleted.

56 changes: 0 additions & 56 deletions tests/qtest/fuzz/fork_fuzz.ld

This file was deleted.

6 changes: 6 additions & 0 deletions tests/qtest/fuzz/fuzz.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,12 @@ void flush_events(QTestState *s)
}
}

void fuzz_reset(QTestState *s)
{
qemu_system_reset(SHUTDOWN_CAUSE_GUEST_RESET);
main_loop_wait(true);
}

static QTestState *qtest_setup(void)
{
qtest_server_set_send_handler(&qtest_client_inproc_recv, &fuzz_qts);
Expand Down
2 changes: 1 addition & 1 deletion tests/qtest/fuzz/fuzz.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ typedef struct FuzzTarget {
} FuzzTarget;

void flush_events(QTestState *);
void reboot(QTestState *);
void fuzz_reset(QTestState *);

/* Use the QTest ASCII protocol or call address_space API directly?*/
void fuzz_qtest_set_serialize(bool option);
Expand Down
Loading

0 comments on commit 4919d0c

Please sign in to comment.