diff --git a/xen/arch/x86/apic.c b/xen/arch/x86/apic.c index 58f809ad42..af335607cd 100644 --- a/xen/arch/x86/apic.c +++ b/xen/arch/x86/apic.c @@ -560,12 +560,9 @@ void __devinit setup_local_APIC(void) init_apic_ldr(); /* - * Set Task Priority to 'accept all'. We never change this - * later on. + * Set Task Priority to reject any interrupts below FIRST_DYNAMIC_VECTOR. */ - value = apic_read(APIC_TASKPRI); - value &= ~APIC_TPRI_MASK; - apic_write_around(APIC_TASKPRI, value); + apic_write_around(APIC_TASKPRI, (FIRST_DYNAMIC_VECTOR & 0xF0) - 0x10); /* * After a crash, we no longer service the interrupts and a pending @@ -1439,3 +1436,9 @@ int __init APIC_init_uniprocessor (void) return 0; } + +void check_for_unexpected_msi(unsigned int vector) +{ + unsigned long v = apic_read(APIC_ISR + ((vector & ~0x1f) >> 1)); + BUG_ON(v & (1 << (vector & 0x1f))); +} diff --git a/xen/arch/x86/x86_64/compat/entry.S b/xen/arch/x86/x86_64/compat/entry.S index dc3b80afe9..3b4f12c151 100644 --- a/xen/arch/x86/x86_64/compat/entry.S +++ b/xen/arch/x86/x86_64/compat/entry.S @@ -10,12 +10,22 @@ #include #include #include +#include ALIGN ENTRY(compat_hypercall) pushq $0 movl $TRAP_syscall,4(%rsp) SAVE_ALL + + cmpb $0,untrusted_msi(%rip) +UNLIKELY_START(ne, msi_check) + movl $HYPERCALL_VECTOR,%edi + call check_for_unexpected_msi + RESTORE_ALL + SAVE_ALL +UNLIKELY_END(msi_check) + GET_CURRENT(%rbx) cmpl $NR_hypercalls,%eax diff --git a/xen/arch/x86/x86_64/entry.S b/xen/arch/x86/x86_64/entry.S index 6cf35f338e..4d49c4331c 100644 --- a/xen/arch/x86/x86_64/entry.S +++ b/xen/arch/x86/x86_64/entry.S @@ -297,6 +297,14 @@ ENTRY(int80_direct_trap) pushq $0 SAVE_ALL + cmpb $0,untrusted_msi(%rip) +UNLIKELY_START(ne, msi_check) + movl $0x80,%edi + call check_for_unexpected_msi + RESTORE_ALL + SAVE_ALL +UNLIKELY_END(msi_check) + GET_CURRENT(%rbx) /* Check that the callback is non-null. */ diff --git a/xen/drivers/passthrough/vtd/iommu.c b/xen/drivers/passthrough/vtd/iommu.c index 8338d3722b..aa3b34aa0a 100644 --- a/xen/drivers/passthrough/vtd/iommu.c +++ b/xen/drivers/passthrough/vtd/iommu.c @@ -45,6 +45,9 @@ #define nr_ioapics iosapic_get_nr_iosapics() #endif +/* Possible unfiltered LAPIC/MSI messages from untrusted sources? */ +bool_t __read_mostly untrusted_msi; + int nr_iommus; static void setup_dom0_devices(struct domain *d); @@ -1579,6 +1582,14 @@ static int reassign_device_ownership( if (!pdev) return -ENODEV; + /* + * Devices assigned to untrusted domains (here assumed to be any domU) + * can attempt to send arbitrary LAPIC/MSI messages. We are unprotected + * by the root complex unless interrupt remapping is enabled. + */ + if ( (target != dom0) && !iommu_intremap ) + untrusted_msi = 1; + ret = domain_context_unmap(source, bus, devfn); if ( ret ) return ret;