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: Bandan Das <bsd@redhat.com>
|
||||||
R: Stefan Hajnoczi <stefanha@redhat.com>
|
R: Stefan Hajnoczi <stefanha@redhat.com>
|
||||||
R: Thomas Huth <thuth@redhat.com>
|
R: Thomas Huth <thuth@redhat.com>
|
||||||
|
R: Darren Kenny <darren.kenny@oracle.com>
|
||||||
|
R: Qiuhao Li <Qiuhao.Li@outlook.com>
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: tests/qtest/fuzz/
|
F: tests/qtest/fuzz/
|
||||||
F: tests/qtest/fuzz-*test.c
|
F: tests/qtest/fuzz-*test.c
|
||||||
|
28
configure
vendored
28
configure
vendored
@ -4198,13 +4198,21 @@ fi
|
|||||||
|
|
||||||
##########################################
|
##########################################
|
||||||
# checks for fuzzer
|
# checks for fuzzer
|
||||||
if test "$fuzzing" = "yes" && test -z "${LIB_FUZZING_ENGINE+xxx}"; then
|
if test "$fuzzing" = "yes" ; then
|
||||||
write_c_fuzzer_skeleton
|
write_c_fuzzer_skeleton
|
||||||
if compile_prog "$CPU_CFLAGS -Werror -fsanitize=fuzzer" ""; then
|
if test -z "${LIB_FUZZING_ENGINE+xxx}"; then
|
||||||
have_fuzzer=yes
|
if compile_prog "$CPU_CFLAGS -Werror -fsanitize=fuzzer" ""; then
|
||||||
else
|
have_fuzzer=yes
|
||||||
error_exit "Your compiler doesn't support -fsanitize=fuzzer"
|
else
|
||||||
exit 1
|
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
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@ -4884,6 +4892,14 @@ if test "$fuzzing" = "yes" ; then
|
|||||||
else
|
else
|
||||||
FUZZ_EXE_LDFLAGS="$LIB_FUZZING_ENGINE"
|
FUZZ_EXE_LDFLAGS="$LIB_FUZZING_ENGINE"
|
||||||
fi
|
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
|
fi
|
||||||
|
|
||||||
if test "$plugins" = "yes" ; then
|
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,
|
addr, &addr1, &l, true,
|
||||||
MEMTXATTRS_UNSPECIFIED);
|
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);
|
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 */
|
/* ROM/RAM case */
|
||||||
if (qtest_log_enabled) {
|
if (qtest_log_enabled) {
|
||||||
/*
|
/*
|
||||||
@ -661,31 +668,41 @@ static void generic_fuzz(QTestState *s, const unsigned char *Data, size_t Size)
|
|||||||
uint8_t op;
|
uint8_t op;
|
||||||
|
|
||||||
if (fork() == 0) {
|
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
|
* Sometimes the fuzzer will find inputs that take quite a long time to
|
||||||
* process. Often times, these inputs do not result in new coverage.
|
* process. Often times, these inputs do not result in new coverage.
|
||||||
* Even if these inputs might be interesting, they can slow down the
|
* 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) {
|
if (timeout) {
|
||||||
struct sigaction sact;
|
|
||||||
struct itimerval timer;
|
|
||||||
|
|
||||||
sigemptyset(&sact.sa_mask);
|
sigemptyset(&sact.sa_mask);
|
||||||
sact.sa_flags = SA_NODEFER;
|
sact.sa_flags = SA_NODEFER;
|
||||||
sact.sa_handler = handle_timeout;
|
sact.sa_handler = handle_timeout;
|
||||||
sigaction(SIGALRM, &sact, NULL);
|
sigaction(SIGALRM, &sact, NULL);
|
||||||
|
|
||||||
|
sigemptyset(&set);
|
||||||
|
sigaddset(&set, SIGALRM);
|
||||||
|
pthread_sigmask(SIG_UNBLOCK, &set, NULL);
|
||||||
|
|
||||||
memset(&timer, 0, sizeof(timer));
|
memset(&timer, 0, sizeof(timer));
|
||||||
timer.it_value.tv_sec = timeout / USEC_IN_SEC;
|
timer.it_value.tv_sec = timeout / USEC_IN_SEC;
|
||||||
timer.it_value.tv_usec = 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);
|
op_clear_dma_patterns(s, NULL, 0);
|
||||||
pci_disabled = false;
|
pci_disabled = false;
|
||||||
|
|
||||||
while (cmd && Size) {
|
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 */
|
/* Get the length until the next command or end of input */
|
||||||
nextcmd = memmem(cmd, Size, SEPARATOR, strlen(SEPARATOR));
|
nextcmd = memmem(cmd, Size, SEPARATOR, strlen(SEPARATOR));
|
||||||
cmd_len = nextcmd ? nextcmd - cmd : Size;
|
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)
|
static int locate_fuzz_objects(Object *child, void *opaque)
|
||||||
{
|
{
|
||||||
|
GString *type_name;
|
||||||
|
GString *path_name;
|
||||||
char *pattern = opaque;
|
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 */
|
/* Find and save ptrs to any child MemoryRegions */
|
||||||
object_child_foreach_recursive(child, locate_fuzz_memory_regions, NULL);
|
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));
|
g_ptr_array_add(fuzzable_pci_devices, PCI_DEVICE(child));
|
||||||
}
|
}
|
||||||
} else if (object_dynamic_cast(OBJECT(child), TYPE_MEMORY_REGION)) {
|
} else if (object_dynamic_cast(OBJECT(child), TYPE_MEMORY_REGION)) {
|
||||||
if (g_pattern_match_simple(pattern,
|
path_name = g_string_new(object_get_canonical_path_component(child));
|
||||||
object_get_canonical_path_component(child))) {
|
g_string_ascii_down(path_name);
|
||||||
|
if (g_pattern_match_simple(pattern, path_name->str)) {
|
||||||
MemoryRegion *mr;
|
MemoryRegion *mr;
|
||||||
mr = MEMORY_REGION(child);
|
mr = MEMORY_REGION(child);
|
||||||
if ((memory_region_is_ram(mr) ||
|
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_hash_table_insert(fuzzable_memoryregions, mr, (gpointer)true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
g_string_free(path_name, true);
|
||||||
}
|
}
|
||||||
|
g_string_free(type_name, true);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -802,6 +827,7 @@ static void generic_pre_fuzz(QTestState *s)
|
|||||||
MemoryRegion *mr;
|
MemoryRegion *mr;
|
||||||
QPCIBus *pcibus;
|
QPCIBus *pcibus;
|
||||||
char **result;
|
char **result;
|
||||||
|
GString *name_pattern;
|
||||||
|
|
||||||
if (!getenv("QEMU_FUZZ_OBJECTS")) {
|
if (!getenv("QEMU_FUZZ_OBJECTS")) {
|
||||||
usage();
|
usage();
|
||||||
@ -831,10 +857,17 @@ static void generic_pre_fuzz(QTestState *s)
|
|||||||
|
|
||||||
result = g_strsplit(getenv("QEMU_FUZZ_OBJECTS"), " ", -1);
|
result = g_strsplit(getenv("QEMU_FUZZ_OBJECTS"), " ", -1);
|
||||||
for (int i = 0; result[i] != NULL; i++) {
|
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]);
|
printf("Matching objects by name %s\n", result[i]);
|
||||||
object_child_foreach_recursive(qdev_get_machine(),
|
object_child_foreach_recursive(qdev_get_machine(),
|
||||||
locate_fuzz_objects,
|
locate_fuzz_objects,
|
||||||
result[i]);
|
name_pattern->str);
|
||||||
|
g_string_free(name_pattern, true);
|
||||||
}
|
}
|
||||||
g_strfreev(result);
|
g_strfreev(result);
|
||||||
printf("This process will try to fuzz the following MemoryRegions:\n");
|
printf("This process will try to fuzz the following MemoryRegions:\n");
|
||||||
|
Loading…
Reference in New Issue
Block a user