Fuzzing Patches for 2021-09-01
-----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEE+tTiv4cTddY0BRfETmYd3lg6lk4FAmEvZwgACgkQTmYd3lg6 lk6nCw//X5wVWFBHDw+7nQ3lpu/rYTVTdqzdwgcOih5ima4ZeqmRbEMGhKYHcekZ YQxAP3r4k11Fp2Jev4CS18c4TVE/jYE7d8RwS5ROGTT8IOhe3Ntgd6d5MNjIdm86 HwaTmmrxpL2cCWUgCGX8H+BXT0p+sjNpMTXfgu9CYlYEgVQKVRiTBTEsCku12FRM kwqHaFzJZoFMd45NhbH2wHt/dmDVuVYp7UuCM/HzNFKLO8E25sBLQip97RRTgInB iT9vadTYsgkrdRbIWiQbP8vWKL4D0SS7Sw6DYlxTCYhEEZffiiXPVqEwf+qr9LRX sLui6vMyjLB4yhjsg5AEd0IMZSP4H431su6YEuP0XOXG5yh5nSNkGVim0ezt1UBF DDvYDumVK0P4seCVhK87fEejW9+GAlTSf65LBcK07JSo5DLyRzfmwBXQM3EKzdCK y58Jthkmlhe4zym40WNwM91QFaNuWAD0pdvB9fa9OcidvuLgkhdgN72LJVgZSoq9 7UuWSV6laTnTAIP1YL4R5fvq1r5gNE1cnzCFf6th87pmvOUhO43Y2dT6Me8UR0v8 B7tHxtAiZJkfWvOYL4Jy3vaBXuivZCtEYUUDc0Y0Cmzfd9DnvnkxrKirZ6ECoyDs RsR6nUO1tbpe0ekdl8EvYG3PRt8iHIahZ25GnKcUSTRFydetPqE= =ec6M -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/a1xndr/tags/fuzz-pull-2021-09-01' into staging Fuzzing Patches for 2021-09-01 # gpg: Signature made Wed 01 Sep 2021 12:42:00 BST # gpg: using RSA key FAD4E2BF871375D6340517C44E661DDE583A964E # gpg: Good signature from "Alexander Bulekov <alxndr@bu.edu>" [unknown] # gpg: WARNING: This key is not certified with a trusted signature! # gpg: There is no indication that the signature belongs to the owner. # Primary key fingerprint: FAD4 E2BF 8713 75D6 3405 17C4 4E66 1DDE 583A 964E * remotes/a1xndr/tags/fuzz-pull-2021-09-01: MAINTAINERS: add fuzzing reviewer MAINTAINERS: Add myself as a reviewer for Device Fuzzing fuzz: unblock SIGALRM so the timeout works fuzz: use ITIMER_REAL for timeouts fuzz: add an instrumentation filter fuzz: make object-name matching case-insensitive fuzz: adjust timeout to allow for longer inputs fuzz: fix sparse memory access in the DMA callback Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
8664d30a30
@ -2760,6 +2760,8 @@ R: Paolo Bonzini <pbonzini@redhat.com>
|
||||
R: Bandan Das <bsd@redhat.com>
|
||||
R: Stefan Hajnoczi <stefanha@redhat.com>
|
||||
R: Thomas Huth <thuth@redhat.com>
|
||||
R: Darren Kenny <darren.kenny@oracle.com>
|
||||
R: Qiuhao Li <Qiuhao.Li@outlook.com>
|
||||
S: Maintained
|
||||
F: tests/qtest/fuzz/
|
||||
F: tests/qtest/fuzz-*test.c
|
||||
|
28
configure
vendored
28
configure
vendored
@ -4198,13 +4198,21 @@ fi
|
||||
|
||||
##########################################
|
||||
# checks for fuzzer
|
||||
if test "$fuzzing" = "yes" && test -z "${LIB_FUZZING_ENGINE+xxx}"; then
|
||||
if test "$fuzzing" = "yes" ; then
|
||||
write_c_fuzzer_skeleton
|
||||
if compile_prog "$CPU_CFLAGS -Werror -fsanitize=fuzzer" ""; then
|
||||
have_fuzzer=yes
|
||||
else
|
||||
error_exit "Your compiler doesn't support -fsanitize=fuzzer"
|
||||
exit 1
|
||||
if test -z "${LIB_FUZZING_ENGINE+xxx}"; then
|
||||
if compile_prog "$CPU_CFLAGS -Werror -fsanitize=fuzzer" ""; then
|
||||
have_fuzzer=yes
|
||||
else
|
||||
error_exit "Your compiler doesn't support -fsanitize=fuzzer"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
have_clang_coverage_filter=no
|
||||
echo > $TMPTXT
|
||||
if compile_prog "$CPU_CFLAGS -Werror -fsanitize=fuzzer -fsanitize-coverage-allowlist=$TMPTXT" ""; then
|
||||
have_clang_coverage_filter=yes
|
||||
fi
|
||||
fi
|
||||
|
||||
@ -4884,6 +4892,14 @@ if test "$fuzzing" = "yes" ; then
|
||||
else
|
||||
FUZZ_EXE_LDFLAGS="$LIB_FUZZING_ENGINE"
|
||||
fi
|
||||
|
||||
# Specify a filter to only instrument code that is directly related to
|
||||
# virtual-devices.
|
||||
if test "$have_clang_coverage_filter" = "yes" ; then
|
||||
cp "$source_path/scripts/oss-fuzz/instrumentation-filter-template" \
|
||||
instrumentation-filter
|
||||
QEMU_CFLAGS="$QEMU_CFLAGS -fsanitize-coverage-allowlist=instrumentation-filter"
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "$plugins" = "yes" ; then
|
||||
|
15
scripts/oss-fuzz/instrumentation-filter-template
Normal file
15
scripts/oss-fuzz/instrumentation-filter-template
Normal file
@ -0,0 +1,15 @@
|
||||
# Code that we actually want the fuzzer to target
|
||||
# See: https://clang.llvm.org/docs/SanitizerCoverage.html#disabling-instrumentation-without-source-modification
|
||||
#
|
||||
src:*/hw/*
|
||||
src:*/include/hw/*
|
||||
src:*/slirp/*
|
||||
src:*/net/*
|
||||
|
||||
# We don't care about coverage over fuzzer-specific code, however we should
|
||||
# instrument the fuzzer entry-point so libFuzzer always sees at least some
|
||||
# coverage - otherwise it will exit after the first input
|
||||
src:*/tests/qtest/fuzz/fuzz.c
|
||||
|
||||
# Enable instrumentation for all functions in those files
|
||||
fun:*
|
@ -240,10 +240,17 @@ void fuzz_dma_read_cb(size_t addr, size_t len, MemoryRegion *mr)
|
||||
addr, &addr1, &l, true,
|
||||
MEMTXATTRS_UNSPECIFIED);
|
||||
|
||||
if (!(memory_region_is_ram(mr1) ||
|
||||
memory_region_is_romd(mr1)) && mr1 != sparse_mem_mr) {
|
||||
/*
|
||||
* If mr1 isn't RAM, address_space_translate doesn't update l. Use
|
||||
* memory_access_size to identify the number of bytes that it is safe
|
||||
* to write without accidentally writing to another MemoryRegion.
|
||||
*/
|
||||
if (!memory_region_is_ram(mr1)) {
|
||||
l = memory_access_size(mr1, l, addr1);
|
||||
} else {
|
||||
}
|
||||
if (memory_region_is_ram(mr1) ||
|
||||
memory_region_is_romd(mr1) ||
|
||||
mr1 == sparse_mem_mr) {
|
||||
/* ROM/RAM case */
|
||||
if (qtest_log_enabled) {
|
||||
/*
|
||||
@ -661,31 +668,41 @@ static void generic_fuzz(QTestState *s, const unsigned char *Data, size_t Size)
|
||||
uint8_t op;
|
||||
|
||||
if (fork() == 0) {
|
||||
struct sigaction sact;
|
||||
struct itimerval timer;
|
||||
sigset_t set;
|
||||
/*
|
||||
* Sometimes the fuzzer will find inputs that take quite a long time to
|
||||
* process. Often times, these inputs do not result in new coverage.
|
||||
* Even if these inputs might be interesting, they can slow down the
|
||||
* fuzzer, overall. Set a timeout to avoid hurting performance, too much
|
||||
* fuzzer, overall. Set a timeout for each command to avoid hurting
|
||||
* performance, too much
|
||||
*/
|
||||
if (timeout) {
|
||||
struct sigaction sact;
|
||||
struct itimerval timer;
|
||||
|
||||
sigemptyset(&sact.sa_mask);
|
||||
sact.sa_flags = SA_NODEFER;
|
||||
sact.sa_handler = handle_timeout;
|
||||
sigaction(SIGALRM, &sact, NULL);
|
||||
|
||||
sigemptyset(&set);
|
||||
sigaddset(&set, SIGALRM);
|
||||
pthread_sigmask(SIG_UNBLOCK, &set, NULL);
|
||||
|
||||
memset(&timer, 0, sizeof(timer));
|
||||
timer.it_value.tv_sec = timeout / USEC_IN_SEC;
|
||||
timer.it_value.tv_usec = timeout % USEC_IN_SEC;
|
||||
setitimer(ITIMER_VIRTUAL, &timer, NULL);
|
||||
}
|
||||
|
||||
op_clear_dma_patterns(s, NULL, 0);
|
||||
pci_disabled = false;
|
||||
|
||||
while (cmd && Size) {
|
||||
/* Reset the timeout, each time we run a new command */
|
||||
if (timeout) {
|
||||
setitimer(ITIMER_REAL, &timer, NULL);
|
||||
}
|
||||
|
||||
/* Get the length until the next command or end of input */
|
||||
nextcmd = memmem(cmd, Size, SEPARATOR, strlen(SEPARATOR));
|
||||
cmd_len = nextcmd ? nextcmd - cmd : Size;
|
||||
@ -746,8 +763,13 @@ static int locate_fuzz_memory_regions(Object *child, void *opaque)
|
||||
|
||||
static int locate_fuzz_objects(Object *child, void *opaque)
|
||||
{
|
||||
GString *type_name;
|
||||
GString *path_name;
|
||||
char *pattern = opaque;
|
||||
if (g_pattern_match_simple(pattern, object_get_typename(child))) {
|
||||
|
||||
type_name = g_string_new(object_get_typename(child));
|
||||
g_string_ascii_down(type_name);
|
||||
if (g_pattern_match_simple(pattern, type_name->str)) {
|
||||
/* Find and save ptrs to any child MemoryRegions */
|
||||
object_child_foreach_recursive(child, locate_fuzz_memory_regions, NULL);
|
||||
|
||||
@ -764,8 +786,9 @@ static int locate_fuzz_objects(Object *child, void *opaque)
|
||||
g_ptr_array_add(fuzzable_pci_devices, PCI_DEVICE(child));
|
||||
}
|
||||
} else if (object_dynamic_cast(OBJECT(child), TYPE_MEMORY_REGION)) {
|
||||
if (g_pattern_match_simple(pattern,
|
||||
object_get_canonical_path_component(child))) {
|
||||
path_name = g_string_new(object_get_canonical_path_component(child));
|
||||
g_string_ascii_down(path_name);
|
||||
if (g_pattern_match_simple(pattern, path_name->str)) {
|
||||
MemoryRegion *mr;
|
||||
mr = MEMORY_REGION(child);
|
||||
if ((memory_region_is_ram(mr) ||
|
||||
@ -774,7 +797,9 @@ static int locate_fuzz_objects(Object *child, void *opaque)
|
||||
g_hash_table_insert(fuzzable_memoryregions, mr, (gpointer)true);
|
||||
}
|
||||
}
|
||||
g_string_free(path_name, true);
|
||||
}
|
||||
g_string_free(type_name, true);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -802,6 +827,7 @@ static void generic_pre_fuzz(QTestState *s)
|
||||
MemoryRegion *mr;
|
||||
QPCIBus *pcibus;
|
||||
char **result;
|
||||
GString *name_pattern;
|
||||
|
||||
if (!getenv("QEMU_FUZZ_OBJECTS")) {
|
||||
usage();
|
||||
@ -831,10 +857,17 @@ static void generic_pre_fuzz(QTestState *s)
|
||||
|
||||
result = g_strsplit(getenv("QEMU_FUZZ_OBJECTS"), " ", -1);
|
||||
for (int i = 0; result[i] != NULL; i++) {
|
||||
name_pattern = g_string_new(result[i]);
|
||||
/*
|
||||
* Make the pattern lowercase. We do the same for all the MemoryRegion
|
||||
* and Type names so the configs are case-insensitive.
|
||||
*/
|
||||
g_string_ascii_down(name_pattern);
|
||||
printf("Matching objects by name %s\n", result[i]);
|
||||
object_child_foreach_recursive(qdev_get_machine(),
|
||||
locate_fuzz_objects,
|
||||
result[i]);
|
||||
name_pattern->str);
|
||||
g_string_free(name_pattern, true);
|
||||
}
|
||||
g_strfreev(result);
|
||||
printf("This process will try to fuzz the following MemoryRegions:\n");
|
||||
|
Loading…
Reference in New Issue
Block a user