aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2020-11-10 12:23:05 +0000
committerPeter Maydell <peter.maydell@linaro.org>2020-11-10 12:23:05 +0000
commit879860ca706fa1ef47ba511c49a6e2b1b49be9b7 (patch)
treef6557aa49be6e488920c865482ce4c874337cc38
parent6c8e801f076109a31d864fdbeec57badd159fb06 (diff)
parenta58cabd0e355fc51f18db359ba260da268df26ef (diff)
downloadqemu-879860ca706fa1ef47ba511c49a6e2b1b49be9b7.zip
qemu-879860ca706fa1ef47ba511c49a6e2b1b49be9b7.tar.gz
qemu-879860ca706fa1ef47ba511c49a6e2b1b49be9b7.tar.bz2
Merge remote-tracking branch 'remotes/huth-gitlab/tags/pull-request-2020-11-10' into staging
* Some small qtest fixes * Oss-fuzz updates * Publish the docs built during gitlab CI to the user's gitlab.io page * Update the OpenBSD VM test to v6.8 * Fix the device-crash-test script to run with the meson build system * Some small s390x fixes # gpg: Signature made Tue 10 Nov 2020 11:05:06 GMT # gpg: using RSA key 27B88847EEE0250118F3EAB92ED9D774FE702DB5 # gpg: issuer "thuth@redhat.com" # gpg: Good signature from "Thomas Huth <th.huth@gmx.de>" [full] # gpg: aka "Thomas Huth <thuth@redhat.com>" [full] # gpg: aka "Thomas Huth <huth@tuxfamily.org>" [full] # gpg: aka "Thomas Huth <th.huth@posteo.de>" [unknown] # Primary key fingerprint: 27B8 8847 EEE0 2501 18F3 EAB9 2ED9 D774 FE70 2DB5 * remotes/huth-gitlab/tags/pull-request-2020-11-10: s390x: Avoid variable size warning in ipl.h s390x: fix clang 11 warnings in cpu_models.c qtest: Update references to parse_escape() in comments fuzz: add virtio-blk fuzz target docs: add "page source" link to sphinx documentation gitlab: force enable docs build in Fedora, Ubuntu, Debian gitlab: publish the docs built during CI configure: surface deprecated targets in the help output fuzz: Make fork_fuzz.ld compatible with LLVM's LLD scripts/oss-fuzz: give all fuzzers -target names docs/fuzz: update fuzzing documentation post-meson docs/fuzz: rST-ify the fuzzing documentation MAINTAINERS: Add gitlab-pipeline-status script to GitLab CI section gitlab-ci: Drop generic cache rule tests/qtest/tpm: Remove redundant check in the tpm_test_swtpm_test() qtest: Fix bad printf format specifiers device-crash-test: Check if path is actually an executable file tests/vm: update openbsd to release 6.8 meson: always include contrib/libvhost-user Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r--.gitlab-ci.yml24
-rw-r--r--MAINTAINERS3
-rwxr-xr-xconfigure4
-rw-r--r--docs/_templates/editpage.html5
-rw-r--r--docs/conf.py1
-rw-r--r--docs/devel/_templates/editpage.html5
-rw-r--r--docs/devel/fuzzing.rst236
-rw-r--r--docs/devel/fuzzing.txt214
-rw-r--r--docs/devel/index.rst1
-rw-r--r--docs/interop/_templates/editpage.html5
-rw-r--r--docs/specs/_templates/editpage.html5
-rw-r--r--docs/system/_templates/editpage.html5
-rw-r--r--docs/tools/_templates/editpage.html5
-rw-r--r--docs/user/_templates/editpage.html5
-rw-r--r--hw/s390x/ipl.h4
-rw-r--r--meson.build6
-rwxr-xr-xscripts/device-crash-test4
-rwxr-xr-xscripts/oss-fuzz/build.sh12
-rw-r--r--target/s390x/cpu_models.c8
-rw-r--r--tests/qtest/arm-cpu-features.c8
-rw-r--r--tests/qtest/fuzz/fork_fuzz.ld12
-rw-r--r--tests/qtest/fuzz/meson.build1
-rw-r--r--tests/qtest/fuzz/virtio_blk_fuzz.c234
-rw-r--r--tests/qtest/libqos/libqtest.h18
-rw-r--r--tests/qtest/libqtest-single.h2
-rw-r--r--tests/qtest/tpm-tests.c6
-rwxr-xr-xtests/vm/openbsd8
27 files changed, 577 insertions, 264 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 3b15ae5..9a8b375 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -7,12 +7,6 @@ stages:
- build
- test
-# We assume GitLab has it's own caching set up for RPM/APT repositories so we
-# just take care of avocado assets here.
-cache:
- paths:
- - $HOME/avocado/data/cache
-
include:
- local: '/.gitlab-ci.d/edk2.yml'
- local: '/.gitlab-ci.d/opensbi.yml'
@@ -80,6 +74,7 @@ build-system-ubuntu:
TARGETS: aarch64-softmmu alpha-softmmu cris-softmmu hppa-softmmu
moxie-softmmu microblazeel-softmmu mips64el-softmmu
MAKE_CHECK_ARGS: check-build
+ CONFIGURE_ARGS: --enable-docs
artifacts:
expire_in: 2 days
paths:
@@ -111,6 +106,7 @@ build-system-debian:
TARGETS: arm-softmmu avr-softmmu i386-softmmu mipsel-softmmu
riscv64-softmmu sh4eb-softmmu sparc-softmmu xtensaeb-softmmu
MAKE_CHECK_ARGS: check-build
+ CONFIGURE_ARGS: --enable-docs
artifacts:
expire_in: 2 days
paths:
@@ -139,7 +135,7 @@ build-system-fedora:
<<: *native_build_job_definition
variables:
IMAGE: fedora
- CONFIGURE_ARGS: --disable-gcrypt --enable-nettle
+ CONFIGURE_ARGS: --disable-gcrypt --enable-nettle --enable-docs
TARGETS: tricore-softmmu microblaze-softmmu mips-softmmu
xtensa-softmmu m68k-softmmu riscv32-softmmu ppc-softmmu sparc64-softmmu
MAKE_CHECK_ARGS: check-build
@@ -423,3 +419,17 @@ check-dco:
- $CI_PROJECT_NAMESPACE == 'qemu-project' && $CI_COMMIT_BRANCH == 'master'
variables:
GIT_DEPTH: 1000
+
+pages:
+ image: $CI_REGISTRY_IMAGE/qemu/ubuntu2004:latest
+ stage: test
+ needs:
+ - job: build-system-ubuntu
+ artifacts: true
+ script:
+ - mkdir public
+ - mv build/docs/index.html public/
+ - for i in devel interop specs system tools user ; do mv build/docs/$i public/ ; done
+ artifacts:
+ paths:
+ - public
diff --git a/MAINTAINERS b/MAINTAINERS
index 0e60109..6c2df0b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2525,7 +2525,7 @@ R: Thomas Huth <thuth@redhat.com>
S: Maintained
F: tests/qtest/fuzz/
F: scripts/oss-fuzz/
-F: docs/devel/fuzzing.txt
+F: docs/devel/fuzzing.rst
Register API
M: Alistair Francis <alistair@alistair23.me>
@@ -3156,6 +3156,7 @@ S: Maintained
F: .gitlab-ci.yml
F: .gitlab-ci.d/crossbuilds.yml
F: .gitlab-ci.d/*py
+F: scripts/ci/gitlab-pipeline-status
Guest Test Compilation Support
M: Alex Bennée <alex.bennee@linaro.org>
diff --git a/configure b/configure
index 805f779..4cef321 100755
--- a/configure
+++ b/configure
@@ -1655,9 +1655,11 @@ Standard options:
--prefix=PREFIX install in PREFIX [$prefix]
--interp-prefix=PREFIX where to find shared libraries, etc.
use %M for cpu name [$interp_prefix]
- --target-list=LIST set target list (default: build everything)
+ --target-list=LIST set target list (default: build all non-deprecated)
$(echo Available targets: $default_target_list | \
fold -s -w 53 | sed -e 's/^/ /')
+$(echo Deprecated targets: $deprecated_targets_list | \
+ fold -s -w 53 | sed -e 's/^/ /')
--target-list-exclude=LIST exclude a set of targets from the default target-list
Advanced options (experts only):
diff --git a/docs/_templates/editpage.html b/docs/_templates/editpage.html
new file mode 100644
index 0000000..4319b0f
--- /dev/null
+++ b/docs/_templates/editpage.html
@@ -0,0 +1,5 @@
+<div id="editpage">
+ <ul>
+ <li><a href="https://gitlab.com/qemu-project/qemu/-/blob/master/docs/{{pagename}}.rst">Page source</a></li>
+ </ul>
+</div>
diff --git a/docs/conf.py b/docs/conf.py
index e584f68..d40d8ff 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -177,6 +177,7 @@ html_theme_options = {
html_sidebars = {
'**': [
'about.html',
+ 'editpage.html',
'navigation.html',
'searchbox.html',
]
diff --git a/docs/devel/_templates/editpage.html b/docs/devel/_templates/editpage.html
new file mode 100644
index 0000000..a86d22b
--- /dev/null
+++ b/docs/devel/_templates/editpage.html
@@ -0,0 +1,5 @@
+<div id="editpage">
+ <ul>
+ <li><a href="https://gitlab.com/qemu-project/qemu/-/blob/master/docs/devel/{{pagename}}.rst">Page source</a></li>
+ </ul>
+</div>
diff --git a/docs/devel/fuzzing.rst b/docs/devel/fuzzing.rst
new file mode 100644
index 0000000..6096242
--- /dev/null
+++ b/docs/devel/fuzzing.rst
@@ -0,0 +1,236 @@
+========
+Fuzzing
+========
+
+This document describes the virtual-device fuzzing infrastructure in QEMU and
+how to use it to implement additional fuzzers.
+
+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.
+
+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
+such as out-of-bounds accesses, use-after-frees, double-frees etc.::
+
+ CC=clang-8 CXX=clang++-8 /path/to/configure --enable-fuzzing \
+ --enable-sanitizers
+
+Fuzz targets are built similarly to system targets::
+
+ make qemu-fuzz-i386
+
+This builds ``./qemu-fuzz-i386``
+
+The first option to this command is: ``--fuzz-target=FUZZ_NAME``
+To list all of the available fuzzers run ``qemu-fuzz-i386`` with no arguments.
+
+For example::
+
+ ./qemu-fuzz-i386 --fuzz-target=virtio-scsi-fuzz
+
+Internally, libfuzzer parses all arguments that do not begin with ``"--"``.
+Information about these is available by passing ``-help=1``
+
+Now the only thing left to do is wait for the fuzzer to trigger potential
+crashes.
+
+Useful libFuzzer flags
+----------------------
+
+As mentioned above, libFuzzer accepts some arguments. Passing ``-help=1`` will
+list the available arguments. In particular, these arguments might be helpful:
+
+* ``CORPUS_DIR/`` : Specify a directory as the last argument to libFuzzer.
+ libFuzzer stores each "interesting" input in this corpus directory. The next
+ time you run libFuzzer, it will read all of the inputs from the corpus, and
+ continue fuzzing from there. You can also specify multiple directories.
+ libFuzzer loads existing inputs from all specified directories, but will only
+ write new ones to the first one specified.
+
+* ``-max_len=4096`` : specify the maximum byte-length of the inputs libFuzzer
+ will generate.
+
+* ``-close_fd_mask={1,2,3}`` : close, stderr, or both. Useful for targets that
+ trigger many debug/error messages, or create output on the serial console.
+
+* ``-jobs=4 -workers=4`` : These arguments configure libFuzzer to run 4 fuzzers in
+ parallel (4 fuzzing jobs in 4 worker processes). Alternatively, with only
+ ``-jobs=N``, libFuzzer automatically spawns a number of workers less than or equal
+ to half the available CPU cores. Replace 4 with a number appropriate for your
+ machine. Make sure to specify a ``CORPUS_DIR``, which will allow the parallel
+ fuzzers to share information about the interesting inputs they find.
+
+* ``-use_value_profile=1`` : For each comparison operation, libFuzzer computes
+ ``(caller_pc&4095) | (popcnt(Arg1 ^ Arg2) << 12)`` and places this in the
+ coverage table. Useful for targets with "magic" constants. If Arg1 came from
+ the fuzzer's input and Arg2 is a magic constant, then each time the Hamming
+ distance between Arg1 and Arg2 decreases, libFuzzer adds the input to the
+ corpus.
+
+* ``-shrink=1`` : Tries to make elements of the corpus "smaller". Might lead to
+ better coverage performance, depending on the target.
+
+Note that libFuzzer's exact behavior will depend on the version of
+clang and libFuzzer used to build the device fuzzers.
+
+Generating Coverage Reports
+---------------------------
+
+Code coverage is a crucial metric for evaluating a fuzzer's performance.
+libFuzzer's output provides a "cov: " column that provides a total number of
+unique blocks/edges covered. To examine coverage on a line-by-line basis we
+can use Clang coverage:
+
+ 1. Configure libFuzzer to store a corpus of all interesting inputs (see
+ CORPUS_DIR above)
+ 2. ``./configure`` the QEMU build with ::
+
+ --enable-fuzzing \
+ --extra-cflags="-fprofile-instr-generate -fcoverage-mapping"
+
+ 3. Re-run the fuzzer. Specify $CORPUS_DIR/* as an argument, telling libfuzzer
+ to execute all of the inputs in $CORPUS_DIR and exit. Once the process
+ exits, you should find a file, "default.profraw" in the working directory.
+ 4. Execute these commands to generate a detailed HTML coverage-report::
+
+ llvm-profdata merge -output=default.profdata default.profraw
+ llvm-cov show ./path/to/qemu-fuzz-i386 -instr-profile=default.profdata \
+ --format html -output-dir=/path/to/output/report
+
+Adding a new fuzzer
+-------------------
+
+Coverage over virtual devices can be improved by adding additional fuzzers.
+Fuzzers are kept in ``tests/qtest/fuzz/`` and should be added to
+``tests/qtest/fuzz/Makefile.include``
+
+Fuzzers can rely on both qtest and libqos to communicate with virtual devices.
+
+1. Create a new source file. For example ``tests/qtest/fuzz/foo-device-fuzz.c``.
+
+2. Write the fuzzing code using the libqtest/libqos API. See existing fuzzers
+ for reference.
+
+3. Register the fuzzer in ``tests/fuzz/Makefile.include`` by appending the
+ corresponding object to fuzz-obj-y
+
+Fuzzers can be more-or-less thought of as special qtest programs which can
+modify the qtest commands and/or qtest command arguments based on inputs
+provided by libfuzzer. Libfuzzer passes a byte array and length. Commonly the
+fuzzer loops over the byte-array interpreting it as a list of qtest commands,
+addresses, or values.
+
+The Generic Fuzzer
+------------------
+
+Writing a fuzz target can be a lot of effort (especially if a device driver has
+not be built-out within libqos). Many devices can be fuzzed to some degree,
+without any device-specific code, using the generic-fuzz target.
+
+The generic-fuzz target is capable of fuzzing devices over their PIO, MMIO,
+and DMA input-spaces. To apply the generic-fuzz to a device, we need to define
+two env-variables, at minimum:
+
+* ``QEMU_FUZZ_ARGS=`` is the set of QEMU arguments used to configure a machine, with
+ the device attached. For example, if we want to fuzz the virtio-net device
+ attached to a pc-i440fx machine, we can specify::
+
+ QEMU_FUZZ_ARGS="-M pc -nodefaults -netdev user,id=user0 \
+ -device virtio-net,netdev=user0"
+
+* ``QEMU_FUZZ_OBJECTS=`` is a set of space-delimited strings used to identify
+ the MemoryRegions that will be fuzzed. These strings are compared against
+ MemoryRegion names and MemoryRegion owner names, to decide whether each
+ MemoryRegion should be fuzzed. These strings support globbing. For the
+ virtio-net example, we could use one of ::
+
+ QEMU_FUZZ_OBJECTS='virtio-net'
+ QEMU_FUZZ_OBJECTS='virtio*'
+ QEMU_FUZZ_OBJECTS='virtio* pcspk' # Fuzz the virtio devices and the speaker
+ QEMU_FUZZ_OBJECTS='*' # Fuzz the whole machine``
+
+The ``"info mtree"`` and ``"info qom-tree"`` monitor commands can be especially
+useful for identifying the ``MemoryRegion`` and ``Object`` names used for
+matching.
+
+As a generic rule-of-thumb, the more ``MemoryRegions``/Devices we match, the
+greater the input-space, and the smaller the probability of finding crashing
+inputs for individual devices. As such, it is usually a good idea to limit the
+fuzzer to only a few ``MemoryRegions``.
+
+To ensure that these env variables have been configured correctly, we can use::
+
+ ./qemu-fuzz-i386 --fuzz-target=generic-fuzz -runs=0
+
+The output should contain a complete list of matched MemoryRegions.
+
+Implementation Details / Fuzzer Lifecycle
+-----------------------------------------
+
+The fuzzer has two entrypoints that libfuzzer calls. libfuzzer provides it's
+own ``main()``, which performs some setup, and calls the entrypoints:
+
+``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 initialized.
+Then the QGraph is walked and the QEMU cmd_line is determined and saved.
+
+After this, the ``vl.c:qemu_main`` is called to set up the guest. There are
+target-specific hooks that can be called before and after qemu_main, for
+additional setup(e.g. PCI setup, or VM snapshotting).
+
+``LLVMFuzzerTestOneInput``: Uses qtest/qos functions to act based on the fuzz
+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:
+
+- 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
+ device requires some initialization prior to being ready for fuzzing (common
+ for QOS-based targets), this initialization needs to be done after each
+ 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``
diff --git a/docs/devel/fuzzing.txt b/docs/devel/fuzzing.txt
deleted file mode 100644
index 03585c1..0000000
--- a/docs/devel/fuzzing.txt
+++ /dev/null
@@ -1,214 +0,0 @@
-= Fuzzing =
-
-== Introduction ==
-
-This document describes the virtual-device fuzzing infrastructure in QEMU and
-how to use it to implement additional fuzzers.
-
-== 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.
-
-== 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 mmaps ~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
-such as out-of-bounds accesses, use-after-frees, double-frees etc.
-
- CC=clang-8 CXX=clang++-8 /path/to/configure --enable-fuzzing \
- --enable-sanitizers
-
-Fuzz targets are built similarly to system/softmmu:
-
- make i386-softmmu/fuzz
-
-This builds ./i386-softmmu/qemu-fuzz-i386
-
-The first option to this command is: --fuzz-target=FUZZ_NAME
-To list all of the available fuzzers run qemu-fuzz-i386 with no arguments.
-
-For example:
- ./i386-softmmu/qemu-fuzz-i386 --fuzz-target=virtio-scsi-fuzz
-
-Internally, libfuzzer parses all arguments that do not begin with "--".
-Information about these is available by passing -help=1
-
-Now the only thing left to do is wait for the fuzzer to trigger potential
-crashes.
-
-== Useful libFuzzer flags ==
-
-As mentioned above, libFuzzer accepts some arguments. Passing -help=1 will list
-the available arguments. In particular, these arguments might be helpful:
-
-$CORPUS_DIR/ : Specify a directory as the last argument to libFuzzer. libFuzzer
-stores each "interesting" input in this corpus directory. The next time you run
-libFuzzer, it will read all of the inputs from the corpus, and continue fuzzing
-from there. You can also specify multiple directories. libFuzzer loads existing
-inputs from all specified directories, but will only write new ones to the
-first one specified.
-
--max_len=4096 : specify the maximum byte-length of the inputs libFuzzer will
-generate.
-
--close_fd_mask={1,2,3} : close, stderr, or both. Useful for targets that
-trigger many debug/error messages, or create output on the serial console.
-
--jobs=4 -workers=4 : These arguments configure libFuzzer to run 4 fuzzers in
-parallel (4 fuzzing jobs in 4 worker processes). Alternatively, with only
--jobs=N, libFuzzer automatically spawns a number of workers less than or equal
-to half the available CPU cores. Replace 4 with a number appropriate for your
-machine. Make sure to specify a $CORPUS_DIR, which will allow the parallel
-fuzzers to share information about the interesting inputs they find.
-
--use_value_profile=1 : For each comparison operation, libFuzzer computes
-(caller_pc&4095) | (popcnt(Arg1 ^ Arg2) << 12) and places this in the coverage
-table. Useful for targets with "magic" constants. If Arg1 came from the fuzzer's
-input and Arg2 is a magic constant, then each time the Hamming distance
-between Arg1 and Arg2 decreases, libFuzzer adds the input to the corpus.
-
--shrink=1 : Tries to make elements of the corpus "smaller". Might lead to
-better coverage performance, depending on the target.
-
-Note that libFuzzer's exact behavior will depend on the version of
-clang and libFuzzer used to build the device fuzzers.
-
-== Generating Coverage Reports ==
-Code coverage is a crucial metric for evaluating a fuzzer's performance.
-libFuzzer's output provides a "cov: " column that provides a total number of
-unique blocks/edges covered. To examine coverage on a line-by-line basis we
-can use Clang coverage:
-
- 1. Configure libFuzzer to store a corpus of all interesting inputs (see
- CORPUS_DIR above)
- 2. ./configure the QEMU build with:
- --enable-fuzzing \
- --extra-cflags="-fprofile-instr-generate -fcoverage-mapping"
- 3. Re-run the fuzzer. Specify $CORPUS_DIR/* as an argument, telling libfuzzer
- to execute all of the inputs in $CORPUS_DIR and exit. Once the process
- exits, you should find a file, "default.profraw" in the working directory.
- 4. Execute these commands to generate a detailed HTML coverage-report:
- llvm-profdata merge -output=default.profdata default.profraw
- llvm-cov show ./path/to/qemu-fuzz-i386 -instr-profile=default.profdata \
- --format html -output-dir=/path/to/output/report
-
-== Adding a new fuzzer ==
-Coverage over virtual devices can be improved by adding additional fuzzers.
-Fuzzers are kept in tests/qtest/fuzz/ and should be added to
-tests/qtest/fuzz/Makefile.include
-
-Fuzzers can rely on both qtest and libqos to communicate with virtual devices.
-
-1. Create a new source file. For example ``tests/qtest/fuzz/foo-device-fuzz.c``.
-
-2. Write the fuzzing code using the libqtest/libqos API. See existing fuzzers
-for reference.
-
-3. Register the fuzzer in ``tests/fuzz/Makefile.include`` by appending the
-corresponding object to fuzz-obj-y
-
-Fuzzers can be more-or-less thought of as special qtest programs which can
-modify the qtest commands and/or qtest command arguments based on inputs
-provided by libfuzzer. Libfuzzer passes a byte array and length. Commonly the
-fuzzer loops over the byte-array interpreting it as a list of qtest commands,
-addresses, or values.
-
-== The Generic Fuzzer ==
-Writing a fuzz target can be a lot of effort (especially if a device driver has
-not be built-out within libqos). Many devices can be fuzzed to some degree,
-without any device-specific code, using the generic-fuzz target.
-
-The generic-fuzz target is capable of fuzzing devices over their PIO, MMIO,
-and DMA input-spaces. To apply the generic-fuzz to a device, we need to define
-two env-variables, at minimum:
-
-QEMU_FUZZ_ARGS= is the set of QEMU arguments used to configure a machine, with
-the device attached. For example, if we want to fuzz the virtio-net device
-attached to a pc-i440fx machine, we can specify:
-QEMU_FUZZ_ARGS="-M pc -nodefaults -netdev user,id=user0 \
- -device virtio-net,netdev=user0"
-
-QEMU_FUZZ_OBJECTS= is a set of space-delimited strings used to identify the
-MemoryRegions that will be fuzzed. These strings are compared against
-MemoryRegion names and MemoryRegion owner names, to decide whether each
-MemoryRegion should be fuzzed. These strings support globbing. For the
-virtio-net example, we could use QEMU_FUZZ_OBJECTS=
- * 'virtio-net'
- * 'virtio*'
- * 'virtio* pcspk' (Fuzz the virtio devices and the PC speaker...)
- * '*' (Fuzz the whole machine)
-
-The "info mtree" and "info qom-tree" monitor commands can be especially useful
-for identifying the MemoryRegion and Object names used for matching.
-
-As a generic rule-of-thumb, the more MemoryRegions/Devices we match, the greater
-the input-space, and the smaller the probability of finding crashing inputs for
-individual devices. As such, it is usually a good idea to limit the fuzzer to
-only a few MemoryRegions.
-
-To ensure that these env variables have been configured correctly, we can use:
-
-./qemu-fuzz-i386 --fuzz-target=generic-fuzz -runs=0
-
-The output should contain a complete list of matched MemoryRegions.
-
-= Implementation Details =
-
-== The Fuzzer's Lifecycle ==
-
-The fuzzer has two entrypoints that libfuzzer calls. libfuzzer provides it's
-own main(), which performs some setup, and calls the entrypoints:
-
-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 initialized.
-Then the QGraph is walked and the QEMU cmd_line is determined and saved.
-
-After this, the vl.c:qemu__main is called to set up the guest. There are
-target-specific hooks that can be called before and after qemu_main, for
-additional setup(e.g. PCI setup, or VM snapshotting).
-
-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 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:
-1. 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
- device requires some initialization prior to being ready for fuzzing
- (common for QOS-based targets), this initialization needs to be done after
- each reboot.
- Example target: i440fx-qtest-reboot-fuzz
-2. 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
diff --git a/docs/devel/index.rst b/docs/devel/index.rst
index 77baae5..f10ed77 100644
--- a/docs/devel/index.rst
+++ b/docs/devel/index.rst
@@ -22,6 +22,7 @@ Contents:
stable-process
testing
qtest
+ fuzzing
decodetree
secure-coding-practices
tcg
diff --git a/docs/interop/_templates/editpage.html b/docs/interop/_templates/editpage.html
new file mode 100644
index 0000000..215e562
--- /dev/null
+++ b/docs/interop/_templates/editpage.html
@@ -0,0 +1,5 @@
+<div id="editpage">
+ <ul>
+ <li><a href="https://gitlab.com/qemu-project/qemu/-/blob/master/docs/interop/{{pagename}}.rst">Page source</a></li>
+ </ul>
+</div>
diff --git a/docs/specs/_templates/editpage.html b/docs/specs/_templates/editpage.html
new file mode 100644
index 0000000..aaa468a
--- /dev/null
+++ b/docs/specs/_templates/editpage.html
@@ -0,0 +1,5 @@
+<div id="editpage">
+ <ul>
+ <li><a href="https://gitlab.com/qemu-project/qemu/-/blob/master/docs/specs/{{pagename}}.rst">Page source</a></li>
+ </ul>
+</div>
diff --git a/docs/system/_templates/editpage.html b/docs/system/_templates/editpage.html
new file mode 100644
index 0000000..6586b2e
--- /dev/null
+++ b/docs/system/_templates/editpage.html
@@ -0,0 +1,5 @@
+<div id="editpage">
+ <ul>
+ <li><a href="https://gitlab.com/qemu-project/qemu/-/blob/master/docs/system/{{pagename}}.rst">Page source</a></li>
+ </ul>
+</div>
diff --git a/docs/tools/_templates/editpage.html b/docs/tools/_templates/editpage.html
new file mode 100644
index 0000000..2a9c8fc
--- /dev/null
+++ b/docs/tools/_templates/editpage.html
@@ -0,0 +1,5 @@
+<div id="editpage">
+ <ul>
+ <li><a href="https://gitlab.com/qemu-project/qemu/-/blob/master/docs/tools/{{pagename}}.rst">Page source</a></li>
+ </ul>
+</div>
diff --git a/docs/user/_templates/editpage.html b/docs/user/_templates/editpage.html
new file mode 100644
index 0000000..1f5ee01
--- /dev/null
+++ b/docs/user/_templates/editpage.html
@@ -0,0 +1,5 @@
+<div id="editpage">
+ <ul>
+ <li><a href="https://gitlab.com/qemu-project/qemu/-/blob/master/docs/user/{{pagename}}.rst">Page source</a></li>
+ </ul>
+</div>
diff --git a/hw/s390x/ipl.h b/hw/s390x/ipl.h
index 9e90169..dfc6dfd 100644
--- a/hw/s390x/ipl.h
+++ b/hw/s390x/ipl.h
@@ -32,7 +32,7 @@ struct IPLBlockPV {
uint32_t num_comp; /* 0x74 */
uint64_t pv_header_addr; /* 0x78 */
uint64_t pv_header_len; /* 0x80 */
- struct IPLBlockPVComp components[];
+ struct IPLBlockPVComp components[0];
} QEMU_PACKED;
typedef struct IPLBlockPV IPLBlockPV;
@@ -63,7 +63,7 @@ struct IplBlockFcp {
uint64_t br_lba;
uint32_t scp_data_len;
uint8_t reserved6[260];
- uint8_t scp_data[];
+ uint8_t scp_data[0];
} QEMU_PACKED;
typedef struct IplBlockFcp IplBlockFcp;
diff --git a/meson.build b/meson.build
index f517501..b473620 100644
--- a/meson.build
+++ b/meson.build
@@ -1450,11 +1450,7 @@ trace_events_subdirs += [
'util',
]
-vhost_user = not_found
-if 'CONFIG_VHOST_USER' in config_host
- subdir('contrib/libvhost-user')
-endif
-
+subdir('contrib/libvhost-user')
subdir('qapi')
subdir('qobject')
subdir('stubs')
diff --git a/scripts/device-crash-test b/scripts/device-crash-test
index 866baf7..0411866 100755
--- a/scripts/device-crash-test
+++ b/scripts/device-crash-test
@@ -383,7 +383,9 @@ def binariesToTest(args, testcase):
if args.qemu:
r = args.qemu
else:
- r = glob.glob('./qemu-system-*')
+ r = [f.path for f in os.scandir('.')
+ if f.name.startswith('qemu-system-') and
+ f.is_file() and os.access(f, os.X_OK)]
return r
diff --git a/scripts/oss-fuzz/build.sh b/scripts/oss-fuzz/build.sh
index 3b1c82b..c1af43f 100755
--- a/scripts/oss-fuzz/build.sh
+++ b/scripts/oss-fuzz/build.sh
@@ -62,9 +62,6 @@ fi
mkdir -p "$DEST_DIR/lib/" # Copy the shared libraries here
-mkdir -p "$DEST_DIR/bin/" # Copy executables that shouldn't
- # be treated as fuzzers by oss-fuzz here
-
# Build once to get the list of dynamic lib paths, and copy them over
../configure --disable-werror --cc="$CC" --cxx="$CXX" --enable-fuzzing \
--prefix="$DEST_DIR" --bindir="$DEST_DIR" --datadir="$DEST_DIR/data/" \
@@ -91,20 +88,23 @@ make "-j$(nproc)" qemu-fuzz-i386 V=1
# Copy over the datadir
cp -r ../pc-bios/ "$DEST_DIR/pc-bios"
-cp "./qemu-fuzz-i386" "$DEST_DIR/bin/qemu-fuzz-i386.base"
+targets=$(./qemu-fuzz-i386 | awk '$1 ~ /\*/ {print $2}')
+base_copy="$DEST_DIR/qemu-fuzz-i386-target-$(echo "$targets" | head -n 1)"
+
+cp "./qemu-fuzz-i386" "$base_copy"
# Run the fuzzer with no arguments, to print the help-string and get the list
# of available fuzz-targets. Copy over the qemu-fuzz-i386, naming it according
# to each available fuzz target (See 05509c8e6d fuzz: select fuzz target using
# executable name)
-for target in $(./qemu-fuzz-i386 | awk '$1 ~ /\*/ {print $2}');
+for target in $(echo "$targets" | tail -n +2);
do
# Ignore the generic-fuzz target, as it requires some environment variables
# to be configured. We have some generic-fuzz-{pc-q35, floppy, ...} targets
# that are thin wrappers around this target that set the required
# environment variables according to predefined configs.
if [ "$target" != "generic-fuzz" ]; then
- ln "$DEST_DIR/bin/qemu-fuzz-i386.base" \
+ ln $base_copy \
"$DEST_DIR/qemu-fuzz-i386-target-$target"
fi
done
diff --git a/target/s390x/cpu_models.c b/target/s390x/cpu_models.c
index 461e0b8..b5abff8 100644
--- a/target/s390x/cpu_models.c
+++ b/target/s390x/cpu_models.c
@@ -986,7 +986,7 @@ void s390_realize_cpu_model(CPUState *cs, Error **errp)
static void get_feature(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp)
{
- S390Feat feat = (S390Feat) opaque;
+ S390Feat feat = (S390Feat) (uintptr_t) opaque;
S390CPU *cpu = S390_CPU(obj);
bool value;
@@ -1003,7 +1003,7 @@ static void get_feature(Object *obj, Visitor *v, const char *name,
static void set_feature(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp)
{
- S390Feat feat = (S390Feat) opaque;
+ S390Feat feat = (S390Feat) (uintptr_t) opaque;
DeviceState *dev = DEVICE(obj);
S390CPU *cpu = S390_CPU(obj);
bool value;
@@ -1037,7 +1037,7 @@ static void set_feature(Object *obj, Visitor *v, const char *name,
static void get_feature_group(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp)
{
- S390FeatGroup group = (S390FeatGroup) opaque;
+ S390FeatGroup group = (S390FeatGroup) (uintptr_t) opaque;
const S390FeatGroupDef *def = s390_feat_group_def(group);
S390CPU *cpu = S390_CPU(obj);
S390FeatBitmap tmp;
@@ -1058,7 +1058,7 @@ static void get_feature_group(Object *obj, Visitor *v, const char *name,
static void set_feature_group(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp)
{
- S390FeatGroup group = (S390FeatGroup) opaque;
+ S390FeatGroup group = (S390FeatGroup) (uintptr_t) opaque;
const S390FeatGroupDef *def = s390_feat_group_def(group);
DeviceState *dev = DEVICE(obj);
S390CPU *cpu = S390_CPU(obj);
diff --git a/tests/qtest/arm-cpu-features.c b/tests/qtest/arm-cpu-features.c
index d20094d..bc681a9 100644
--- a/tests/qtest/arm-cpu-features.c
+++ b/tests/qtest/arm-cpu-features.c
@@ -536,7 +536,7 @@ static void test_query_cpu_model_expansion_kvm(const void *data)
if (kvm_supports_sve) {
g_assert(vls != 0);
max_vq = 64 - __builtin_clzll(vls);
- sprintf(max_name, "sve%d", max_vq * 128);
+ sprintf(max_name, "sve%u", max_vq * 128);
/* Enabling a supported length is of course fine. */
assert_sve_vls(qts, "host", vls, "{ %s: true }", max_name);
@@ -556,7 +556,7 @@ static void test_query_cpu_model_expansion_kvm(const void *data)
* unless all larger, supported vector lengths are also
* disabled.
*/
- sprintf(name, "sve%d", vq * 128);
+ sprintf(name, "sve%u", vq * 128);
error = g_strdup_printf("cannot disable %s", name);
assert_error(qts, "host", error,
"{ %s: true, %s: false }",
@@ -569,7 +569,7 @@ static void test_query_cpu_model_expansion_kvm(const void *data)
* we need at least one vector length enabled.
*/
vq = __builtin_ffsll(vls);
- sprintf(name, "sve%d", vq * 128);
+ sprintf(name, "sve%u", vq * 128);
error = g_strdup_printf("cannot disable %s", name);
assert_error(qts, "host", error, "{ %s: false }", name);
g_free(error);
@@ -581,7 +581,7 @@ static void test_query_cpu_model_expansion_kvm(const void *data)
}
}
if (vq <= SVE_MAX_VQ) {
- sprintf(name, "sve%d", vq * 128);
+ sprintf(name, "sve%u", vq * 128);
error = g_strdup_printf("cannot enable %s", name);
assert_error(qts, "host", error, "{ %s: true }", name);
g_free(error);
diff --git a/tests/qtest/fuzz/fork_fuzz.ld b/tests/qtest/fuzz/fork_fuzz.ld
index bfb667e..cfb88b7 100644
--- a/tests/qtest/fuzz/fork_fuzz.ld
+++ b/tests/qtest/fuzz/fork_fuzz.ld
@@ -16,6 +16,11 @@ SECTIONS
/* Lowest stack counter */
*(__sancov_lowest_stack);
}
+}
+INSERT AFTER .data;
+
+SECTIONS
+{
.data.fuzz_ordered :
{
/*
@@ -34,6 +39,11 @@ SECTIONS
*/
*(.bss._ZN6fuzzer3TPCE);
}
+}
+INSERT AFTER .data.fuzz_start;
+
+SECTIONS
+{
.data.fuzz_end : ALIGN(4K)
{
__FUZZ_COUNTERS_END = .;
@@ -43,4 +53,4 @@ SECTIONS
* Don't overwrite the SECTIONS in the default linker script. Instead insert the
* above into the default script
*/
-INSERT AFTER .data;
+INSERT AFTER .data.fuzz_ordered;
diff --git a/tests/qtest/fuzz/meson.build b/tests/qtest/fuzz/meson.build
index 5162321..8af6848 100644
--- a/tests/qtest/fuzz/meson.build
+++ b/tests/qtest/fuzz/meson.build
@@ -5,6 +5,7 @@ specific_fuzz_ss.add(files('fuzz.c', 'fork_fuzz.c', 'qos_fuzz.c',
specific_fuzz_ss.add(when: 'CONFIG_I440FX', if_true: files('i440fx_fuzz.c'))
specific_fuzz_ss.add(when: 'CONFIG_VIRTIO_NET', if_true: files('virtio_net_fuzz.c'))
specific_fuzz_ss.add(when: 'CONFIG_VIRTIO_SCSI', if_true: files('virtio_scsi_fuzz.c'))
+specific_fuzz_ss.add(when: 'CONFIG_VIRTIO_BLK', if_true: files('virtio_blk_fuzz.c'))
specific_fuzz_ss.add(files('generic_fuzz.c'))
fork_fuzz = declare_dependency(
diff --git a/tests/qtest/fuzz/virtio_blk_fuzz.c b/tests/qtest/fuzz/virtio_blk_fuzz.c
new file mode 100644
index 0000000..623a756
--- /dev/null
+++ b/tests/qtest/fuzz/virtio_blk_fuzz.c
@@ -0,0 +1,234 @@
+/*
+ * virtio-blk Fuzzing Target
+ *
+ * Copyright Red Hat Inc., 2020
+ *
+ * Based on virtio-scsi-fuzz target.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+
+#include "tests/qtest/libqos/libqtest.h"
+#include "tests/qtest/libqos/virtio-blk.h"
+#include "tests/qtest/libqos/virtio.h"
+#include "tests/qtest/libqos/virtio-pci.h"
+#include "standard-headers/linux/virtio_ids.h"
+#include "standard-headers/linux/virtio_pci.h"
+#include "standard-headers/linux/virtio_blk.h"
+#include "fuzz.h"
+#include "fork_fuzz.h"
+#include "qos_fuzz.h"
+
+#define TEST_IMAGE_SIZE (64 * 1024 * 1024)
+#define PCI_SLOT 0x02
+#define PCI_FN 0x00
+
+#define MAX_NUM_QUEUES 64
+
+/* Based on tests/qtest/virtio-blk-test.c. */
+typedef struct {
+ int num_queues;
+ QVirtQueue *vq[MAX_NUM_QUEUES + 2];
+} QVirtioBlkQueues;
+
+static QVirtioBlkQueues *qvirtio_blk_init(QVirtioDevice *dev, uint64_t mask)
+{
+ QVirtioBlkQueues *vs;
+ uint64_t features;
+
+ vs = g_new0(QVirtioBlkQueues, 1);
+
+ features = qvirtio_get_features(dev);
+ if (!mask) {
+ mask = ~((1u << VIRTIO_RING_F_INDIRECT_DESC) |
+ (1u << VIRTIO_RING_F_EVENT_IDX) |
+ (1u << VIRTIO_BLK_F_SCSI));
+ }
+ mask |= ~QVIRTIO_F_BAD_FEATURE;
+ features &= mask;
+ qvirtio_set_features(dev, features);
+
+ vs->num_queues = 1;
+ vs->vq[0] = qvirtqueue_setup(dev, fuzz_qos_alloc, 0);
+
+ qvirtio_set_driver_ok(dev);
+
+ return vs;
+}
+
+static void virtio_blk_fuzz(QTestState *s, QVirtioBlkQueues* queues,
+ const unsigned char *Data, size_t Size)
+{
+ /*
+ * Data is a sequence of random bytes. We split them up into "actions",
+ * followed by data:
+ * [vqa][dddddddd][vqa][dddd][vqa][dddddddddddd] ...
+ * The length of the data is specified by the preceding vqa.length
+ */
+ typedef struct vq_action {
+ uint8_t queue;
+ uint8_t length;
+ uint8_t write;
+ uint8_t next;
+ uint8_t kick;
+ } vq_action;
+
+ /* Keep track of the free head for each queue we interact with */
+ bool vq_touched[MAX_NUM_QUEUES + 2] = {0};
+ uint32_t free_head[MAX_NUM_QUEUES + 2];
+
+ QGuestAllocator *t_alloc = fuzz_qos_alloc;
+
+ QVirtioBlk *blk = fuzz_qos_obj;
+ QVirtioDevice *dev = blk->vdev;
+ QVirtQueue *q;
+ vq_action vqa;
+ while (Size >= sizeof(vqa)) {
+ /* Copy the action, so we can normalize length, queue and flags */
+ memcpy(&vqa, Data, sizeof(vqa));
+
+ Data += sizeof(vqa);
+ Size -= sizeof(vqa);
+
+ vqa.queue = vqa.queue % queues->num_queues;
+ /* Cap length at the number of remaining bytes in data */
+ vqa.length = vqa.length >= Size ? Size : vqa.length;
+ vqa.write = vqa.write & 1;
+ vqa.next = vqa.next & 1;
+ vqa.kick = vqa.kick & 1;
+
+ q = queues->vq[vqa.queue];
+
+ /* Copy the data into ram, and place it on the virtqueue */
+ uint64_t req_addr = guest_alloc(t_alloc, vqa.length);
+ qtest_memwrite(s, req_addr, Data, vqa.length);
+ if (vq_touched[vqa.queue] == 0) {
+ vq_touched[vqa.queue] = 1;
+ free_head[vqa.queue] = qvirtqueue_add(s, q, req_addr, vqa.length,
+ vqa.write, vqa.next);
+ } else {
+ qvirtqueue_add(s, q, req_addr, vqa.length, vqa.write , vqa.next);
+ }
+
+ if (vqa.kick) {
+ qvirtqueue_kick(s, dev, q, free_head[vqa.queue]);
+ free_head[vqa.queue] = 0;
+ }
+ Data += vqa.length;
+ Size -= vqa.length;
+ }
+ /* In the end, kick each queue we interacted with */
+ for (int i = 0; i < MAX_NUM_QUEUES + 2; i++) {
+ if (vq_touched[i]) {
+ qvirtqueue_kick(s, dev, queues->vq[i], free_head[i]);
+ }
+ }
+}
+
+static void virtio_blk_fork_fuzz(QTestState *s,
+ const unsigned char *Data, size_t Size)
+{
+ QVirtioBlk *blk = fuzz_qos_obj;
+ static QVirtioBlkQueues *queues;
+ if (!queues) {
+ queues = qvirtio_blk_init(blk->vdev, 0);
+ }
+ if (fork() == 0) {
+ virtio_blk_fuzz(s, queues, Data, Size);
+ flush_events(s);
+ _Exit(0);
+ } else {
+ flush_events(s);
+ wait(NULL);
+ }
+}
+
+static void virtio_blk_with_flag_fuzz(QTestState *s,
+ const unsigned char *Data, size_t Size)
+{
+ QVirtioBlk *blk = fuzz_qos_obj;
+ static QVirtioBlkQueues *queues;
+
+ if (fork() == 0) {
+ if (Size >= sizeof(uint64_t)) {
+ queues = qvirtio_blk_init(blk->vdev, *(uint64_t *)Data);
+ virtio_blk_fuzz(s, queues,
+ Data + sizeof(uint64_t), Size - sizeof(uint64_t));
+ flush_events(s);
+ }
+ _Exit(0);
+ } else {
+ flush_events(s);
+ wait(NULL);
+ }
+}
+
+static void virtio_blk_pre_fuzz(QTestState *s)
+{
+ qos_init_path(s);
+ counter_shm_init();
+}
+
+static void drive_destroy(void *path)
+{
+ unlink(path);
+ g_free(path);
+}
+
+static char *drive_create(void)
+{
+ int fd, ret;
+ char *t_path = g_strdup("/tmp/qtest.XXXXXX");
+
+ /* Create a temporary raw image */
+ fd = mkstemp(t_path);
+ g_assert_cmpint(fd, >=, 0);
+ ret = ftruncate(fd, TEST_IMAGE_SIZE);
+ g_assert_cmpint(ret, ==, 0);
+ close(fd);
+
+ g_test_queue_destroy(drive_destroy, t_path);
+ return t_path;
+}
+
+static void *virtio_blk_test_setup(GString *cmd_line, void *arg)
+{
+ char *tmp_path = drive_create();
+
+ g_string_append_printf(cmd_line,
+ " -drive if=none,id=drive0,file=%s,"
+ "format=raw,auto-read-only=off ",
+ tmp_path);
+
+ return arg;
+}
+
+static void register_virtio_blk_fuzz_targets(void)
+{
+ fuzz_add_qos_target(&(FuzzTarget){
+ .name = "virtio-blk-fuzz",
+ .description = "Fuzz the virtio-blk virtual queues, forking "
+ "for each fuzz run",
+ .pre_vm_init = &counter_shm_init,
+ .pre_fuzz = &virtio_blk_pre_fuzz,
+ .fuzz = virtio_blk_fork_fuzz,},
+ "virtio-blk",
+ &(QOSGraphTestOptions){.before = virtio_blk_test_setup}
+ );
+
+ fuzz_add_qos_target(&(FuzzTarget){
+ .name = "virtio-blk-flags-fuzz",
+ .description = "Fuzz the virtio-blk virtual queues, forking "
+ "for each fuzz run (also fuzzes the virtio flags)",
+ .pre_vm_init = &counter_shm_init,
+ .pre_fuzz = &virtio_blk_pre_fuzz,
+ .fuzz = virtio_blk_with_flag_fuzz,},
+ "virtio-blk",
+ &(QOSGraphTestOptions){.before = virtio_blk_test_setup}
+ );
+}
+
+fuzz_target_init(register_virtio_blk_fuzz_targets);
diff --git a/tests/qtest/libqos/libqtest.h b/tests/qtest/libqos/libqtest.h
index 5c959f1..724f65a 100644
--- a/tests/qtest/libqos/libqtest.h
+++ b/tests/qtest/libqos/libqtest.h
@@ -88,7 +88,7 @@ void qtest_quit(QTestState *s);
* @fds: array of file descriptors
* @fds_num: number of elements in @fds
* @fmt: QMP message to send to qemu, formatted like
- * qobject_from_jsonf_nofail(). See parse_escape() for what's
+ * qobject_from_jsonf_nofail(). See parse_interpolation() for what's
* supported after '%'.
*
* Sends a QMP message to QEMU with fds and returns the response.
@@ -101,7 +101,7 @@ QDict *qtest_qmp_fds(QTestState *s, int *fds, size_t fds_num,
* qtest_qmp:
* @s: #QTestState instance to operate on.
* @fmt: QMP message to send to qemu, formatted like
- * qobject_from_jsonf_nofail(). See parse_escape() for what's
+ * qobject_from_jsonf_nofail(). See parse_interpolation() for what's
* supported after '%'.
*
* Sends a QMP message to QEMU and returns the response.
@@ -113,7 +113,7 @@ QDict *qtest_qmp(QTestState *s, const char *fmt, ...)
* qtest_qmp_send:
* @s: #QTestState instance to operate on.
* @fmt: QMP message to send to qemu, formatted like
- * qobject_from_jsonf_nofail(). See parse_escape() for what's
+ * qobject_from_jsonf_nofail(). See parse_interpolation() for what's
* supported after '%'.
*
* Sends a QMP message to QEMU and leaves the response in the stream.
@@ -138,7 +138,7 @@ void qtest_qmp_send_raw(QTestState *s, const char *fmt, ...)
* @fds: array of file descriptors
* @fds_num: number of elements in @fds
* @fmt: QMP message to send to QEMU, formatted like
- * qobject_from_jsonf_nofail(). See parse_escape() for what's
+ * qobject_from_jsonf_nofail(). See parse_interpolation() for what's
* supported after '%'.
* @ap: QMP message arguments
*
@@ -152,7 +152,7 @@ QDict *qtest_vqmp_fds(QTestState *s, int *fds, size_t fds_num,
* qtest_vqmp:
* @s: #QTestState instance to operate on.
* @fmt: QMP message to send to QEMU, formatted like
- * qobject_from_jsonf_nofail(). See parse_escape() for what's
+ * qobject_from_jsonf_nofail(). See parse_interpolation() for what's
* supported after '%'.
* @ap: QMP message arguments
*
@@ -167,7 +167,7 @@ QDict *qtest_vqmp(QTestState *s, const char *fmt, va_list ap)
* @fds: array of file descriptors
* @fds_num: number of elements in @fds
* @fmt: QMP message to send to QEMU, formatted like
- * qobject_from_jsonf_nofail(). See parse_escape() for what's
+ * qobject_from_jsonf_nofail(). See parse_interpolation() for what's
* supported after '%'.
* @ap: QMP message arguments
*
@@ -181,7 +181,7 @@ void qtest_qmp_vsend_fds(QTestState *s, int *fds, size_t fds_num,
* qtest_qmp_vsend:
* @s: #QTestState instance to operate on.
* @fmt: QMP message to send to QEMU, formatted like
- * qobject_from_jsonf_nofail(). See parse_escape() for what's
+ * qobject_from_jsonf_nofail(). See parse_interpolation() for what's
* supported after '%'.
* @ap: QMP message arguments
*
@@ -636,7 +636,7 @@ void qtest_add_abrt_handler(GHookFunc fn, const void *data);
* qtest_qmp_assert_success:
* @qts: QTestState instance to operate on
* @fmt: QMP message to send to qemu, formatted like
- * qobject_from_jsonf_nofail(). See parse_escape() for what's
+ * qobject_from_jsonf_nofail(). See parse_interpolation() for what's
* supported after '%'.
*
* Sends a QMP message to QEMU and asserts that a 'return' key is present in
@@ -683,7 +683,7 @@ void qtest_qmp_device_add_qdict(QTestState *qts, const char *drv,
* @driver: Name of the device that should be added
* @id: Identification string
* @fmt: QMP message to send to qemu, formatted like
- * qobject_from_jsonf_nofail(). See parse_escape() for what's
+ * qobject_from_jsonf_nofail(). See parse_interpolation() for what's
* supported after '%'.
*
* Generic hot-plugging test via the device_add QMP command.
diff --git a/tests/qtest/libqtest-single.h b/tests/qtest/libqtest-single.h
index 176979a..0d7f568 100644
--- a/tests/qtest/libqtest-single.h
+++ b/tests/qtest/libqtest-single.h
@@ -47,7 +47,7 @@ static inline void qtest_end(void)
/**
* qmp:
* @fmt...: QMP message to send to qemu, formatted like
- * qobject_from_jsonf_nofail(). See parse_escape() for what's
+ * qobject_from_jsonf_nofail(). See parse_interpolation() for what's
* supported after '%'.
*
* Sends a QMP message to QEMU and returns the response.
diff --git a/tests/qtest/tpm-tests.c b/tests/qtest/tpm-tests.c
index 70c80f8..0da3a8a 100644
--- a/tests/qtest/tpm-tests.c
+++ b/tests/qtest/tpm-tests.c
@@ -70,10 +70,8 @@ void tpm_test_swtpm_test(const char *src_tpm_path, tx_func *tx,
qtest_end();
tpm_util_swtpm_kill(swtpm_pid);
- if (addr) {
- g_unlink(addr->u.q_unix.path);
- qapi_free_SocketAddress(addr);
- }
+ g_unlink(addr->u.q_unix.path);
+ qapi_free_SocketAddress(addr);
}
void tpm_test_swtpm_migration_test(const char *src_tpm_path,
diff --git a/tests/vm/openbsd b/tests/vm/openbsd
index ad882a7..386b2c7 100755
--- a/tests/vm/openbsd
+++ b/tests/vm/openbsd
@@ -22,8 +22,8 @@ class OpenBSDVM(basevm.BaseVM):
name = "openbsd"
arch = "x86_64"
- link = "https://cdn.openbsd.org/pub/OpenBSD/6.6/amd64/install66.iso"
- csum = "b22e63df56e6266de6bbeed8e9be0fbe9ee2291551c5bc03f3cc2e4ab9436ee3"
+ link = "https://cdn.openbsd.org/pub/OpenBSD/6.8/amd64/install68.iso"
+ csum = "47e291fcc2d0c1a8ae0b66329f040b33af755b6adbd21739e20bb5ad56f62b6c"
size = "20G"
pkgs = [
# tools
@@ -37,10 +37,10 @@ class OpenBSDVM(basevm.BaseVM):
"bash",
"gmake",
"gsed",
- "gettext",
+ "gettext-tools",
# libs: usb
- "libusb1",
+ "libusb1--",
# libs: crypto
"gnutls",