diff mbox series

[v3,09/16] fuzz: add a crossover function to generic-fuzzer

Message ID 20200921022506.873303-10-alxndr@bu.edu
State New
Headers show
Series Add a General Virtual Device Fuzzer | expand

Commit Message

Alexander Bulekov Sept. 21, 2020, 2:24 a.m. UTC
Signed-off-by: Alexander Bulekov <alxndr@bu.edu>
---
 tests/qtest/fuzz/general_fuzz.c | 90 ++++++++++++++++++++++++++++++++-
 1 file changed, 89 insertions(+), 1 deletion(-)

Comments

Darren Kenny Oct. 1, 2020, 3:31 p.m. UTC | #1
As mentioned in an earlier patch, maybe the definition of SEPARATOR
should be here as well as some of the comments you provided in the
replies to it.

Otherwise, this looks good,

Reviewed-by: Darren Kenny <darren.kenny@oracle.com>


Thanks,

Darren.

On Sunday, 2020-09-20 at 22:24:59 -04, Alexander Bulekov wrote:
> Signed-off-by: Alexander Bulekov <alxndr@bu.edu>

> ---

>  tests/qtest/fuzz/general_fuzz.c | 90 ++++++++++++++++++++++++++++++++-

>  1 file changed, 89 insertions(+), 1 deletion(-)

>

> diff --git a/tests/qtest/fuzz/general_fuzz.c b/tests/qtest/fuzz/general_fuzz.c

> index 656ec7fd55..3833b505c8 100644

> --- a/tests/qtest/fuzz/general_fuzz.c

> +++ b/tests/qtest/fuzz/general_fuzz.c

> @@ -741,6 +741,92 @@ static void general_pre_fuzz(QTestState *s)

>  

>      counter_shm_init();

>  }

> +

> +/*

> + * When libfuzzer gives us two inputs to combine, return a new input with the

> + * following structure:

> + *

> + * Input 1 (data1)

> + * SEPARATOR

> + * Clear out the DMA Patterns

> + * SEPARATOR

> + * Disable the pci_read/write instructions

> + * SEPARATOR

> + * Input 2 (data2)

> + *

> + * The idea is to collate the core behaviors of the two inputs.

> + * For example:

> + * Input 1: maps a device's BARs, sets up three DMA patterns, and triggers

> + *          device functionality A

> + * Input 2: maps a device's BARs, sets up one DMA pattern, and triggers device

> + *          functionality B

> + *

> + * This function attempts to produce an input that:

> + * Ouptut: maps a device's BARs, set up three DMA patterns, triggers

> + *          functionality A device, replaces the DMA patterns with a single

> + *          patten, and triggers device functionality B.

> + */

> +static size_t general_fuzz_crossover(const uint8_t *data1, size_t size1, const

> +                                     uint8_t *data2, size_t size2, uint8_t *out,

> +                                     size_t max_out_size, unsigned int seed)

> +{

> +    size_t copy_len = 0, size = 0;

> +

> +    /* Check that we have enough space for data1 and at least part of data2 */

> +    if (max_out_size <= size + strlen(SEPARATOR) * 3 + 2) {

> +        return 0;

> +    }

> +

> +    /* Copy_Len in the first input */

> +    copy_len = size1;

> +    memcpy(out + size, data1, copy_len);

> +    size += copy_len;

> +    max_out_size -= copy_len;

> +

> +    /* Append a separator */

> +    copy_len = strlen(SEPARATOR);

> +    memcpy(out + size, SEPARATOR, copy_len);

> +    size += copy_len;

> +    max_out_size -= copy_len;

> +

> +    /* Clear out the DMA Patterns */

> +    copy_len = 1;

> +    if (copy_len) {

> +        out[size] = OP_CLEAR_DMA_PATTERNS;

> +    }

> +    size += copy_len;

> +    max_out_size -= copy_len;

> +

> +    /* Append a separator */

> +    copy_len = strlen(SEPARATOR);

> +    memcpy(out + size, SEPARATOR, copy_len);

> +    size += copy_len;

> +    max_out_size -= copy_len;

> +

> +    /* Disable PCI ops. Assume data1 took care of setting up PCI */

> +    copy_len = 1;

> +    if (copy_len) {

> +        out[size] = OP_DISABLE_PCI;

> +    }

> +    size += copy_len;

> +    max_out_size -= copy_len;

> +

> +    /* Append a separator */

> +    copy_len = strlen(SEPARATOR);

> +    memcpy(out + size, SEPARATOR, copy_len);

> +    size += copy_len;

> +    max_out_size -= copy_len;

> +

> +    /* Copy_Len over the second input */

> +    copy_len = MIN(size2, max_out_size);

> +    memcpy(out + size, data2, copy_len);

> +    size += copy_len;

> +    max_out_size -= copy_len;

> +

> +    return  size;

> +}

> +

> +

>  static GString *general_fuzz_cmdline(FuzzTarget *t)

>  {

>      GString *cmd_line = g_string_new(TARGET_NAME);

> @@ -760,7 +846,9 @@ static void register_general_fuzz_targets(void)

>              .description = "Fuzz based on any qemu command-line args. ",

>              .get_init_cmdline = general_fuzz_cmdline,

>              .pre_fuzz = general_pre_fuzz,

> -            .fuzz = general_fuzz});

> +            .fuzz = general_fuzz,

> +            .crossover = general_fuzz_crossover

> +    });

>  }

>  

>  fuzz_target_init(register_general_fuzz_targets);

> -- 

> 2.28.0
diff mbox series

Patch

diff --git a/tests/qtest/fuzz/general_fuzz.c b/tests/qtest/fuzz/general_fuzz.c
index 656ec7fd55..3833b505c8 100644
--- a/tests/qtest/fuzz/general_fuzz.c
+++ b/tests/qtest/fuzz/general_fuzz.c
@@ -741,6 +741,92 @@  static void general_pre_fuzz(QTestState *s)
 
     counter_shm_init();
 }
+
+/*
+ * When libfuzzer gives us two inputs to combine, return a new input with the
+ * following structure:
+ *
+ * Input 1 (data1)
+ * SEPARATOR
+ * Clear out the DMA Patterns
+ * SEPARATOR
+ * Disable the pci_read/write instructions
+ * SEPARATOR
+ * Input 2 (data2)
+ *
+ * The idea is to collate the core behaviors of the two inputs.
+ * For example:
+ * Input 1: maps a device's BARs, sets up three DMA patterns, and triggers
+ *          device functionality A
+ * Input 2: maps a device's BARs, sets up one DMA pattern, and triggers device
+ *          functionality B
+ *
+ * This function attempts to produce an input that:
+ * Ouptut: maps a device's BARs, set up three DMA patterns, triggers
+ *          functionality A device, replaces the DMA patterns with a single
+ *          patten, and triggers device functionality B.
+ */
+static size_t general_fuzz_crossover(const uint8_t *data1, size_t size1, const
+                                     uint8_t *data2, size_t size2, uint8_t *out,
+                                     size_t max_out_size, unsigned int seed)
+{
+    size_t copy_len = 0, size = 0;
+
+    /* Check that we have enough space for data1 and at least part of data2 */
+    if (max_out_size <= size + strlen(SEPARATOR) * 3 + 2) {
+        return 0;
+    }
+
+    /* Copy_Len in the first input */
+    copy_len = size1;
+    memcpy(out + size, data1, copy_len);
+    size += copy_len;
+    max_out_size -= copy_len;
+
+    /* Append a separator */
+    copy_len = strlen(SEPARATOR);
+    memcpy(out + size, SEPARATOR, copy_len);
+    size += copy_len;
+    max_out_size -= copy_len;
+
+    /* Clear out the DMA Patterns */
+    copy_len = 1;
+    if (copy_len) {
+        out[size] = OP_CLEAR_DMA_PATTERNS;
+    }
+    size += copy_len;
+    max_out_size -= copy_len;
+
+    /* Append a separator */
+    copy_len = strlen(SEPARATOR);
+    memcpy(out + size, SEPARATOR, copy_len);
+    size += copy_len;
+    max_out_size -= copy_len;
+
+    /* Disable PCI ops. Assume data1 took care of setting up PCI */
+    copy_len = 1;
+    if (copy_len) {
+        out[size] = OP_DISABLE_PCI;
+    }
+    size += copy_len;
+    max_out_size -= copy_len;
+
+    /* Append a separator */
+    copy_len = strlen(SEPARATOR);
+    memcpy(out + size, SEPARATOR, copy_len);
+    size += copy_len;
+    max_out_size -= copy_len;
+
+    /* Copy_Len over the second input */
+    copy_len = MIN(size2, max_out_size);
+    memcpy(out + size, data2, copy_len);
+    size += copy_len;
+    max_out_size -= copy_len;
+
+    return  size;
+}
+
+
 static GString *general_fuzz_cmdline(FuzzTarget *t)
 {
     GString *cmd_line = g_string_new(TARGET_NAME);
@@ -760,7 +846,9 @@  static void register_general_fuzz_targets(void)
             .description = "Fuzz based on any qemu command-line args. ",
             .get_init_cmdline = general_fuzz_cmdline,
             .pre_fuzz = general_pre_fuzz,
-            .fuzz = general_fuzz});
+            .fuzz = general_fuzz,
+            .crossover = general_fuzz_crossover
+    });
 }
 
 fuzz_target_init(register_general_fuzz_targets);