CVE-2011-3131
Xen DoS using IOMMU faults from PCI-passthrough guest
A VM that controls a PCI[E] device directly can cause it to issue DMA requests to invalid addresses. Although these requests are denied by the IOMMU, the hypervisor needs to handle the interrupt and clear the error from the IOMMU, and this can be used to live-lock a CPU and potentially hang the host.
improper error handling (live lock)
http://xenbits.xen.org/hg/xen-4.1-testing.hg/rev/84e3706df07a
Passthrough: disable bus-mastering on any card that causes an IOMMU fault.
This stops the card from raising back-to-back faults and live-locking the CPU that handles them.
--- a/xen/drivers/passthrough/amd/iommu_init.c Mon Jul 25 16:48:39 2011 +0100
+++ b/xen/drivers/passthrough/amd/iommu_init.c Fri Aug 12 11:33:41 2011 +0100
@@ -462,7 +462,7 @@ static hw_irq_controller iommu_msi_type
static void parse_event_log_entry(u32 entry[])
{
- u16 domain_id, device_id;
+ u16 domain_id, device_id, bdf, cword;
u32 code;
u64 *addr;
char * event_str[] = {"ILLEGAL_DEV_TABLE_ENTRY",
@@ -497,6 +497,18 @@ static void parse_event_log_entry(u32 en
"%s: domain = %d, device id = 0x%04x, "
"fault address = 0x%"PRIx64"\n",
event_str[code-1], domain_id, device_id, *addr);
+
+ /* Tell the device to stop DMAing; we can't rely on the guest to
+ * control it for us. */
+ for ( bdf = 0; bdf < ivrs_bdf_entries; bdf++ )
+ if ( get_dma_requestor_id(bdf) == device_id )
+ {
+ cword = pci_conf_read16(PCI_BUS(bdf), PCI_SLOT(bdf),
+ PCI_FUNC(bdf), PCI_COMMAND);
+ pci_conf_write16(PCI_BUS(bdf), PCI_SLOT(bdf),
+ PCI_FUNC(bdf), PCI_COMMAND,
+ cword & ~PCI_COMMAND_MASTER);
+ }
}
else
{
--- a/xen/drivers/passthrough/vtd/iommu.c Mon Jul 25 16:48:39 2011 +0100
+++ b/xen/drivers/passthrough/vtd/iommu.c Fri Aug 12 11:33:41 2011 +0100
@@ -893,7 +893,7 @@ static void iommu_page_fault(int irq, vo
while (1)
{
u8 fault_reason;
- u16 source_id;
+ u16 source_id, cword;
u32 data;
u64 guest_addr;
int type;
@@ -926,6 +926,14 @@ static void iommu_page_fault(int irq, vo
iommu_page_fault_do_one(iommu, type, fault_reason,
source_id, guest_addr);
+ /* Tell the device to stop DMAing; we can't rely on the guest to
+ * control it for us. */
+ cword = pci_conf_read16(PCI_BUS(source_id), PCI_SLOT(source_id),
+ PCI_FUNC(source_id), PCI_COMMAND);
+ pci_conf_write16(PCI_BUS(source_id), PCI_SLOT(source_id),
+ PCI_FUNC(source_id), PCI_COMMAND,
+ cword & ~PCI_COMMAND_MASTER);
+
fault_index++;
if ( fault_index > cap_num_fault_regs(iommu->cap) )
fault_index = 0;
A malicious guest administrator of a VM that has direct control of a PCI[E] device can cause a performance degradation, and possibly hang the host.
DoS