xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
From: George Dunlap <george.dunlap@citrix.com>
To: xen-devel@lists.xenproject.org
Cc: Ian Jackson <ian.jackson@citrix.com>,
	Wei Liu <wei.liu2@citrix.com>,
	George Dunlap <george.dunlap@citrix.com>,
	Jan Beulich <jbeulich@suse.com>,
	Andrew Cooper <andrew.cooper3@citrix.com>
Subject: [PATCH v2 10/13] fuzz/x86_emulate: Make input more compact
Date: Mon, 25 Sep 2017 15:26:45 +0100	[thread overview]
Message-ID: <20170925142648.25959-10-george.dunlap@citrix.com> (raw)
In-Reply-To: <20170925142648.25959-1-george.dunlap@citrix.com>

At the moment, AFL reckons that for any given input, 87% of it is
completely irrelevant: that is, it can change it as much as it wants
but have no impact on the result of the test; and yet it can't remove
it.

This is largely because we interpret the blob handed to us as a large
struct, including CR values, MSR values, segment registers, and a full
cpu_user_regs.

Instead, modify our interpretation to have a "set state" stanza at the
front.  Begin by reading a byte; if it is lower than a certain
threshold, set some state according to what byte it is, and repeat.
Continue until the byte is above a certain threshold.

This allows AFL to compact any given test case much smaller; to the
point where now it reckons there is not a single byte of the test file
which becomes irrelevant.  Testing have shown that this option both
allows AFL to reach coverage much faster, and to have a total coverage
higher than with the old format.

Make this an option (rather than a unilateral change) to enable
side-by-side performance comparison of the old and new formats.

Signed-off-by: George Dunlap <george.dunlap@citrix.com>
---
v2: Port over previous changes

CC: Ian Jackson <ian.jackson@citrix.com>
CC: Wei Liu <wei.liu2@citrix.com>
CC: Andrew Cooper <andrew.cooper3@citrix.com>
CC: Jan Beulich <jbeulich@suse.com>
---
 tools/fuzz/x86_instruction_emulator/afl-harness.c | 13 +++-
 tools/fuzz/x86_instruction_emulator/fuzz-emul.c   | 94 ++++++++++++++++++++---
 2 files changed, 97 insertions(+), 10 deletions(-)

diff --git a/tools/fuzz/x86_instruction_emulator/afl-harness.c b/tools/fuzz/x86_instruction_emulator/afl-harness.c
index 669f698711..806f54d606 100644
--- a/tools/fuzz/x86_instruction_emulator/afl-harness.c
+++ b/tools/fuzz/x86_instruction_emulator/afl-harness.c
@@ -4,6 +4,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <getopt.h>
+#include <stdbool.h>
 
 extern int LLVMFuzzerInitialize(int *argc, char ***argv);
 extern int LLVMFuzzerTestOneInput(const uint8_t *data_p, size_t size);
@@ -12,6 +13,8 @@ extern unsigned int fuzz_minimal_input_size(void);
 #define INPUT_SIZE  4096
 static uint8_t input[INPUT_SIZE];
 
+extern bool opt_compact;
+
 int main(int argc, char **argv)
 {
     size_t size;
@@ -22,13 +25,17 @@ int main(int argc, char **argv)
     setbuf(stdin, NULL);
     setbuf(stdout, NULL);
 
+    opt_compact = true;
+
     while ( 1 )
     {
         enum {
             OPT_MIN_SIZE,
+            OPT_COMPACT,
         };
         static const struct option lopts[] = {
             { "min-input-size", no_argument, NULL, OPT_MIN_SIZE },
+            { "compact", required_argument, NULL, OPT_COMPACT },
             { 0, 0, 0, 0 }
         };
         int c = getopt_long_only(argc, argv, "", lopts, NULL);
@@ -43,8 +50,12 @@ int main(int argc, char **argv)
             exit(0);
             break;
 
+        case OPT_COMPACT:
+            opt_compact = atoi(optarg);
+            break;
+            
         case '?':
-            printf("Usage: %s $FILE [$FILE...] | [--min-input-size]\n", argv[0]);
+            printf("Usage: %s [--compact=0|1] $FILE [$FILE...] | [--min-input-size]\n", argv[0]);
             exit(-1);
             break;
 
diff --git a/tools/fuzz/x86_instruction_emulator/fuzz-emul.c b/tools/fuzz/x86_instruction_emulator/fuzz-emul.c
index c8a5507f8b..d99a50d12c 100644
--- a/tools/fuzz/x86_instruction_emulator/fuzz-emul.c
+++ b/tools/fuzz/x86_instruction_emulator/fuzz-emul.c
@@ -53,6 +53,15 @@ struct fuzz_state
 };
 #define DATA_OFFSET offsetof(struct fuzz_state, corpus)
 
+bool opt_compact;
+
+unsigned int fuzz_minimal_input_size(void)
+{
+    if ( opt_compact )
+        return sizeof(unsigned long) + 1;
+    else
+        return DATA_OFFSET + 1;
+}
 
 static inline bool input_available(struct fuzz_state *s, size_t size)
 {
@@ -647,9 +656,81 @@ static void setup_state(struct x86_emulate_ctxt *ctxt)
 {
     struct fuzz_state *s = ctxt->data;
 
-    /* Fuzz all of the state in one go */
-    if (!input_read(s, s, DATA_OFFSET))
-        exit(-1);
+    if ( !opt_compact )
+    {
+        /* Fuzz all of the state in one go */
+        if (!input_read(s, s, DATA_OFFSET))
+            exit(-1);
+        return;
+    }
+
+    /* Modify only select bits of state */
+
+    /* Always read 'options' */
+    if ( !input_read(s, &s->options, sizeof(s->options)) )
+        return;
+    
+    while(1) {
+        uint16_t offset;
+
+        /* Read 16 bits to decide what bit of state to modify */
+        if ( !input_read(s, &offset, sizeof(offset)) )
+            return;
+
+        /* 
+         * Then decide if it's "pointing to" different bits of the
+         * state 
+         */
+
+        /* cr[]? */
+        if ( offset < 5 )
+        {
+            if ( !input_read(s, s->cr + offset, sizeof(*s->cr)) )
+                return;
+            printf("Setting CR %d to %lx\n", offset, s->cr[offset]);
+            continue;
+        }
+        
+        offset -= 5;
+
+        /* msr[]? */
+        if ( offset < MSR_INDEX_MAX )
+        {
+            if ( !input_read(s, s->msr + offset, sizeof(*s->msr)) )
+                return;
+            printf("Setting MSR i%d (%x) to %lx\n", offset,
+                   msr_index[offset], s->msr[offset]);
+            continue;
+        }
+
+        offset -= MSR_INDEX_MAX;
+
+        /* segments[]? */
+        if ( offset < SEG_NUM )
+        {
+            if ( !input_read(s, s->segments + offset, sizeof(*s->segments)) )
+                return;
+            printf("Setting Segment %d\n", offset);
+            continue;
+            
+        }
+
+        offset -= SEG_NUM;
+
+        /* regs? */
+        if ( offset < sizeof(struct cpu_user_regs)
+             && offset + sizeof(uint64_t) <= sizeof(struct cpu_user_regs) )
+        {
+            if ( !input_read(s, ((char *)ctxt->regs) + offset, sizeof(uint64_t)) )
+                return;
+            printf("Setting cpu_user_regs offset %x\n", offset);
+            continue;
+        }
+
+        /* None of the above -- take that as "start emulating" */
+        
+        return;
+    }
 }
 
 #define CANONICALIZE(x)                                   \
@@ -821,7 +902,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data_p, size_t size)
     /* Reset all global state variables */
     memset(&input, 0, sizeof(input));
 
-    if ( size <= DATA_OFFSET )
+    if ( size < fuzz_minimal_input_size() )
     {
         printf("Input too small\n");
         return 1;
@@ -858,11 +939,6 @@ int LLVMFuzzerTestOneInput(const uint8_t *data_p, size_t size)
     return 0;
 }
 
-unsigned int fuzz_minimal_input_size(void)
-{
-    return DATA_OFFSET + 1;
-}
-
 /*
  * Local variables:
  * mode: C
-- 
2.14.1


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

  parent reply	other threads:[~2017-09-25 14:27 UTC|newest]

Thread overview: 56+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-09-25 14:26 [PATCH v2 01/13] x86emul/fuzz: add rudimentary limit checking George Dunlap
2017-09-25 14:26 ` [PATCH v2 02/13] fuzz/x86_emulate: Actually use cpu_regs input George Dunlap
2017-10-04  8:21   ` Jan Beulich
2017-09-25 14:26 ` [PATCH v2 03/13] fuzz/x86_emulate: Clear errors after each iteration George Dunlap
2017-10-04  8:22   ` Jan Beulich
2017-09-25 14:26 ` [PATCH v2 04/13] fuzz/x86_emulate: Improve failure descriptions in x86_emulate harness George Dunlap
2017-10-04  8:22   ` Jan Beulich
2017-09-25 14:26 ` [PATCH v2 05/13] fuzz/x86_emulate: Implement input_read() and input_avail() George Dunlap
2017-10-04  8:22   ` Jan Beulich
2017-10-04 16:23     ` George Dunlap
2017-09-25 14:26 ` [PATCH v2 06/13] fuzz/x86_emulate: Rename the file containing the wrapper code George Dunlap
2017-10-04  8:23   ` Jan Beulich
2017-10-04 16:34     ` George Dunlap
2017-10-05  9:01       ` Jan Beulich
2017-10-05 13:50         ` George Dunlap
2017-09-25 14:26 ` [PATCH v2 07/13] fuzz/x86_emulate: Add 'afl-cov' target George Dunlap
2017-10-04  8:23   ` Jan Beulich
2017-10-04 16:48     ` George Dunlap
2017-10-05  9:06       ` Jan Beulich
2017-09-25 14:26 ` [PATCH v2 08/13] fuzz/x86_emulate: Take multiple test files for inputs George Dunlap
2017-10-04  8:24   ` Jan Beulich
2017-10-04 16:58     ` George Dunlap
2017-10-05  9:08       ` Jan Beulich
2017-09-25 14:26 ` [PATCH v2 09/13] fuzz/x86_emulate: Move all state into fuzz_state George Dunlap
2017-10-04  8:25   ` Jan Beulich
2017-10-04 16:51     ` George Dunlap
2017-09-25 14:26 ` George Dunlap [this message]
2017-10-04  8:26   ` [PATCH v2 10/13] fuzz/x86_emulate: Make input more compact Jan Beulich
2017-10-05 15:04     ` George Dunlap
2017-10-05 15:37       ` Jan Beulich
2017-09-25 14:26 ` [PATCH v2 11/13] fuzz/x86_emulate: Add --rerun option to try to track down instability George Dunlap
2017-10-04  8:27   ` Jan Beulich
2017-10-05 16:12     ` George Dunlap
2017-10-06  5:53       ` Jan Beulich
2017-09-25 14:26 ` [PATCH v2 12/13] fuzz/x86_emulate: Set and fuzz more CPU state George Dunlap
2017-10-04  8:28   ` Jan Beulich
2017-10-05 17:08     ` George Dunlap
2017-10-06  6:10       ` Jan Beulich
2017-10-06 10:53         ` George Dunlap
2017-10-06  9:57       ` Jan Beulich
2017-10-06 10:50         ` George Dunlap
2017-10-06 11:53           ` Jan Beulich
2017-10-06 11:56   ` Jan Beulich
2017-10-10 15:45     ` George Dunlap
2017-09-25 14:26 ` [PATCH v2 13/13] fuzz/x86_emulate: Add an option to limit the number of instructions executed George Dunlap
2017-10-04  8:28   ` Jan Beulich
2017-10-06 10:40     ` George Dunlap
2017-10-06 12:12       ` Jan Beulich
2017-10-06 13:02         ` George Dunlap
2017-10-06 15:21 ` [PATCH v2 01/13] x86emul/fuzz: add rudimentary limit checking George Dunlap
2017-10-06 15:54   ` Jan Beulich
2017-10-06 17:06     ` George Dunlap
2017-10-09  7:17       ` Jan Beulich
2017-10-09 12:54 ` Andrew Cooper
2017-10-09 13:26   ` Jan Beulich
2017-10-09 13:35     ` Andrew Cooper

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20170925142648.25959-10-george.dunlap@citrix.com \
    --to=george.dunlap@citrix.com \
    --cc=andrew.cooper3@citrix.com \
    --cc=ian.jackson@citrix.com \
    --cc=jbeulich@suse.com \
    --cc=wei.liu2@citrix.com \
    --cc=xen-devel@lists.xenproject.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).