Message ID | 1521193892-15552-4-git-send-email-thuth@redhat.com |
---|---|
State | New |
Headers | show |
Series | Fix crashes with CAN bus and ISA DMA devices | expand |
On 03/16/2018 10:51 AM, Thomas Huth wrote: > The cs4231a, gus and sb16 sound cards crash QEMU when the user tries > to instantiate them on a machine with DMA-less ISA bus (for example > with "qemu-system-mips64el -M mips -device sb16"). Add proper checks > to the realize functions to avoid the crashes. > > Signed-off-by: Thomas Huth <thuth@redhat.com> Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> > --- > hw/audio/cs4231a.c | 8 +++++++- > hw/audio/gus.c | 7 ++++++- > hw/audio/sb16.c | 9 +++++++-- > scripts/device-crash-test | 3 --- > 4 files changed, 20 insertions(+), 7 deletions(-) > > diff --git a/hw/audio/cs4231a.c b/hw/audio/cs4231a.c > index 096e8e9..aaebec1 100644 > --- a/hw/audio/cs4231a.c > +++ b/hw/audio/cs4231a.c > @@ -28,6 +28,7 @@ > #include "hw/isa/isa.h" > #include "hw/qdev.h" > #include "qemu/timer.h" > +#include "qapi/error.h" > > /* > Missing features: > @@ -663,8 +664,13 @@ static void cs4231a_realizefn (DeviceState *dev, Error **errp) > CSState *s = CS4231A (dev); > IsaDmaClass *k; > > - isa_init_irq (d, &s->pic, s->irq); > s->isa_dma = isa_get_dma(isa_bus_from_device(d), s->dma); > + if (!s->isa_dma) { > + error_setg(errp, "ISA controller does not support DMA"); > + return; > + } > + > + isa_init_irq(d, &s->pic, s->irq); > k = ISADMA_GET_CLASS(s->isa_dma); > k->register_channel(s->isa_dma, s->dma, cs_dma_read, s); > > diff --git a/hw/audio/gus.c b/hw/audio/gus.c > index 3e864cd..8e0b27e 100644 > --- a/hw/audio/gus.c > +++ b/hw/audio/gus.c > @@ -241,6 +241,12 @@ static void gus_realizefn (DeviceState *dev, Error **errp) > IsaDmaClass *k; > struct audsettings as; > > + s->isa_dma = isa_get_dma(isa_bus_from_device(d), s->emu.gusdma); > + if (!s->isa_dma) { > + error_setg(errp, "ISA controller does not support DMA"); > + return; > + } > + > AUD_register_card ("gus", &s->card); > > as.freq = s->freq; > @@ -272,7 +278,6 @@ static void gus_realizefn (DeviceState *dev, Error **errp) > isa_register_portio_list(d, &s->portio_list2, (s->port + 0x100) & 0xf00, > gus_portio_list2, s, "gus"); > > - s->isa_dma = isa_get_dma(isa_bus_from_device(d), s->emu.gusdma); > k = ISADMA_GET_CLASS(s->isa_dma); > k->register_channel(s->isa_dma, s->emu.gusdma, GUS_read_DMA, s); > s->emu.himemaddr = s->himem; > diff --git a/hw/audio/sb16.c b/hw/audio/sb16.c > index 31de264..5a4d323 100644 > --- a/hw/audio/sb16.c > +++ b/hw/audio/sb16.c > @@ -1371,6 +1371,13 @@ static void sb16_realizefn (DeviceState *dev, Error **errp) > SB16State *s = SB16 (dev); > IsaDmaClass *k; > > + s->isa_hdma = isa_get_dma(isa_bus_from_device(isadev), s->hdma); > + s->isa_dma = isa_get_dma(isa_bus_from_device(isadev), s->dma); > + if (!s->isa_dma || !s->isa_hdma) { > + error_setg(errp, "ISA controller does not support DMA"); > + return; > + } > + > isa_init_irq (isadev, &s->pic, s->irq); > > s->mixer_regs[0x80] = magic_of_irq (s->irq); > @@ -1389,11 +1396,9 @@ static void sb16_realizefn (DeviceState *dev, Error **errp) > isa_register_portio_list(isadev, &s->portio_list, s->port, > sb16_ioport_list, s, "sb16"); > > - s->isa_hdma = isa_get_dma(isa_bus_from_device(isadev), s->hdma); > k = ISADMA_GET_CLASS(s->isa_hdma); > k->register_channel(s->isa_hdma, s->hdma, SB_read_DMA, s); > > - s->isa_dma = isa_get_dma(isa_bus_from_device(isadev), s->dma); > k = ISADMA_GET_CLASS(s->isa_dma); > k->register_channel(s->isa_dma, s->dma, SB_read_DMA, s); > > diff --git a/scripts/device-crash-test b/scripts/device-crash-test > index 99d20cb..8ad3f44 100755 > --- a/scripts/device-crash-test > +++ b/scripts/device-crash-test > @@ -217,10 +217,7 @@ ERROR_WHITELIST = [ > {'exitcode':-6, 'log':r"Object .* is not an instance of type generic-pc-machine", 'loglevel':logging.ERROR}, > {'exitcode':-6, 'log':r"Object .* is not an instance of type e500-ccsr", 'loglevel':logging.ERROR}, > {'exitcode':-6, 'log':r"vmstate_register_with_alias_id: Assertion `!se->compat \|\| se->instance_id == 0' failed", 'loglevel':logging.ERROR}, > - {'exitcode':-11, 'device':'gus', 'loglevel':logging.ERROR, 'expected':True}, > {'exitcode':-11, 'device':'isa-serial', 'loglevel':logging.ERROR, 'expected':True}, > - {'exitcode':-11, 'device':'sb16', 'loglevel':logging.ERROR, 'expected':True}, > - {'exitcode':-11, 'device':'cs4231a', 'loglevel':logging.ERROR, 'expected':True}, > {'exitcode':-11, 'machine':'isapc', 'device':'.*-iommu', 'loglevel':logging.ERROR, 'expected':True}, > > # everything else (including SIGABRT and SIGSEGV) will be a fatal error: >
diff --git a/hw/audio/cs4231a.c b/hw/audio/cs4231a.c index 096e8e9..aaebec1 100644 --- a/hw/audio/cs4231a.c +++ b/hw/audio/cs4231a.c @@ -28,6 +28,7 @@ #include "hw/isa/isa.h" #include "hw/qdev.h" #include "qemu/timer.h" +#include "qapi/error.h" /* Missing features: @@ -663,8 +664,13 @@ static void cs4231a_realizefn (DeviceState *dev, Error **errp) CSState *s = CS4231A (dev); IsaDmaClass *k; - isa_init_irq (d, &s->pic, s->irq); s->isa_dma = isa_get_dma(isa_bus_from_device(d), s->dma); + if (!s->isa_dma) { + error_setg(errp, "ISA controller does not support DMA"); + return; + } + + isa_init_irq(d, &s->pic, s->irq); k = ISADMA_GET_CLASS(s->isa_dma); k->register_channel(s->isa_dma, s->dma, cs_dma_read, s); diff --git a/hw/audio/gus.c b/hw/audio/gus.c index 3e864cd..8e0b27e 100644 --- a/hw/audio/gus.c +++ b/hw/audio/gus.c @@ -241,6 +241,12 @@ static void gus_realizefn (DeviceState *dev, Error **errp) IsaDmaClass *k; struct audsettings as; + s->isa_dma = isa_get_dma(isa_bus_from_device(d), s->emu.gusdma); + if (!s->isa_dma) { + error_setg(errp, "ISA controller does not support DMA"); + return; + } + AUD_register_card ("gus", &s->card); as.freq = s->freq; @@ -272,7 +278,6 @@ static void gus_realizefn (DeviceState *dev, Error **errp) isa_register_portio_list(d, &s->portio_list2, (s->port + 0x100) & 0xf00, gus_portio_list2, s, "gus"); - s->isa_dma = isa_get_dma(isa_bus_from_device(d), s->emu.gusdma); k = ISADMA_GET_CLASS(s->isa_dma); k->register_channel(s->isa_dma, s->emu.gusdma, GUS_read_DMA, s); s->emu.himemaddr = s->himem; diff --git a/hw/audio/sb16.c b/hw/audio/sb16.c index 31de264..5a4d323 100644 --- a/hw/audio/sb16.c +++ b/hw/audio/sb16.c @@ -1371,6 +1371,13 @@ static void sb16_realizefn (DeviceState *dev, Error **errp) SB16State *s = SB16 (dev); IsaDmaClass *k; + s->isa_hdma = isa_get_dma(isa_bus_from_device(isadev), s->hdma); + s->isa_dma = isa_get_dma(isa_bus_from_device(isadev), s->dma); + if (!s->isa_dma || !s->isa_hdma) { + error_setg(errp, "ISA controller does not support DMA"); + return; + } + isa_init_irq (isadev, &s->pic, s->irq); s->mixer_regs[0x80] = magic_of_irq (s->irq); @@ -1389,11 +1396,9 @@ static void sb16_realizefn (DeviceState *dev, Error **errp) isa_register_portio_list(isadev, &s->portio_list, s->port, sb16_ioport_list, s, "sb16"); - s->isa_hdma = isa_get_dma(isa_bus_from_device(isadev), s->hdma); k = ISADMA_GET_CLASS(s->isa_hdma); k->register_channel(s->isa_hdma, s->hdma, SB_read_DMA, s); - s->isa_dma = isa_get_dma(isa_bus_from_device(isadev), s->dma); k = ISADMA_GET_CLASS(s->isa_dma); k->register_channel(s->isa_dma, s->dma, SB_read_DMA, s); diff --git a/scripts/device-crash-test b/scripts/device-crash-test index 99d20cb..8ad3f44 100755 --- a/scripts/device-crash-test +++ b/scripts/device-crash-test @@ -217,10 +217,7 @@ ERROR_WHITELIST = [ {'exitcode':-6, 'log':r"Object .* is not an instance of type generic-pc-machine", 'loglevel':logging.ERROR}, {'exitcode':-6, 'log':r"Object .* is not an instance of type e500-ccsr", 'loglevel':logging.ERROR}, {'exitcode':-6, 'log':r"vmstate_register_with_alias_id: Assertion `!se->compat \|\| se->instance_id == 0' failed", 'loglevel':logging.ERROR}, - {'exitcode':-11, 'device':'gus', 'loglevel':logging.ERROR, 'expected':True}, {'exitcode':-11, 'device':'isa-serial', 'loglevel':logging.ERROR, 'expected':True}, - {'exitcode':-11, 'device':'sb16', 'loglevel':logging.ERROR, 'expected':True}, - {'exitcode':-11, 'device':'cs4231a', 'loglevel':logging.ERROR, 'expected':True}, {'exitcode':-11, 'machine':'isapc', 'device':'.*-iommu', 'loglevel':logging.ERROR, 'expected':True}, # everything else (including SIGABRT and SIGSEGV) will be a fatal error:
The cs4231a, gus and sb16 sound cards crash QEMU when the user tries to instantiate them on a machine with DMA-less ISA bus (for example with "qemu-system-mips64el -M mips -device sb16"). Add proper checks to the realize functions to avoid the crashes. Signed-off-by: Thomas Huth <thuth@redhat.com> --- hw/audio/cs4231a.c | 8 +++++++- hw/audio/gus.c | 7 ++++++- hw/audio/sb16.c | 9 +++++++-- scripts/device-crash-test | 3 --- 4 files changed, 20 insertions(+), 7 deletions(-)