hw/isa/lpc_ich9: Ignore reserved/invalid SCI IRQ
libFuzzer triggered the following assertion:
cat << EOF | qemu-system-i386 -M pc-q35-5.0 \
-nographic -monitor none -serial none \
-qtest stdio -d guest_errors -trace pci\*
outl 0xcf8 0x8400f841
outl 0xcfc 0xebed205d
outl 0x5d02 0xedf82049
EOF
pci_cfg_write ICH9-LPC 31:0 @0x41 <- 0xebed205d
hw/pci/pci.c:268: int pci_bus_get_irq_level(PCIBus *, int): Assertion `irq_num < bus->nirq' failed.
This is because ich9_lpc_sci_irq() returns -1 for reserved
(illegal) values, but ich9_lpc_pmbase_sci_update() considers
it valid and store it in a 8-bit unsigned type. Then the 255
value is used as GSI IRQ, resulting in a PIRQ value of 247,
more than ICH9_LPC_NB_PIRQS (8).
Fix by simply ignoring the invalid access (and reporting it):
pci_cfg_write ICH9-LPC 31:0 @0x41 <- 0xebed205d
ICH9 LPC: SCI IRQ SEL #3 is reserved
pci_cfg_read mch 00:0 @0x0 -> 0x8086
pci_cfg_read mch 00:0 @0x0 -> 0x29c08086
...
Cc: qemu-stable@nongnu.org
Reported-by: Alexander Bulekov <alxndr@bu.edu>
Fixes: 8f242cb724
("ich9: implement SCI_IRQ_SEL register")
BugLink: https://bugs.launchpad.net/qemu/+bug/1878642
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Message-Id: <20200717151705.18611-1-f4bug@amsat.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
f8b8f37463
commit
4177b062fc
@ -29,6 +29,7 @@
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/log.h"
|
||||
#include "cpu.h"
|
||||
#include "qapi/visitor.h"
|
||||
#include "qemu/range.h"
|
||||
@ -312,10 +313,12 @@ void ich9_generate_smi(void)
|
||||
cpu_interrupt(first_cpu, CPU_INTERRUPT_SMI);
|
||||
}
|
||||
|
||||
/* Returns -1 on error, IRQ number on success */
|
||||
static int ich9_lpc_sci_irq(ICH9LPCState *lpc)
|
||||
{
|
||||
switch (lpc->d.config[ICH9_LPC_ACPI_CTRL] &
|
||||
ICH9_LPC_ACPI_CTRL_SCI_IRQ_SEL_MASK) {
|
||||
uint8_t sel = lpc->d.config[ICH9_LPC_ACPI_CTRL] &
|
||||
ICH9_LPC_ACPI_CTRL_SCI_IRQ_SEL_MASK;
|
||||
switch (sel) {
|
||||
case ICH9_LPC_ACPI_CTRL_9:
|
||||
return 9;
|
||||
case ICH9_LPC_ACPI_CTRL_10:
|
||||
@ -328,6 +331,8 @@ static int ich9_lpc_sci_irq(ICH9LPCState *lpc)
|
||||
return 21;
|
||||
default:
|
||||
/* reserved */
|
||||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
"ICH9 LPC: SCI IRQ SEL #%u is reserved\n", sel);
|
||||
break;
|
||||
}
|
||||
return -1;
|
||||
@ -459,7 +464,7 @@ ich9_lpc_pmbase_sci_update(ICH9LPCState *lpc)
|
||||
{
|
||||
uint32_t pm_io_base = pci_get_long(lpc->d.config + ICH9_LPC_PMBASE);
|
||||
uint8_t acpi_cntl = pci_get_long(lpc->d.config + ICH9_LPC_ACPI_CTRL);
|
||||
uint8_t new_gsi;
|
||||
int new_gsi;
|
||||
|
||||
if (acpi_cntl & ICH9_LPC_ACPI_CTRL_ACPI_EN) {
|
||||
pm_io_base &= ICH9_LPC_PMBASE_BASE_ADDRESS_MASK;
|
||||
@ -470,6 +475,9 @@ ich9_lpc_pmbase_sci_update(ICH9LPCState *lpc)
|
||||
ich9_pm_iospace_update(&lpc->pm, pm_io_base);
|
||||
|
||||
new_gsi = ich9_lpc_sci_irq(lpc);
|
||||
if (new_gsi == -1) {
|
||||
return;
|
||||
}
|
||||
if (lpc->sci_level && new_gsi != lpc->sci_gsi) {
|
||||
qemu_set_irq(lpc->pm.irq, 0);
|
||||
lpc->sci_gsi = new_gsi;
|
||||
|
@ -144,6 +144,7 @@ struct ICH9LPCState {
|
||||
#define ICH9_LPC_PMBASE_BASE_ADDRESS_MASK Q35_MASK(32, 15, 7)
|
||||
#define ICH9_LPC_PMBASE_RTE 0x1
|
||||
#define ICH9_LPC_PMBASE_DEFAULT 0x1
|
||||
|
||||
#define ICH9_LPC_ACPI_CTRL 0x44
|
||||
#define ICH9_LPC_ACPI_CTRL_ACPI_EN 0x80
|
||||
#define ICH9_LPC_ACPI_CTRL_SCI_IRQ_SEL_MASK Q35_MASK(8, 2, 0)
|
||||
|
Loading…
Reference in New Issue
Block a user