From be5a8cf347d0c47ee3e933dde075526fd8bd5c40 Mon Sep 17 00:00:00 2001 From: Philippe Mathieu-Daudé Date: Sat, 18 Dec 2021 17:09:10 +0100 Subject: hw/audio/intel-hda: Do not ignore DMA overrun errors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per the "High Definition Audio Specification" manual (rev. 1.0a), section "3.3.30 Offset 5Dh: RIRBSTS - RIRB Status": Response Overrun Interrupt Status (RIRBOIS): Hardware sets this bit to a 1 when an overrun occurs in the RIRB. An interrupt may be generated if the Response Overrun Interrupt Control bit is set. This bit will be set if the RIRB DMA engine is not able to write the incoming responses to memory before additional incoming responses overrun the internal FIFO. When hardware detects an overrun, it will drop the responses which overrun the buffer and set the RIRBOIS status bit to indicate the error condition. Optionally, if the RIRBOIC is set, the hardware will also generate an error to alert software to the problem. QEMU emulates the DMA engine with the stl_le_pci_dma() calls. This function returns a MemTxResult indicating whether the DMA access was successful. Handle any MemTxResult error as "DMA engine is not able to write the incoming responses to memory" and raise the Overrun Interrupt flag when this case occurs. Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20211218160912.1591633-2-philmd@redhat.com> Signed-off-by: Thomas Huth --- hw/audio/intel-hda.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'hw/audio/intel-hda.c') diff --git a/hw/audio/intel-hda.c b/hw/audio/intel-hda.c index 5f8a878f20..47a36acc71 100644 --- a/hw/audio/intel-hda.c +++ b/hw/audio/intel-hda.c @@ -350,6 +350,7 @@ static void intel_hda_response(HDACodecDevice *dev, bool solicited, uint32_t res IntelHDAState *d = container_of(bus, IntelHDAState, codecs); hwaddr addr; uint32_t wp, ex; + MemTxResult res = MEMTX_OK; if (d->ics & ICH6_IRS_BUSY) { dprint(d, 2, "%s: [irr] response 0x%x, cad 0x%x\n", @@ -368,8 +369,12 @@ static void intel_hda_response(HDACodecDevice *dev, bool solicited, uint32_t res ex = (solicited ? 0 : (1 << 4)) | dev->cad; wp = (d->rirb_wp + 1) & 0xff; addr = intel_hda_addr(d->rirb_lbase, d->rirb_ubase); - stl_le_pci_dma(&d->pci, addr + 8 * wp, response, attrs); - stl_le_pci_dma(&d->pci, addr + 8 * wp + 4, ex, attrs); + res |= stl_le_pci_dma(&d->pci, addr + 8 * wp, response, attrs); + res |= stl_le_pci_dma(&d->pci, addr + 8 * wp + 4, ex, attrs); + if (res != MEMTX_OK && (d->rirb_ctl & ICH6_RBCTL_OVERRUN_EN)) { + d->rirb_sts |= ICH6_RBSTS_OVERRUN; + intel_hda_update_irq(d); + } d->rirb_wp = wp; dprint(d, 2, "%s: [wp 0x%x] response 0x%x, extra 0x%x\n", -- cgit 1.4.1 From 79fa99831debc9782087e834382c577215f2f511 Mon Sep 17 00:00:00 2001 From: Philippe Mathieu-Daudé Date: Sat, 18 Dec 2021 17:09:11 +0100 Subject: hw/audio/intel-hda: Restrict DMA engine to memories (not MMIO devices) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Issue #542 reports a reentrancy problem when the DMA engine accesses the HDA controller I/O registers. Fix by restricting the DMA engine to memories regions (forbidding MMIO devices such the HDA controller). Reported-by: OSS-Fuzz (Issue 28435) Reported-by: Alexander Bulekov Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Thomas Huth Resolves: https://gitlab.com/qemu-project/qemu/-/issues/542 CVE: CVE-2021-3611 Message-Id: <20211218160912.1591633-3-philmd@redhat.com> Signed-off-by: Thomas Huth --- hw/audio/intel-hda.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'hw/audio/intel-hda.c') diff --git a/hw/audio/intel-hda.c b/hw/audio/intel-hda.c index 47a36acc71..78a47bc08c 100644 --- a/hw/audio/intel-hda.c +++ b/hw/audio/intel-hda.c @@ -345,7 +345,7 @@ static void intel_hda_corb_run(IntelHDAState *d) static void intel_hda_response(HDACodecDevice *dev, bool solicited, uint32_t response) { - const MemTxAttrs attrs = MEMTXATTRS_UNSPECIFIED; + const MemTxAttrs attrs = { .memory = true }; HDACodecBus *bus = HDA_BUS(dev->qdev.parent_bus); IntelHDAState *d = container_of(bus, IntelHDAState, codecs); hwaddr addr; -- cgit 1.4.1