* Fix memory leak in fuzzer
* Fuzzer documentation updates * Some other minor fuzzer updates * Fix "make check-qtest SPEED=slow" (bug in msf2 instance_init) -----BEGIN PGP SIGNATURE----- iQJFBAABCAAvFiEEJ7iIR+7gJQEY8+q5LtnXdP5wLbUFAl8Wj6oRHHRodXRoQHJl ZGhhdC5jb20ACgkQLtnXdP5wLbWHSA//QBjJ3mLlFXTyKzgloDCRi8Y7f3TtpGNo A1oyub/TIpUFif7/57nOD3XYwwYwaAhxY19cgQsEwXFXOxWEhkLg2QMaLimop31K mKwoXrJiuzrpVWcDZLdLpxCUQbljo2pT7QJDnPLAA14c6/32Frxoh2BO8B/RyFeq mReSVpwL0lfmdxVZpHk/61fluVikT0NJEBaDXf1zcNt09ejPR6hC423aqc9Dzt5t IyacpGUDIS4miY2VM4FZm9MnSTTqMjuKEUKFS+VtdEuEzxqiM2+uqikfHIDjIpQz JBOzI0b9PTXO3WGfN2ZDPmgiCCh68EMX2lM4RlrqMcCagW6KLyBvANfMnblyZFHK Ufz8vjp542o9j145y9wOyMJ0DQR9njaWbR+v+BeJ6T25Qb8XZgEv18H4M73yJdRa jTcd78punfpJf1vSVP7S1JiRlgh7EPLjJZF48Nk7kDtxl/zc8QG221p/Rm8QtGTq gPZdZocbVj/rv8qVEzSRpDRb2MdSYt5acTzXS/DGb0fhr2KEf5zr6snBY9V+G8un sH2OpVgJiBwyuNqg+3D3SjH4aWK83RL6WvPPaUfEdW8sATow0yXRwQhKKvnGUl2L bH9YAvInJgmvxr1tZcQOji12QfM4ZYMrMhKbblVlyh2V4IyhhXIXfvauuyUSLt6A Kw0Su8gq2Ic= =xq1/ -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/huth-gitlab/tags/pull-request-2020-07-21' into staging * Fix memory leak in fuzzer * Fuzzer documentation updates * Some other minor fuzzer updates * Fix "make check-qtest SPEED=slow" (bug in msf2 instance_init) # gpg: Signature made Tue 21 Jul 2020 07:48:10 BST # 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-07-21: hw: Mark nd_table[] misuse in realize methods FIXME msf2: Unbreak device-list-properties for "msf-soc" MAINTAINERS: Extend the device fuzzing section docs/fuzz: add instructions for generating a coverage report docs/fuzz: add information about useful libFuzzer flags docs/fuzz: describe building fuzzers with enable-sanitizers fuzz: build without AddressSanitizer, by default gitlab-ci.yml: Add oss-fuzz build tests fuzz: Fix leak when assembling datadir path string scripts/oss-fuzz: Limit target list to i386-softmmu Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
90218a9a39
@ -164,22 +164,20 @@ build-clang:
|
||||
ppc-softmmu s390x-softmmu arm-linux-user
|
||||
MAKE_CHECK_ARGS: check
|
||||
|
||||
build-fuzzer:
|
||||
build-oss-fuzz:
|
||||
<<: *native_build_job_definition
|
||||
variables:
|
||||
IMAGE: fedora
|
||||
script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ../configure --cc=clang --cxx=clang++ --enable-fuzzing
|
||||
--enable-sanitizers --target-list=x86_64-softmmu
|
||||
- make -j"$JOBS" all check-build x86_64-softmmu/fuzz
|
||||
- make check
|
||||
- for fuzzer in i440fx-qos-fork-fuzz i440fx-qos-noreset-fuzz
|
||||
i440fx-qtest-reboot-fuzz virtio-scsi-flags-fuzz virtio-scsi-fuzz ; do
|
||||
echo Testing ${fuzzer} ... ;
|
||||
x86_64-softmmu/qemu-fuzz-x86_64 --fuzz-target=${fuzzer} -runs=1000
|
||||
|| exit 1 ;
|
||||
- mkdir build-oss-fuzz
|
||||
- CC="clang" CXX="clang++" CFLAGS="-fsanitize=address"
|
||||
./scripts/oss-fuzz/build.sh
|
||||
- for fuzzer in $(find ./build-oss-fuzz/DEST_DIR/ -executable -type f
|
||||
| grep -v slirp); do
|
||||
grep "LLVMFuzzerTestOneInput" ${fuzzer} > /dev/null 2>&1 || continue ;
|
||||
echo Testing ${fuzzer} ... ;
|
||||
ASAN_OPTIONS="fast_unwind_on_malloc=0"
|
||||
"${fuzzer}" -runs=1000 -seed=1 || exit 1 ;
|
||||
done
|
||||
|
||||
build-tci:
|
||||
|
@ -2449,9 +2449,11 @@ M: Alexander Bulekov <alxndr@bu.edu>
|
||||
R: Paolo Bonzini <pbonzini@redhat.com>
|
||||
R: Bandan Das <bsd@redhat.com>
|
||||
R: Stefan Hajnoczi <stefanha@redhat.com>
|
||||
R: Thomas Huth <thuth@redhat.com>
|
||||
S: Maintained
|
||||
F: tests/qtest/fuzz/
|
||||
F: scripts/oss-fuzz/
|
||||
F: docs/devel/fuzzing.txt
|
||||
|
||||
Register API
|
||||
M: Alistair Francis <alistair@alistair23.me>
|
||||
|
10
configure
vendored
10
configure
vendored
@ -6337,7 +6337,7 @@ fi
|
||||
# checks for fuzzer
|
||||
if test "$fuzzing" = "yes" ; then
|
||||
write_c_fuzzer_skeleton
|
||||
if compile_prog "$CPU_CFLAGS -Werror -fsanitize=address,fuzzer" ""; then
|
||||
if compile_prog "$CPU_CFLAGS -Werror -fsanitize=fuzzer" ""; then
|
||||
have_fuzzer=yes
|
||||
fi
|
||||
fi
|
||||
@ -7893,11 +7893,11 @@ if test "$have_mlockall" = "yes" ; then
|
||||
fi
|
||||
if test "$fuzzing" = "yes" ; then
|
||||
if test "$have_fuzzer" = "yes"; then
|
||||
FUZZ_LDFLAGS=" -fsanitize=address,fuzzer"
|
||||
FUZZ_CFLAGS=" -fsanitize=address,fuzzer"
|
||||
CFLAGS="$CFLAGS -fsanitize=address,fuzzer-no-link"
|
||||
FUZZ_LDFLAGS=" -fsanitize=fuzzer"
|
||||
FUZZ_CFLAGS=" -fsanitize=fuzzer"
|
||||
CFLAGS="$CFLAGS -fsanitize=fuzzer-no-link"
|
||||
else
|
||||
error_exit "Your compiler doesn't support -fsanitize=address,fuzzer"
|
||||
error_exit "Your compiler doesn't support -fsanitize=fuzzer"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
@ -23,9 +23,12 @@ 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):
|
||||
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
|
||||
CC=clang-8 CXX=clang++-8 /path/to/configure --enable-fuzzing \
|
||||
--enable-sanitizers
|
||||
|
||||
Fuzz targets are built similarly to system/softmmu:
|
||||
|
||||
@ -45,6 +48,62 @@ 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
|
||||
|
@ -358,6 +358,7 @@ static void allwinner_h3_realize(DeviceState *dev, Error **errp)
|
||||
"sd-bus");
|
||||
|
||||
/* EMAC */
|
||||
/* FIXME use qdev NIC properties instead of nd_table[] */
|
||||
if (nd_table[0].used) {
|
||||
qemu_check_nic_model(&nd_table[0], TYPE_AW_SUN8I_EMAC);
|
||||
qdev_set_nic_properties(DEVICE(&s->emac), &nd_table[0]);
|
||||
|
@ -82,10 +82,6 @@ static void m2sxxx_soc_initfn(Object *obj)
|
||||
}
|
||||
|
||||
object_initialize_child(obj, "emac", &s->emac, TYPE_MSS_EMAC);
|
||||
if (nd_table[0].used) {
|
||||
qemu_check_nic_model(&nd_table[0], TYPE_MSS_EMAC);
|
||||
qdev_set_nic_properties(DEVICE(&s->emac), &nd_table[0]);
|
||||
}
|
||||
}
|
||||
|
||||
static void m2sxxx_soc_realize(DeviceState *dev_soc, Error **errp)
|
||||
@ -187,6 +183,11 @@ static void m2sxxx_soc_realize(DeviceState *dev_soc, Error **errp)
|
||||
g_free(bus_name);
|
||||
}
|
||||
|
||||
/* FIXME use qdev NIC properties instead of nd_table[] */
|
||||
if (nd_table[0].used) {
|
||||
qemu_check_nic_model(&nd_table[0], TYPE_MSS_EMAC);
|
||||
qdev_set_nic_properties(DEVICE(&s->emac), &nd_table[0]);
|
||||
}
|
||||
dev = DEVICE(&s->emac);
|
||||
object_property_set_link(OBJECT(&s->emac), "ahb-bus",
|
||||
OBJECT(get_system_memory()), &error_abort);
|
||||
|
@ -160,6 +160,7 @@ static void versal_create_gems(Versal *s, qemu_irq *pic)
|
||||
object_initialize_child(OBJECT(s), name, &s->lpd.iou.gem[i],
|
||||
TYPE_CADENCE_GEM);
|
||||
dev = DEVICE(&s->lpd.iou.gem[i]);
|
||||
/* FIXME use qdev NIC properties instead of nd_table[] */
|
||||
if (nd->used) {
|
||||
qemu_check_nic_model(nd, "cadence_gem");
|
||||
qdev_set_nic_properties(dev, nd);
|
||||
|
@ -455,6 +455,7 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
|
||||
for (i = 0; i < XLNX_ZYNQMP_NUM_GEMS; i++) {
|
||||
NICInfo *nd = &nd_table[i];
|
||||
|
||||
/* FIXME use qdev NIC properties instead of nd_table[] */
|
||||
if (nd->used) {
|
||||
qemu_check_nic_model(nd, TYPE_CADENCE_GEM);
|
||||
qdev_set_nic_properties(DEVICE(&s->gem[i]), nd);
|
||||
|
@ -341,6 +341,7 @@ static void sparc32_ledma_device_realize(DeviceState *dev, Error **errp)
|
||||
DeviceState *d;
|
||||
NICInfo *nd = &nd_table[0];
|
||||
|
||||
/* FIXME use qdev NIC properties instead of nd_table[] */
|
||||
qemu_check_nic_model(nd, TYPE_LANCE);
|
||||
|
||||
d = qdev_new(TYPE_LANCE);
|
||||
|
@ -714,6 +714,7 @@ static void sifive_u_soc_realize(DeviceState *dev, Error **errp)
|
||||
}
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(&s->otp), 0, memmap[SIFIVE_U_OTP].base);
|
||||
|
||||
/* FIXME use qdev NIC properties instead of nd_table[] */
|
||||
if (nd->used) {
|
||||
qemu_check_nic_model(nd, TYPE_CADENCE_GEM);
|
||||
qdev_set_nic_properties(DEVICE(&s->gem), nd);
|
||||
|
@ -68,7 +68,7 @@ mkdir -p "$DEST_DIR/lib/" # Copy the shared libraries here
|
||||
|
||||
# Build once to get the list of dynamic lib paths, and copy them over
|
||||
../configure --disable-werror --cc="$CC" --cxx="$CXX" \
|
||||
--extra-cflags="$EXTRA_CFLAGS"
|
||||
--extra-cflags="$EXTRA_CFLAGS" --target-list="i386-softmmu"
|
||||
|
||||
if ! make CONFIG_FUZZ=y CFLAGS="$LIB_FUZZING_ENGINE" "-j$(nproc)" \
|
||||
i386-softmmu/fuzz; then
|
||||
|
@ -143,7 +143,7 @@ int LLVMFuzzerInitialize(int *argc, char ***argv, char ***envp)
|
||||
{
|
||||
|
||||
char *target_name;
|
||||
char *dir;
|
||||
char *bindir, *datadir;
|
||||
bool serialize = false;
|
||||
|
||||
/* Initialize qgraph and modules */
|
||||
@ -164,11 +164,13 @@ int LLVMFuzzerInitialize(int *argc, char ***argv, char ***envp)
|
||||
* location of the executable. Using this we add exec_dir/pc-bios to
|
||||
* the datadirs.
|
||||
*/
|
||||
dir = g_build_filename(g_path_get_dirname(**argv), "pc-bios", NULL);
|
||||
if (g_file_test(dir, G_FILE_TEST_IS_DIR)) {
|
||||
qemu_add_data_dir(dir);
|
||||
bindir = g_path_get_dirname(**argv);
|
||||
datadir = g_build_filename(bindir, "pc-bios", NULL);
|
||||
g_free(bindir);
|
||||
if (g_file_test(datadir, G_FILE_TEST_IS_DIR)) {
|
||||
qemu_add_data_dir(datadir);
|
||||
}
|
||||
g_free(dir);
|
||||
g_free(datadir);
|
||||
} else if (*argc > 1) { /* The target is specified as an argument */
|
||||
target_name = (*argv)[1];
|
||||
if (!strstr(target_name, "--fuzz-target=")) {
|
||||
|
Loading…
Reference in New Issue
Block a user