All of lore.kernel.org
 help / color / mirror / Atom feed
* [PULL 0/3] Fuzzing Patches
@ 2021-07-13  5:48 Alexander Bulekov
  2021-07-13  5:48 ` [PULL 1/3] fuzz: fix sparse memory access in the DMA callback Alexander Bulekov
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Alexander Bulekov @ 2021-07-13  5:48 UTC (permalink / raw)
  To: qemu-devel; +Cc: Paolo Bonzini, Alexander Bulekov

Hello Paolo,

The following changes since commit 711c0418c8c1ce3a24346f058b001c4c5a2f0f81:

  Merge remote-tracking branch 'remotes/philmd/tags/mips-20210702' into staging (2021-07-04 14:04:12 +0100)

are available in the Git repository at:

  https://gitlab.com/a1xndr/qemu tags/pull-request-2021-07-12

for you to fetch changes up to 3f4a00e1ec2ee9ab34cfbb8a955c3089256b21c2:

  fuzz: make object-name matching case-insensitive (2021-07-12 09:56:13 -0400)

----------------------------------------------------------------
Fuzzing PR for 6.1: Bug-fixes and refined timeout mechanism

----------------------------------------------------------------
Alexander Bulekov (3):
      fuzz: fix sparse memory access in the DMA callback
      fuzz: adjust timeout to allow for longer inputs
      fuzz: make object-name matching case-insensitive

 tests/qtest/fuzz/generic_fuzz.c | 50 +++++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 39 insertions(+), 11 deletions(-)

-- 
2.28.0



^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PULL 1/3] fuzz: fix sparse memory access in the DMA callback
  2021-07-13  5:48 [PULL 0/3] Fuzzing Patches Alexander Bulekov
@ 2021-07-13  5:48 ` Alexander Bulekov
  2021-07-13  5:48 ` [PULL 2/3] fuzz: adjust timeout to allow for longer inputs Alexander Bulekov
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Alexander Bulekov @ 2021-07-13  5:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: Paolo Bonzini, Philippe Mathieu-Daudé,
	Darren Kenny, Alexander Bulekov

The code mistakenly relied on address_space_translate to store the
length remaining until the next memory-region. We care about this
because when there is RAM or sparse-memory neighboring on an MMIO
region, we should only write up to the border, to prevent inadvertently
invoking MMIO handlers within the DMA callback.

However address_space_translate_internal only stores the length until
the end of the MemoryRegion if memory_region_is_ram(mr). Otherwise
the *len is left unmodified. This caused some false-positive issues,
where the fuzzer found a way to perform a nested MMIO write through a
DMA callback on an [address, length] that started within sparse memory
and spanned some device MMIO regions.

To fix this, write to sparse memory in small chunks of
memory_access_size (similar to the underlying address_space_write code),
which will prevent accidentally hitting MMIO handlers through large
writes.

Signed-off-by: Alexander Bulekov <alxndr@bu.edu>
Reviewed-by: Darren Kenny <darren.kenny@oracle.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
---
 tests/qtest/fuzz/generic_fuzz.c | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/tests/qtest/fuzz/generic_fuzz.c b/tests/qtest/fuzz/generic_fuzz.c
index 6c67522717..0ea47298b7 100644
--- a/tests/qtest/fuzz/generic_fuzz.c
+++ b/tests/qtest/fuzz/generic_fuzz.c
@@ -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) {
                 /*
-- 
2.28.0



^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PULL 2/3] fuzz: adjust timeout to allow for longer inputs
  2021-07-13  5:48 [PULL 0/3] Fuzzing Patches Alexander Bulekov
  2021-07-13  5:48 ` [PULL 1/3] fuzz: fix sparse memory access in the DMA callback Alexander Bulekov
@ 2021-07-13  5:48 ` Alexander Bulekov
  2021-07-13  5:48 ` [PULL 3/3] fuzz: make object-name matching case-insensitive Alexander Bulekov
  2021-07-13 15:00 ` [PULL 0/3] Fuzzing Patches Alexander Bulekov
  3 siblings, 0 replies; 5+ messages in thread
From: Alexander Bulekov @ 2021-07-13  5:48 UTC (permalink / raw)
  To: qemu-devel; +Cc: Paolo Bonzini, Darren Kenny, Alexander Bulekov

Using a custom timeout is useful to continue fuzzing complex devices,
even after we run into some slow code-path. However, simply adding a
fixed timeout to each input effectively caps the maximum input
length/number of operations at some artificial value. There are two
major problems with this:
1. Some code might only be reachable through long IO sequences.
2. Longer inputs can actually be _better_ for performance. While the
   raw number of fuzzer executions decreases with larger inputs, the
   number of MMIO/PIO/DMA operation/second actually increases, since
   were are speding proportionately less time fork()ing.

With this change, we keep the custom-timeout, but we renew it, prior to
each MMIO/PIO/DMA operation. Thus, we time-out only when a specific
operation takes a long time.

Reviewed-by: Darren Kenny <darren.kenny@oracle.com>
Signed-off-by: Alexander Bulekov <alxndr@bu.edu>
---
 tests/qtest/fuzz/generic_fuzz.c | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/tests/qtest/fuzz/generic_fuzz.c b/tests/qtest/fuzz/generic_fuzz.c
index 0ea47298b7..80eb29bd2d 100644
--- a/tests/qtest/fuzz/generic_fuzz.c
+++ b/tests/qtest/fuzz/generic_fuzz.c
@@ -668,15 +668,16 @@ 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;
         /*
          * 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;
@@ -686,13 +687,17 @@ static void generic_fuzz(QTestState *s, const unsigned char *Data, size_t Size)
             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_VIRTUAL, &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;
-- 
2.28.0



^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PULL 3/3] fuzz: make object-name matching case-insensitive
  2021-07-13  5:48 [PULL 0/3] Fuzzing Patches Alexander Bulekov
  2021-07-13  5:48 ` [PULL 1/3] fuzz: fix sparse memory access in the DMA callback Alexander Bulekov
  2021-07-13  5:48 ` [PULL 2/3] fuzz: adjust timeout to allow for longer inputs Alexander Bulekov
@ 2021-07-13  5:48 ` Alexander Bulekov
  2021-07-13 15:00 ` [PULL 0/3] Fuzzing Patches Alexander Bulekov
  3 siblings, 0 replies; 5+ messages in thread
From: Alexander Bulekov @ 2021-07-13  5:48 UTC (permalink / raw)
  To: qemu-devel; +Cc: Paolo Bonzini, Darren Kenny, Alexander Bulekov

We have some configs for devices such as the AC97 and ES1370 that were
not matching memory-regions correctly, because the configs provided
lowercase names. To resolve these problems and prevent them from
occurring again in the future, convert both the pattern and names to
lower-case, prior to checking for a match.

Suggested-by: Darren Kenny <darren.kenny@oracle.com>
Reviewed-by: Darren Kenny <darren.kenny@oracle.com>
Signed-off-by: Alexander Bulekov <alxndr@bu.edu>
---
 tests/qtest/fuzz/generic_fuzz.c | 24 ++++++++++++++++++++----
 1 file changed, 20 insertions(+), 4 deletions(-)

diff --git a/tests/qtest/fuzz/generic_fuzz.c b/tests/qtest/fuzz/generic_fuzz.c
index 80eb29bd2d..3e8ce29227 100644
--- a/tests/qtest/fuzz/generic_fuzz.c
+++ b/tests/qtest/fuzz/generic_fuzz.c
@@ -758,8 +758,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);
 
@@ -776,8 +781,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) ||
@@ -786,7 +792,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;
 }
 
@@ -814,6 +822,7 @@ static void generic_pre_fuzz(QTestState *s)
     MemoryRegion *mr;
     QPCIBus *pcibus;
     char **result;
+    GString *name_pattern;
 
     if (!getenv("QEMU_FUZZ_OBJECTS")) {
         usage();
@@ -843,10 +852,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");
-- 
2.28.0



^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PULL 0/3] Fuzzing Patches
  2021-07-13  5:48 [PULL 0/3] Fuzzing Patches Alexander Bulekov
                   ` (2 preceding siblings ...)
  2021-07-13  5:48 ` [PULL 3/3] fuzz: make object-name matching case-insensitive Alexander Bulekov
@ 2021-07-13 15:00 ` Alexander Bulekov
  3 siblings, 0 replies; 5+ messages in thread
From: Alexander Bulekov @ 2021-07-13 15:00 UTC (permalink / raw)
  To: qemu-devel; +Cc: Paolo Bonzini

On 210713 0148, Alexander Bulekov wrote:
> Hello Paolo,
> 
> The following changes since commit 711c0418c8c1ce3a24346f058b001c4c5a2f0f81:
> 
>   Merge remote-tracking branch 'remotes/philmd/tags/mips-20210702' into staging (2021-07-04 14:04:12 +0100)
> 
> are available in the Git repository at:
> 
>   https://gitlab.com/a1xndr/qemu tags/pull-request-2021-07-12
> 
> for you to fetch changes up to 3f4a00e1ec2ee9ab34cfbb8a955c3089256b21c2:
> 
>   fuzz: make object-name matching case-insensitive (2021-07-12 09:56:13 -0400)
> 
> ----------------------------------------------------------------
> Fuzzing PR for 6.1: Bug-fixes and refined timeout mechanism
> 
> ----------------------------------------------------------------
> Alexander Bulekov (3):
>       fuzz: fix sparse memory access in the DMA callback
>       fuzz: adjust timeout to allow for longer inputs
>       fuzz: make object-name matching case-insensitive
> 
>  tests/qtest/fuzz/generic_fuzz.c | 50 +++++++++++++++++++++++++++++++++++++++-----------
>  1 file changed, 39 insertions(+), 11 deletions(-)
> 
> -- 
> 2.28.0
> 

One more Patch was reviewed, so I just sent a v2.


^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2021-07-13 15:06 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-07-13  5:48 [PULL 0/3] Fuzzing Patches Alexander Bulekov
2021-07-13  5:48 ` [PULL 1/3] fuzz: fix sparse memory access in the DMA callback Alexander Bulekov
2021-07-13  5:48 ` [PULL 2/3] fuzz: adjust timeout to allow for longer inputs Alexander Bulekov
2021-07-13  5:48 ` [PULL 3/3] fuzz: make object-name matching case-insensitive Alexander Bulekov
2021-07-13 15:00 ` [PULL 0/3] Fuzzing Patches Alexander Bulekov

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.