[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH v5 10/16] scripts/oss-fuzz: Add script to reorder a general-fuzze
From: |
Alexander Bulekov |
Subject: |
[PATCH v5 10/16] scripts/oss-fuzz: Add script to reorder a general-fuzzer trace |
Date: |
Tue, 20 Oct 2020 21:07:46 -0400 |
The general-fuzzer uses hooks to fulfill DMA requests just-in-time.
This means that if we try to use QTEST_LOG=1 to build a reproducer, the
DMA writes will be logged _after_ the in/out/read/write that triggered
the DMA read. To work work around this, the general-fuzzer annotates
these just-in time DMA fulfilments with a tag that we can use to
discern them. This script simply iterates over a raw qtest
trace (including log messages, errors, timestamps etc), filters it and
re-orders it so that DMA fulfillments are placed directly _before_ the
qtest command that will cause the DMA access.
Signed-off-by: Alexander Bulekov <alxndr@bu.edu>
Reviewed-by: Darren Kenny <darren.kenny@oracle.com>
---
.../oss-fuzz/reorder_fuzzer_qtest_trace.py | 103 ++++++++++++++++++
1 file changed, 103 insertions(+)
create mode 100755 scripts/oss-fuzz/reorder_fuzzer_qtest_trace.py
diff --git a/scripts/oss-fuzz/reorder_fuzzer_qtest_trace.py
b/scripts/oss-fuzz/reorder_fuzzer_qtest_trace.py
new file mode 100755
index 0000000000..47295c9e69
--- /dev/null
+++ b/scripts/oss-fuzz/reorder_fuzzer_qtest_trace.py
@@ -0,0 +1,103 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+"""
+Use this to convert qtest log info from a generic fuzzer input into a qtest
+trace that you can feed into a standard qemu-system process. Example usage:
+
+QEMU_FUZZ_ARGS="-machine q35,accel=qtest" QEMU_FUZZ_OBJECTS="*" \
+ ./i386-softmmu/qemu-fuzz-i386 --fuzz-target=general-pci-fuzz
+# .. Finds some crash
+QTEST_LOG=1 FUZZ_SERIALIZE_QTEST=1 \
+QEMU_FUZZ_ARGS="-machine q35,accel=qtest" QEMU_FUZZ_OBJECTS="*" \
+ ./i386-softmmu/qemu-fuzz-i386 --fuzz-target=general-pci-fuzz
+ /path/to/crash 2> qtest_log_output
+scripts/oss-fuzz/reorder_fuzzer_qtest_trace.py qtest_log_output > qtest_trace
+./i386-softmmu/qemu-fuzz-i386 -machine q35,accel=qtest \
+ -qtest stdin < qtest_trace
+
+### Details ###
+
+Some fuzzer make use of hooks that allow us to populate some memory range, just
+before a DMA read from that range. This means that the fuzzer can produce
+activity that looks like:
+ [start] read from mmio addr
+ [end] read from mmio addr
+ [start] write to pio addr
+ [start] fill a DMA buffer just in time
+ [end] fill a DMA buffer just in time
+ [start] fill a DMA buffer just in time
+ [end] fill a DMA buffer just in time
+ [end] write to pio addr
+ [start] read from mmio addr
+ [end] read from mmio addr
+
+We annotate these "nested" DMA writes, so with QTEST_LOG=1 the QTest trace
+might look something like:
+[R +0.028431] readw 0x10000
+[R +0.028434] outl 0xc000 0xbeef # Triggers a DMA read from 0xbeef and 0xbf00
+[DMA][R +0.034639] write 0xbeef 0x2 0xAAAA
+[DMA][R +0.034639] write 0xbf00 0x2 0xBBBB
+[R +0.028431] readw 0xfc000
+
+This script would reorder the above trace so it becomes:
+readw 0x10000
+write 0xbeef 0x2 0xAAAA
+write 0xbf00 0x2 0xBBBB
+outl 0xc000 0xbeef
+readw 0xfc000
+
+I.e. by the time, 0xc000 tries to read from DMA, those DMA buffers have already
+been set up, removing the need for the DMA hooks. We can simply provide this
+reordered trace via -qtest stdio to reproduce the input
+
+Note: this won't work for traces where the device tries to read from the same
+DMA region twice in between MMIO/PIO commands. E.g:
+ [R +0.028434] outl 0xc000 0xbeef
+ [DMA][R +0.034639] write 0xbeef 0x2 0xAAAA
+ [DMA][R +0.034639] write 0xbeef 0x2 0xBBBB
+
+The fuzzer will annotate suspected double-fetches with [DOUBLE-FETCH]. This
+script looks for these tags and warns the users that the resulting trace might
+not reproduce the bug.
+"""
+
+import sys
+
+__author__ = "Alexander Bulekov <alxndr@bu.edu>"
+__copyright__ = "Copyright (C) 2020, Red Hat, Inc."
+__license__ = "GPL version 2 or (at your option) any later version"
+
+__maintainer__ = "Alexander Bulekov"
+__email__ = "alxndr@bu.edu"
+
+
+def usage():
+ sys.exit("Usage: {} /path/to/qtest_log_output".format((sys.argv[0])))
+
+
+def main(filename):
+ with open(filename, "r") as f:
+ trace = f.readlines()
+
+ # Leave only lines that look like logged qtest commands
+ trace[:] = [x.strip() for x in trace if "[R +" in x
+ or "[S +" in x and "CLOSED" not in x]
+
+ for i in range(len(trace)):
+ if i+1 < len(trace):
+ if "[DMA]" in trace[i+1]:
+ if "[DOUBLE-FETCH]" in trace[i+1]:
+ sys.stderr.write("Warning: Likely double fetch on line"
+ "{}.\n There will likely be problems "
+ "reproducing behavior with the "
+ "resulting qtest trace\n\n".format(i+1))
+ trace[i], trace[i+1] = trace[i+1], trace[i]
+ for line in trace:
+ print(line.split("]")[-1].strip())
+
+
+if __name__ == '__main__':
+ if len(sys.argv) == 1:
+ usage()
+ main(sys.argv[1])
--
2.28.0
- [PATCH v5 01/16] memory: Add FlatView foreach function, (continued)
- [PATCH v5 01/16] memory: Add FlatView foreach function, Alexander Bulekov, 2020/10/20
- [PATCH v5 02/16] fuzz: Add general virtual-device fuzzer, Alexander Bulekov, 2020/10/20
- [PATCH v5 03/16] fuzz: Add PCI features to the general fuzzer, Alexander Bulekov, 2020/10/20
- [PATCH v5 04/16] fuzz: Add DMA support to the generic-fuzzer, Alexander Bulekov, 2020/10/20
- [PATCH v5 05/16] fuzz: Declare DMA Read callback function, Alexander Bulekov, 2020/10/20
- [PATCH v5 06/16] fuzz: Add fuzzer callbacks to DMA-read functions, Alexander Bulekov, 2020/10/20
- [PATCH v5 07/16] fuzz: Add support for custom crossover functions, Alexander Bulekov, 2020/10/20
- [PATCH v5 08/16] fuzz: add a DISABLE_PCI op to general-fuzzer, Alexander Bulekov, 2020/10/20
- [PATCH v5 09/16] fuzz: add a crossover function to generic-fuzzer, Alexander Bulekov, 2020/10/20
- [PATCH v5 10/16] scripts/oss-fuzz: Add script to reorder a general-fuzzer trace,
Alexander Bulekov <=
- [PATCH v5 11/16] scripts/oss-fuzz: Add crash trace minimization script, Alexander Bulekov, 2020/10/20
- [PATCH v5 12/16] fuzz: Add instructions for using general-fuzz, Alexander Bulekov, 2020/10/20
- [PATCH v5 13/16] fuzz: add an "opaque" to the FuzzTarget struct, Alexander Bulekov, 2020/10/20
- [PATCH v5 14/16] fuzz: add general-fuzz configs for oss-fuzz, Alexander Bulekov, 2020/10/20
- [PATCH v5 15/16] fuzz: register predefined general-fuzz configs, Alexander Bulekov, 2020/10/20
- [PATCH v5 16/16] scripts/oss-fuzz: remove the general-fuzz target, Alexander Bulekov, 2020/10/20
- Re: [PATCH v5 00/16] Add a Generic Virtual Device Fuzzer, Thomas Huth, 2020/10/21