All of lore.kernel.org
 help / color / mirror / Atom feed
From: Wei Liu <wei.liu2@citrix.com>
To: Jan Beulich <JBeulich@suse.com>
Cc: Stefano Stabellini <sstabellini@kernel.org>,
	Wei Liu <wei.liu2@citrix.com>,
	George Dunlap <George.Dunlap@eu.citrix.com>,
	Andrew Cooper <andrew.cooper3@citrix.com>,
	Ian Jackson <ian.jackson@eu.citrix.com>,
	George Dunlap <george.dunlap@citrix.com>,
	Tim Deegan <tim@xen.org>,
	Xen-devel <xen-devel@lists.xenproject.org>
Subject: Re: [PATCH v3 5/7] tools/fuzz: introduce x86 instruction emulator target
Date: Mon, 12 Dec 2016 11:19:53 +0000	[thread overview]
Message-ID: <20161212111953.GA22644@citrix.com> (raw)
In-Reply-To: <584E82DF0200007800127DC0@prv-mh.provo.novell.com>

On Mon, Dec 12, 2016 at 02:58:39AM -0700, Jan Beulich wrote:
> >>> On 12.12.16 at 10:28, <wei.liu2@citrix.com> wrote:
> > Instruction emulator fuzzing code is from code previous written by
> > Andrew and George. Adapted to llvm fuzzer and hook up the build system.
> > 
> > Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
> > Signed-off-by: George Dunlap <george.dunlap@citrix.com>
> > Signed-off-by: Wei Liu <wei.liu2@citrix.com>
> > ---
> > Cc: Andrew Cooper <andrew.cooper3@citrix.com>
> > Cc: George Dunlap <George.Dunlap@eu.citrix.com>
> > Cc: Ian Jackson <ian.jackson@eu.citrix.com>
> > Cc: Jan Beulich <jbeulich@suse.com>
> > Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
> > Cc: Stefano Stabellini <sstabellini@kernel.org>
> > Cc: Tim Deegan <tim@xen.org>
> > Cc: Wei Liu <wei.liu2@citrix.com>
> > 
> > v3:
> > 1. coding style fix
> > 2. share more code
> > 3. exit when stack can't be made executable
> > ---
> >  .gitignore                                         |   1 +
> >  tools/fuzz/x86_instruction_emulator/Makefile       |  31 ++++
> >  .../x86-insn-emulator-fuzzer.c                     | 195 +++++++++++++++++++++
> >  3 files changed, 227 insertions(+)
> >  create mode 100644 tools/fuzz/x86_instruction_emulator/Makefile
> >  create mode 100644 
> > tools/fuzz/x86_instruction_emulator/x86-insn-emulator-fuzzer.c
> > 
> > diff --git a/.gitignore b/.gitignore
> > index a2f34a1..d507243 100644
> > --- a/.gitignore
> > +++ b/.gitignore
> > @@ -145,6 +145,7 @@ tools/flask/utils/flask-loadpolicy
> >  tools/flask/utils/flask-setenforce
> >  tools/flask/utils/flask-set-bool
> >  tools/flask/utils/flask-label-pci
> > +tools/fuzz/x86_instruction_emulator/x86_emulate*
> >  tools/helpers/_paths.h
> >  tools/helpers/init-xenstore-domain
> >  tools/helpers/xen-init-dom0
> > diff --git a/tools/fuzz/x86_instruction_emulator/Makefile 
> > b/tools/fuzz/x86_instruction_emulator/Makefile
> > new file mode 100644
> > index 0000000..2b147ac
> > --- /dev/null
> > +++ b/tools/fuzz/x86_instruction_emulator/Makefile
> > @@ -0,0 +1,31 @@
> > +XEN_ROOT=$(CURDIR)/../../..
> > +include $(XEN_ROOT)/tools/Rules.mk
> > +
> > +x86-instruction-emulator-fuzzer-all: x86-insn-emulator.a x86-insn-emulator-fuzzer.o
> > +
> > +x86_emulate/x86_emulate.c x86_emulate/x86_emulate.h:
> > +	[ -L x86_emulate ] || ln -sf $(XEN_ROOT)/xen/arch/x86/x86_emulate .
> > +
> > +x86_emulate.c x86_emulate.h: %:
> > +	[ -L $* ] || ln -sf $(XEN_ROOT)/tools/tests/x86_emulator/$*
> > +
> > +CFLAGS += $(CFLAGS_xeninclude)
> > +
> > +x86_emulate.o: x86_emulate.c x86_emulate.h x86_emulate/x86_emulate.c x86_emulate/x86_emulate.h
> 
> Perhaps worthwhile shortening this to
> 
> x86_emulate.o: x86_emulate.[ch] x86_emulate/x86_emulate.[ch]
> 
> ?

Done.

> 
> > --- /dev/null
> > +++ b/tools/fuzz/x86_instruction_emulator/x86-insn-emulator-fuzzer.c
> > @@ -0,0 +1,195 @@
> > +#include <assert.h>
> > +#include <errno.h>
> > +#include <fcntl.h>
> > +#include <inttypes.h>
> > +#include <limits.h>
> > +#include <stdbool.h>
> > +#include <stdint.h>
> > +#include <stdio.h>
> > +#include <stdlib.h>
> > +#include <string.h>
> > +#include <sys/types.h>
> > +#include <sys/stat.h>
> > +#include <sys/mman.h>
> > +#include <unistd.h>
> > +#include <xen/xen.h>
> > +
> > +#include "x86_emulate.h"
> > +
> > +static unsigned char data[4096];
> > +static unsigned int data_index = 0;
> 
> Pointless initializer.
> 

Done.

> > +static unsigned int data_max;
> > +
> > +static int data_read(const char *why, void *dst, unsigned int bytes)
> > +{
> > +    unsigned i;
> 
> Please don't omit the "int" here (and in a few more places below)
> when basically everywhere else it is present.
> 

Done.

> > +    if ( data_index + bytes > data_max )
> > +        return X86EMUL_EXCEPTION;
> > +
> > +    memcpy(dst,  data+data_index, bytes);
> 
> Blanks around binary operators please (more further down).
> 

Done.

> > +    data_index += bytes;
> > +
> > +    printf("%s: ", why);
> > +    for ( i = 0; i < bytes; i++ )
> > +        printf(" %02x", (unsigned int)*(unsigned char *)(dst+i));
> 
> Is the left most cast really needed here?
> 

No. I've deleted that.

> > +int LLVMFuzzerTestOneInput(const uint8_t *data_p, size_t size)
> > +{
> > +    bool stack_exec;
> > +    struct cpu_user_regs regs = {};
> > +    struct x86_emulate_ctxt ctxt =
> > +        {
> > +            .regs = &regs,
> > +            .addr_size = 8 * sizeof(void *),
> > +            .sp_size = 8 * sizeof(void *),
> > +        };
> > +
> 
> Stray blank line. The indentation of the initializer above also looks
> a little unusual.
> 

Fixed.

> > +    unsigned nr = 0;
> > +    int rc;
> > +    unsigned x;
> > +    const uint8_t *p = data_p;
> > +
> > +    stack_exec = emul_test_make_stack_executable();
> > +    if ( !stack_exec )
> > +    {
> > +        printf("Warning: Stack could not be made executable (%d).\n", errno);
> > +        exit(1);
> > +    }
> > +
> > +    /* Reset all global states */
> 
> DYM "state"?
> 

I mean "states". There are three states we need to reset.

> > +    memset(data, 0, sizeof(data));
> > +    data_index = 0;
> > +    data_max = 0;
> > +
> > +    nr = size < sizeof(regs) ? size : sizeof(regs);
> > +
> > +    memcpy(&regs, p, nr);
> > +    p += sizeof(regs);
> > +    nr += sizeof(regs);
> 
> I think this second += wants to be dropped, considering how nr
> gets set above and used below.
> 
> > +    if ( nr <= size )
> 
> < would seem more natural here.

Yes, you're right in both places.

> 
> > +    {
> > +        memcpy(data, p, size - nr);
> > +        data_max = size - nr;
> > +    }
> > +
> > +    ctxt.force_writeback = 0;
> 
> false

Done.

> 
> > +    /* Zero 'private' entries */
> 
> s/entries/fields/ ?
> 

Done.

> > +    regs.error_code = 0;
> > +    regs.entry_vector = 0;
> > +
> > +    /* Use the upper bits of regs.eip to determine addr_size */
> > +    x = (regs.rip >> ADDR_SIZE_SHIFT) & 0x3;
> 
> This won't build as 32-bit code. If that's intentional, then I think
> this would better be enforced in the Makefile (rather than
> surfacing a compile error here).
> 

Good catch. I think this test case is still preliminary. TBH I haven't
paid much attention to the working of this test target, other than
pulling everything together to work.

I think long term we do need to determine what to do with 32 bit build,
but I would wait until George to come back because he wrote this
snippet.

For now I will disable 32bit build in Makefile.

> > +    if (x == 3)

I also fix this instance to add spaces in ().


---8<---
From 83b7381080aafc3f2fb35ba589715694f847f73a Mon Sep 17 00:00:00 2001
From: Wei Liu <wei.liu2@citrix.com>
Date: Thu, 8 Dec 2016 12:09:54 +0000
Subject: [PATCH] tools/fuzz: introduce x86 instruction emulator target

Instruction emulator fuzzing code is from code previous written by
Andrew and George. Adapt it to llvm fuzzer and hook up the build system.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Signed-off-by: George Dunlap <george.dunlap@citrix.com>
Signed-off-by: Wei Liu <wei.liu2@citrix.com>
---
Cc: Andrew Cooper <andrew.cooper3@citrix.com>
Cc: George Dunlap <George.Dunlap@eu.citrix.com>
Cc: Ian Jackson <ian.jackson@eu.citrix.com>
Cc: Jan Beulich <jbeulich@suse.com>
Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Cc: Stefano Stabellini <sstabellini@kernel.org>
Cc: Tim Deegan <tim@xen.org>
Cc: Wei Liu <wei.liu2@citrix.com>

v4:
1. more coding style fixes and bug fixes
2. only do 64 bit build

v3:
1. coding style fix
2. share more code
3. exit when stack can't be made executable
---
 .gitignore                                         |   1 +
 tools/fuzz/x86_instruction_emulator/Makefile       |  36 ++++
 .../x86-insn-emulator-fuzzer.c                     | 190 +++++++++++++++++++++
 3 files changed, 227 insertions(+)
 create mode 100644 tools/fuzz/x86_instruction_emulator/Makefile
 create mode 100644 tools/fuzz/x86_instruction_emulator/x86-insn-emulator-fuzzer.c

diff --git a/.gitignore b/.gitignore
index a2f34a1..d507243 100644
--- a/.gitignore
+++ b/.gitignore
@@ -145,6 +145,7 @@ tools/flask/utils/flask-loadpolicy
 tools/flask/utils/flask-setenforce
 tools/flask/utils/flask-set-bool
 tools/flask/utils/flask-label-pci
+tools/fuzz/x86_instruction_emulator/x86_emulate*
 tools/helpers/_paths.h
 tools/helpers/init-xenstore-domain
 tools/helpers/xen-init-dom0
diff --git a/tools/fuzz/x86_instruction_emulator/Makefile b/tools/fuzz/x86_instruction_emulator/Makefile
new file mode 100644
index 0000000..6e68df7
--- /dev/null
+++ b/tools/fuzz/x86_instruction_emulator/Makefile
@@ -0,0 +1,36 @@
+XEN_ROOT=$(CURDIR)/../../..
+include $(XEN_ROOT)/tools/Rules.mk
+
+.PHONY: x86-instruction-emulator-fuzzer-all
+ifeq ($(CONFIG_X86_64),y)
+x86-instruction-emulator-fuzzer-all: x86-insn-emulator.a x86-insn-emulator-fuzzer.o
+else
+x86-instruction-emulator-fuzzer-all:
+endif
+
+x86_emulate/x86_emulate.c x86_emulate/x86_emulate.h:
+	[ -L x86_emulate ] || ln -sf $(XEN_ROOT)/xen/arch/x86/x86_emulate .
+
+x86_emulate.c x86_emulate.h: %:
+	[ -L $* ] || ln -sf $(XEN_ROOT)/tools/tests/x86_emulator/$*
+
+CFLAGS += $(CFLAGS_xeninclude)
+
+x86_emulate.o: x86_emulate.[ch] x86_emulate/x86_emulate.[ch]
+
+x86-insn-emulator.a: x86_emulate.o
+	$(AR) rc $@ $^
+
+x86-insn-emulator-fuzzer.o: x86-insn-emulator-fuzzer.c
+
+# Common targets
+.PHONY: all
+all: x86-instruction-emulator-fuzzer-all
+
+.PHONY: distclean
+distclean: clean
+	rm -f x86_emulate x86_emulate.c x86_emulate.h
+
+.PHONY: clean
+clean:
+	rm -f *.a *.o
diff --git a/tools/fuzz/x86_instruction_emulator/x86-insn-emulator-fuzzer.c b/tools/fuzz/x86_instruction_emulator/x86-insn-emulator-fuzzer.c
new file mode 100644
index 0000000..94ec311
--- /dev/null
+++ b/tools/fuzz/x86_instruction_emulator/x86-insn-emulator-fuzzer.c
@@ -0,0 +1,190 @@
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#include <xen/xen.h>
+
+#include "x86_emulate.h"
+
+static unsigned char data[4096];
+static unsigned int data_index;
+static unsigned int data_max;
+
+static int data_read(const char *why, void *dst, unsigned int bytes)
+{
+    unsigned int i;
+
+    if ( data_index + bytes > data_max )
+        return X86EMUL_EXCEPTION;
+
+    memcpy(dst,  data + data_index, bytes);
+    data_index += bytes;
+
+    printf("%s: ", why);
+    for ( i = 0; i < bytes; i++ )
+        printf(" %02x", *(unsigned char *)(dst + i));
+    printf("\n");
+
+    return X86EMUL_OKAY;
+}
+
+static int fuzz_read(
+    unsigned int seg,
+    unsigned long offset,
+    void *p_data,
+    unsigned int bytes,
+    struct x86_emulate_ctxt *ctxt)
+{
+    return data_read("read", p_data, bytes);
+}
+
+static int fuzz_fetch(
+    unsigned int seg,
+    unsigned long offset,
+    void *p_data,
+    unsigned int bytes,
+    struct x86_emulate_ctxt *ctxt)
+{
+    return data_read("fetch", p_data, bytes);
+}
+
+static int fuzz_write(
+    unsigned int seg,
+    unsigned long offset,
+    void *p_data,
+    unsigned int bytes,
+    struct x86_emulate_ctxt *ctxt)
+{
+    return X86EMUL_OKAY;
+}
+
+static int fuzz_cmpxchg(
+    unsigned int seg,
+    unsigned long offset,
+    void *old,
+    void *new,
+    unsigned int bytes,
+    struct x86_emulate_ctxt *ctxt)
+{
+    return X86EMUL_OKAY;
+}
+
+static struct x86_emulate_ops fuzz_emulops = {
+    .read       = fuzz_read,
+    .insn_fetch = fuzz_fetch,
+    .write      = fuzz_write,
+    .cmpxchg    = fuzz_cmpxchg,
+    .cpuid      = emul_test_cpuid,
+    .read_cr    = emul_test_read_cr,
+    .get_fpu    = emul_test_get_fpu,
+};
+
+#define CANONICALIZE(x)                                   \
+    do {                                                  \
+        uint64_t _y = (x);                                \
+        if ( _y & (1ULL << 47) )                          \
+            _y |= (~0ULL) << 48;                          \
+        else                                              \
+            _y &= (1ULL << 48)-1;                         \
+        printf("Canonicalized %" PRIx64 " to %" PRIx64 "\n", x, _y);    \
+        (x) = _y;                                       \
+    } while( 0 )
+
+#define ADDR_SIZE_SHIFT 60
+#define ADDR_SIZE_64 (2ULL << ADDR_SIZE_SHIFT)
+#define ADDR_SIZE_32 (1ULL << ADDR_SIZE_SHIFT)
+#define ADDR_SIZE_16 (0)
+
+int LLVMFuzzerTestOneInput(const uint8_t *data_p, size_t size)
+{
+    bool stack_exec;
+    struct cpu_user_regs regs = {};
+    struct x86_emulate_ctxt ctxt = {
+        .regs = &regs,
+        .addr_size = 8 * sizeof(void *),
+        .sp_size = 8 * sizeof(void *),
+    };
+    unsigned int nr = 0;
+    int rc;
+    unsigned int x;
+    const uint8_t *p = data_p;
+
+    stack_exec = emul_test_make_stack_executable();
+    if ( !stack_exec )
+    {
+        printf("Warning: Stack could not be made executable (%d).\n", errno);
+        return 1;
+    }
+
+    /* Reset all global states */
+    memset(data, 0, sizeof(data));
+    data_index = 0;
+    data_max = 0;
+
+    nr = size < sizeof(regs) ? size : sizeof(regs);
+
+    memcpy(&regs, p, nr);
+    p += sizeof(regs);
+
+    if ( nr < size )
+    {
+        memcpy(data, p, size - nr);
+        data_max = size - nr;
+    }
+
+    ctxt.force_writeback = false;
+
+    /* Zero 'private' fields */
+    regs.error_code = 0;
+    regs.entry_vector = 0;
+
+    /* Use the upper bits of regs.eip to determine addr_size */
+    x = (regs.rip >> ADDR_SIZE_SHIFT) & 0x3;
+    if ( x == 3 )
+        x = 2;
+    ctxt.addr_size = 16 << x;
+    printf("addr_size: %d\n", ctxt.addr_size);
+
+    /* Use the upper bit of regs.rsp to determine sp_size (if appropriate) */
+    if ( ctxt.addr_size == 64 )
+        ctxt.sp_size = 64;
+    else
+    {
+        /* If addr_size isn't 64-bits, sp_size can only be 16 or 32 bits */
+        x = (regs.rsp >> ADDR_SIZE_SHIFT) & 0x1;
+        ctxt.sp_size = 16 << x;
+    }
+    printf("sp_size: %d\n", ctxt.sp_size);
+    CANONICALIZE(regs.rip);
+    CANONICALIZE(regs.rsp);
+    CANONICALIZE(regs.rbp);
+
+    /* Zero all segments for now */
+    regs.cs = regs.ss = regs.es = regs.ds = regs.fs = regs.gs = 0;
+
+    do {
+        rc = x86_emulate(&ctxt, &fuzz_emulops);
+        printf("Emulation result: %d\n", rc);
+    } while ( rc == X86EMUL_OKAY );
+
+    return 0;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
-- 
2.1.4


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

  reply	other threads:[~2016-12-12 11:19 UTC|newest]

Thread overview: 21+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-12-12  9:28 [PATCH v3 0/7] Fuzzing targets for oss-fuzz Wei Liu
2016-12-12  9:28 ` [PATCH v3 1/7] tools/fuzz: introduce libelf target Wei Liu
2016-12-12  9:43   ` Jan Beulich
2016-12-12  9:28 ` [PATCH v3 2/7] x86emul/test: factor out emul_test_make_stack_executable Wei Liu
2016-12-12  9:28 ` [PATCH v3 3/7] x86emul/test: factor out emul_test_{read_cr, cpuid} Wei Liu
2016-12-12  9:45   ` Jan Beulich
2016-12-12  9:51     ` Wei Liu
2016-12-12  9:28 ` [PATCH v3 4/7] x86emul/test: factor out emul_test_get_fpu Wei Liu
2016-12-12  9:46   ` Jan Beulich
2016-12-12  9:28 ` [PATCH v3 5/7] tools/fuzz: introduce x86 instruction emulator target Wei Liu
2016-12-12  9:58   ` Jan Beulich
2016-12-12 11:19     ` Wei Liu [this message]
2016-12-12 11:30       ` Jan Beulich
2016-12-12 11:40         ` Wei Liu
2016-12-12 17:59           ` Ian Jackson
2016-12-12 18:00             ` Wei Liu
2016-12-12 17:51     ` Wei Liu
2016-12-13  7:42       ` Jan Beulich
2016-12-16  9:03   ` George Dunlap
2016-12-12  9:28 ` [PATCH v3 6/7] tools: hook up fuzz directory Wei Liu
2016-12-12  9:28 ` [PATCH v3 7/7] tools/fuzz: add README Wei Liu

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=20161212111953.GA22644@citrix.com \
    --to=wei.liu2@citrix.com \
    --cc=George.Dunlap@eu.citrix.com \
    --cc=JBeulich@suse.com \
    --cc=andrew.cooper3@citrix.com \
    --cc=george.dunlap@citrix.com \
    --cc=ian.jackson@eu.citrix.com \
    --cc=sstabellini@kernel.org \
    --cc=tim@xen.org \
    --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 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.