x86/intel/irq_remapping: Clean up x2apic opt-out security warning mess

Current kernels print this on my Dell server:

   ------------[ cut here ]------------
   WARNING: at drivers/iommu/intel_irq_remapping.c:542
   intel_enable_irq_remapping+0x7b/0x27e()
   Hardware name: PowerEdge R620
   Your BIOS is broken and requested that x2apic be disabled
   This will leave your machine vulnerable to irq-injection attacks
   Use 'intremap=no_x2apic_optout' to override BIOS request
   [...]
   Enabled IRQ remapping in xapic mode
   x2apic not enabled, IRQ remapping is in xapic mode

This is inconsistent with itself -- interrupt remapping is *on*.

Fix the mess by making the warnings say what they mean and my
making sure that compatibility format interrupts (the dangerous
ones) are disabled if x2apic is present regardless of BIOS
settings.

With this patch applied, the output is:

  Your BIOS is broken and requested that x2apic be disabled.
  This will slightly decrease performance.
  Use 'intremap=no_x2apic_optout' to override BIOS request.
  Enabled IRQ remapping in xapic mode
  x2apic not enabled, IRQ remapping is in xapic mode

This should make us as or more secure than we are now and
replace a rather scary warning with a much less scary warning on
silly but functional systems.

Signed-off-by: Andy Lutomirski <luto@amacapital.net>
Cc: Suresh Siddha <suresh.b.siddha@intel.com>
Cc: Prarit Bhargava <prarit@redhat.com>
Cc: Gleb Natapov <gleb@redhat.com>
Cc: Don Zickus <dzickus@redhat.com>
Cc: Alex Williamson <alex.williamson@redhat.com>
Link: http://lkml.kernel.org/r/2011b943a886fd7c46079eb10bc24fc130587503.1359759303.git.luto@amacapital.net
Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
Andy Lutomirski 2013-02-01 14:57:43 -08:00 committed by Ingo Molnar
parent e9b6025bf8
commit af8d102f99

View File

@ -429,11 +429,22 @@ static void iommu_set_irq_remapping(struct intel_iommu *iommu, int mode)
/* Enable interrupt-remapping */ /* Enable interrupt-remapping */
iommu->gcmd |= DMA_GCMD_IRE; iommu->gcmd |= DMA_GCMD_IRE;
iommu->gcmd &= ~DMA_GCMD_CFI; /* Block compatibility-format MSIs */
writel(iommu->gcmd, iommu->reg + DMAR_GCMD_REG); writel(iommu->gcmd, iommu->reg + DMAR_GCMD_REG);
IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG, IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
readl, (sts & DMA_GSTS_IRES), sts); readl, (sts & DMA_GSTS_IRES), sts);
/*
* With CFI clear in the Global Command register, we should be
* protected from dangerous (i.e. compatibility) interrupts
* regardless of x2apic status. Check just to be sure.
*/
if (sts & DMA_GSTS_CFIS)
WARN(1, KERN_WARNING
"Compatibility-format IRQs enabled despite intr remapping;\n"
"you are vulnerable to IRQ injection.\n");
raw_spin_unlock_irqrestore(&iommu->register_lock, flags); raw_spin_unlock_irqrestore(&iommu->register_lock, flags);
} }
@ -530,20 +541,24 @@ static int __init intel_irq_remapping_supported(void)
static int __init intel_enable_irq_remapping(void) static int __init intel_enable_irq_remapping(void)
{ {
struct dmar_drhd_unit *drhd; struct dmar_drhd_unit *drhd;
bool x2apic_present;
int setup = 0; int setup = 0;
int eim = 0; int eim = 0;
x2apic_present = x2apic_supported();
if (parse_ioapics_under_ir() != 1) { if (parse_ioapics_under_ir() != 1) {
printk(KERN_INFO "Not enable interrupt remapping\n"); printk(KERN_INFO "Not enable interrupt remapping\n");
return -1; goto error;
} }
if (x2apic_supported()) { if (x2apic_present) {
eim = !dmar_x2apic_optout(); eim = !dmar_x2apic_optout();
WARN(!eim, KERN_WARNING if (!eim)
"Your BIOS is broken and requested that x2apic be disabled\n" printk(KERN_WARNING
"This will leave your machine vulnerable to irq-injection attacks\n" "Your BIOS is broken and requested that x2apic be disabled.\n"
"Use 'intremap=no_x2apic_optout' to override BIOS request\n"); "This will slightly decrease performance.\n"
"Use 'intremap=no_x2apic_optout' to override BIOS request.\n");
} }
for_each_drhd_unit(drhd) { for_each_drhd_unit(drhd) {
@ -582,7 +597,7 @@ static int __init intel_enable_irq_remapping(void)
if (eim && !ecap_eim_support(iommu->ecap)) { if (eim && !ecap_eim_support(iommu->ecap)) {
printk(KERN_INFO "DRHD %Lx: EIM not supported by DRHD, " printk(KERN_INFO "DRHD %Lx: EIM not supported by DRHD, "
" ecap %Lx\n", drhd->reg_base_addr, iommu->ecap); " ecap %Lx\n", drhd->reg_base_addr, iommu->ecap);
return -1; goto error;
} }
} }
@ -598,7 +613,7 @@ static int __init intel_enable_irq_remapping(void)
printk(KERN_ERR "DRHD %Lx: failed to enable queued, " printk(KERN_ERR "DRHD %Lx: failed to enable queued, "
" invalidation, ecap %Lx, ret %d\n", " invalidation, ecap %Lx, ret %d\n",
drhd->reg_base_addr, iommu->ecap, ret); drhd->reg_base_addr, iommu->ecap, ret);
return -1; goto error;
} }
} }
@ -637,6 +652,11 @@ error:
/* /*
* handle error condition gracefully here! * handle error condition gracefully here!
*/ */
if (x2apic_present)
WARN(1, KERN_WARNING
"Failed to enable irq remapping. You are vulnerable to irq-injection attacks.\n");
return -1; return -1;
} }