On Tue, 16 May 2023 at 06:20, Thomas Huth <th...@redhat.com> wrote: > > We cannot use the generic reentrancy guard in the LSI code, so > we have to manually prevent endless reentrancy here. The problematic > lsi_execute_script() function has already a way to detect whether > too many instructions have been executed - we just have to slightly > change the logic here that it also takes into account if the function > has been called too often in a reentrant way. > > The code in fuzz-lsi53c895a-test.c has been taken from an earlier > patch by Mauro Matteo Cascella. > > Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1563 > Signed-off-by: Thomas Huth <th...@redhat.com> > --- > hw/scsi/lsi53c895a.c | 7 ++++++- > tests/qtest/fuzz-lsi53c895a-test.c | 33 ++++++++++++++++++++++++++++++ > 2 files changed, 39 insertions(+), 1 deletion(-) > > diff --git a/hw/scsi/lsi53c895a.c b/hw/scsi/lsi53c895a.c > index 048436352b..8b34199ab8 100644 > --- a/hw/scsi/lsi53c895a.c > +++ b/hw/scsi/lsi53c895a.c > @@ -1134,10 +1134,13 @@ static void lsi_execute_script(LSIState *s) > uint32_t addr, addr_high; > int opcode; > int insn_processed = 0; > + static int reentrancy_level; > + > + reentrancy_level++; > > s->istat1 |= LSI_ISTAT1_SRUN; > again: > - if (++insn_processed > LSI_MAX_INSN) { > + if (++insn_processed > LSI_MAX_INSN || reentrancy_level > 8) {
Why 8 and not some other number? > /* Some windows drivers make the device spin waiting for a memory > location to change. If we have been executed a lot of code then > assume this is the case and force an unexpected device disconnect. > @@ -1596,6 +1599,8 @@ again: > } > } > trace_lsi_execute_script_stop(); > + > + reentrancy_level--; > } > > static uint8_t lsi_reg_readb(LSIState *s, int offset) > diff --git a/tests/qtest/fuzz-lsi53c895a-test.c > b/tests/qtest/fuzz-lsi53c895a-test.c > index 2012bd54b7..1b55928b9f 100644 > --- a/tests/qtest/fuzz-lsi53c895a-test.c > +++ b/tests/qtest/fuzz-lsi53c895a-test.c > @@ -8,6 +8,36 @@ > #include "qemu/osdep.h" > #include "libqtest.h" > > +/* > + * This used to trigger a DMA reentrancy issue > + * leading to memory corruption bugs like stack > + * overflow or use-after-free > + * https://gitlab.com/qemu-project/qemu/-/issues/1563 > + */ > +static void test_lsi_dma_reentrancy(void) > +{ > + QTestState *s; > + > + s = qtest_init("-M q35 -m 512M -nodefaults " > + "-blockdev driver=null-co,node-name=null0 " > + "-device lsi53c810 -device scsi-cd,drive=null0"); > + > + qtest_outl(s, 0xcf8, 0x80000804); /* PCI Command Register */ > + qtest_outw(s, 0xcfc, 0x7); /* Enables accesses */ > + qtest_outl(s, 0xcf8, 0x80000814); /* Memory Bar 1 */ > + qtest_outl(s, 0xcfc, 0xff100000); /* Set MMIO Address*/ > + qtest_outl(s, 0xcf8, 0x80000818); /* Memory Bar 2 */ > + qtest_outl(s, 0xcfc, 0xff000000); /* Set RAM Address*/ > + qtest_writel(s, 0xff000000, 0xc0000024); > + qtest_writel(s, 0xff000114, 0x00000080); > + qtest_writel(s, 0xff00012c, 0xff000000); > + qtest_writel(s, 0xff000004, 0xff000114); > + qtest_writel(s, 0xff000008, 0xff100014); > + qtest_writel(s, 0xff10002f, 0x000000ff); > + > + qtest_quit(s); > +} > + > /* > * This used to trigger a UAF in lsi_do_msgout() > * https://gitlab.com/qemu-project/qemu/-/issues/972 > @@ -124,5 +154,8 @@ int main(int argc, char **argv) > qtest_add_func("fuzz/lsi53c895a/lsi_do_msgout_cancel_req", > test_lsi_do_msgout_cancel_req); > > + qtest_add_func("fuzz/lsi53c895a/lsi_dma_reentrancy", > + test_lsi_dma_reentrancy); > + > return g_test_run(); > } > -- > 2.31.1 > >