On 200528 1533, Philippe Mathieu-Daudé wrote:
> On 5/26/20 5:52 PM, Philippe Mathieu-Daudé wrote:
> > On 5/26/20 5:41 PM, Alexander Bulekov wrote:
> >> On 200526 1725, Philippe Mathieu-Daudé wrote:
> >>> On 5/26/20 4:56 PM, Alexander Bulekov wrote:
> >>>> On 200526 1105, Philippe Mathieu-Daudé wrote:
> >>>>> On 5/26/20 10:56 AM, Stefan Hajnoczi wrote:
> >>>>>> On Tue, May 26, 2020 at 07:58:18AM +0200, Philippe Mathieu-Daudé wrote:
> >>>>>>> Hi Alexander,
> >>>>>>>
> >>>>>>> I forgot to share these 2 patches wrote before
> >>>>>>> the direct MemoryRegion fuzzer sent yesterday.
> >>>>>>>
> >>>>>>> Regards,
> >>>>>>>
> >>>>>>> Phil.
> >>>>>>>
> >>>>>>> Philippe Mathieu-Daudé (2):
> >>>>>>>   tests/qtest/fuzz: Avoid QTest ioport serialization
> >>>>>>>   tests/qtest/fuzz: Avoid QTest mmio serialization
> >>>>>>>
> >>>>>>>  tests/qtest/fuzz/i440fx_fuzz.c      | 19 +++++++++++++------
> >>>>>>>  tests/qtest/fuzz/virtio_net_fuzz.c  |  6 ++++--
> >>>>>>>  tests/qtest/fuzz/virtio_scsi_fuzz.c |  6 +++++-
> >>>>>>>  3 files changed, 22 insertions(+), 9 deletions(-)
> >>>>>>
> >>>>>> Will it still be possible to print qtest reproducer commands when a
> >>>>>> crash is found?
> >>>>>
> >>>>> Yes, there is no change in the corpus format.
> >>>>
> >>>> Yes, though with these patches, the qtest-based code will be gone.
> >>>> Should there be some option to switch between the two modes?
> >>>
> >>> How so?
> >>>
> >>> How do you generate your reproducers?
> >>
> >> Right now basically with this:
> >>
> >> --- a/qtest.c
> >> +++ b/qtest.c
> >> @@ -808,6 +808,8 @@ bool qtest_driver(void)
> >>
> >>  void qtest_server_inproc_recv(void *dummy, const char *buf)
> >>  {
> >> +    // It would be nice to add support for qtest's built in qtest_log_fp.
> >> +    printf(">>> %s\n", buf);
> > 
> > Uh =) I suppose you restart a single job with the offending corpus file?
> > 
> >>      static GString *gstr;
> >>      if (!gstr) {
> >>          gstr = g_string_new(NULL);
> >> --
> >>
> >> It would be nice to add support for qtest's built in qtest_log_fp.
> >> Unless I'm missing something, these address_space_writes completely
> >> bypass qtest, so there has to be some additional step to build
> >> reproducers(eg running against the QTest-based version, or adding some
> >> way to spit out corresponding qtest commands for the
> >> address_space_writes).
> > 
> > I am using this hacky script, not committed yet because not ready but
> > still you can get the idea:
> > 
> > -- >8 --
> > import sys
> > import struct
> > 
> > # Tune to MemoryRegion properties
> > IOBASE = 0xa0002000
> > IOSIZE =     0x1000
> > 
> > action = { #           ASM        ADDR         VAL
> >     0x00: {'opcode': 'writeb', 'size': 8,  'fmt': 'B'},
> >     0x01: {'opcode': 'writew', 'size': 8,  'fmt': 'H'},
> >     0x02: {'opcode': 'writel', 'size': 8,  'fmt': 'I'},
> >     0x03: {'opcode': 'writeq', 'size': 8,  'fmt': 'L'},
> > 
> >     0x04: {'opcode': 'writeb', 'size': 16,  'fmt': 'B'},
> >     0x05: {'opcode': 'writew', 'size': 16,  'fmt': 'H'},
> >     0x06: {'opcode': 'writel', 'size': 16,  'fmt': 'I'},
> >     0x07: {'opcode': 'writeq', 'size': 16,  'fmt': 'L'},
> > 
> >     0x08: {'opcode': 'writeb', 'size': 32,  'fmt': 'B'},
> >     0x09: {'opcode': 'writew', 'size': 32,  'fmt': 'H'},
> >     0x0a: {'opcode': 'writel', 'size': 32,  'fmt': 'I'},
> >     0x0b: {'opcode': 'writeq', 'size': 32,  'fmt': 'L'},
> > 
> >     0x10: {'opcode': 'readb',  'size': 8,  'fmt': 'B'},
> >     0x11: {'opcode': 'readw',  'size': 8,  'fmt': 'H'},
> >     0x12: {'opcode': 'readl',  'size': 8,  'fmt': 'I'},
> >     0x13: {'opcode': 'readq',  'size': 8,  'fmt': 'L'},
> > 
> >     0x14: {'opcode': 'readb',  'size': 16,  'fmt': 'B'},
> >     0x15: {'opcode': 'readw',  'size': 16,  'fmt': 'H'},
> >     0x16: {'opcode': 'readl',  'size': 16,  'fmt': 'I'},
> >     0x17: {'opcode': 'readq',  'size': 16,  'fmt': 'L'},
> > 
> >     0x18: {'opcode': 'readb',  'size': 32,  'fmt': 'B'},
> >     0x19: {'opcode': 'readw',  'size': 32,  'fmt': 'H'},
> >     0x1a: {'opcode': 'readl',  'size': 32,  'fmt': 'I'},
> >     0x1b: {'opcode': 'readq',  'size': 32,  'fmt': 'L'},
> > }
> > AMASK = 0x1f
> > ADDR = {8: 'B', 16: 'H', 32: 'I', 64: 'L'}
> > 
> > def fuzz_parse_corpus_data(fn):
> >     fd = open(fn, 'rb')
> >     while True:
> >         buf = fd.read(1)
> >         if len(buf) < 1:
> >             break
> >         op, = struct.unpack("B", buf)
> >         op &= AMASK
> >         if op not in action:
> >             break
> >         a = action[op]
> >         fmt = "<" + ADDR[a['size']] + a['fmt']
> >         fmtsz = struct.calcsize(fmt)
> >         buf = fd.read(fmtsz)
> >         if len(buf) < fmtsz:
> >             break
> >         if a['fmt'] == 'x':
> >             addr, = struct.unpack(fmt, buf)
> >             val = 0
> >         else:
> >             addr, val = struct.unpack(fmt, buf)
> >         addr &= IOSIZE - 1
> >         print("%s 0x%02x 0x%x" % (a['opcode'], IOBASE + addr, val))
> > 
> > fuzz_parse_corpus_data(sys.argv[1])
> > ---
> > 
> > $ python tests/qtest/fuzz/corpus2qtest.py \
> >   ./crash-12e481ba7c2a7a625152dc701821d5e184cddee8
> > writel 0xa0002000 0x20010000
> > writeb 0xa0002020 0x20
> > readl 0xa0002100 0x204204ff
> > writeb 0xa0002042 0x36
> > readl 0xa0002436 0xf4760024
> > writel 0xa0002020 0x4363636
> > writeb 0xa0002600 0xf4
> > writew 0xa0002001 0x2020
> > writeb 0xa0002020 0x4
> > writel 0xa0002020 0x4363636
> > writeb 0xa0002600 0xf4
> > writel 0xa0002020 0x36363a01
> > readl 0xa0002404 0x1f47600
> > writew 0xa0002020 0x2020
> > writeb 0xa0002004 0x42
> > writeb 0xa0002036 0x36
> > readl 0xa0002404 0x42f47600
> > writeb 0xa0002036 0x36
> > readl 0xa0002404 0x1f47600
> > writew 0xa0002020 0x420
> 
> FYI talking with Stefan he kinda suggested it is cleaner to use a
> '-replay corpus_data.bin' mode that enables the printf output from
> qtest_*read/write (without reaching the device) rather than maintaining
> a Python script.

I think handling the QTEST_LOG=1 environment variable in
qtest_inproc_init would be a decent solution. Alternatively we could
have a -replay flag which just adds "-qtest-log /dev/fd/2" to the
qemu_main args. Writing scripts gets complicated for e.g. the
virtio-net-* fuzzers, where the input is converted into some high-level
libqos calls.
-Alex

> > 
> >>
> >>>>
> >>>>>>
> >>>>>> Other than this concern, higher fuzzing rates would be great.
> >>>>>
> >>>>> Thanks,
> >>>>>
> >>>>> Phil.
> >>>>
> >>
> > 

Reply via email to