diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2020-11-10 12:23:05 +0000 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2020-11-10 12:23:05 +0000 |
commit | 879860ca706fa1ef47ba511c49a6e2b1b49be9b7 (patch) | |
tree | f6557aa49be6e488920c865482ce4c874337cc38 | |
parent | 6c8e801f076109a31d864fdbeec57badd159fb06 (diff) | |
parent | a58cabd0e355fc51f18db359ba260da268df26ef (diff) |
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>
27 files changed, 577 insertions, 264 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 3b15ae5c30..9a8b375188 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 0e60109d28..6c2df0bef3 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> @@ -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 0000000000..4319b0f5ac --- /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 e584f68393..d40d8ff37b 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 0000000000..a86d22bca8 --- /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 0000000000..6096242d99 --- /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 03585c1a9b..0000000000 --- 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 77baae5c77..f10ed77e4c 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 0000000000..215e562681 --- /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 0000000000..aaa468aa98 --- /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 0000000000..6586b2e257 --- /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 0000000000..2a9c8fc92b --- /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 0000000000..1f5ee01e60 --- /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 9e90169695..dfc6dfd89c 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 f5175010df..b473620321 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 866baf7058..04118669ba 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 3b1c82b63d..c1af43fded 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 461e0b8f4a..b5abff8bef 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 d20094d5a7..bc681a95d5 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 bfb667ed06..cfb88b7fdb 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 5162321f30..8af6848cd5 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 0000000000..623a756fd4 --- /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 5c959f1853..724f65aa94 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 176979a2ce..0d7f568678 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 70c80f8379..0da3a8a4df 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 ad882a76a2..386b2c72f7 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", |