x86/ioapic: Fix NULL pointer dereference on CPU hotplug after disabling irqs
In the current kernel, percpu variable `vector_irq' is not always
cleared when a CPU is offlined. If the CPU that has the disabled
irqs in vector_irq is hotplugged again, __setup_vector_irq()
hits invalid irq vector and may crash.
This bug can be reproduced as following;
# echo 0 > /sys/devices/system/cpu/cpu7/online
# modprobe -r some_driver_using_interrupts # vector_irq@cpu7 uncleared
# echo 1 > /sys/devices/system/cpu/cpu7/online # kernel may crash
To fix this problem, this patch clears vector_irq in
__fixup_irqs() when the CPU is offlined.
This also reverts commit f6175f5bfb
, which partially fixes
this bug by clearing vector in __clear_irq_vector(). But in
environments with IOMMU IRQ remapper, it could fail because
cfg->domain doesn't contain offlined CPUs. With this patch, the
fix in __clear_irq_vector() can be reverted because every
vector_irq is already cleared in __fixup_irqs() on offlined CPUs.
Signed-off-by: Tomoki Sekiyama <tomoki.sekiyama.qu@hitachi.com>
Acked-by: Suresh Siddha <suresh.b.siddha@intel.com>
Cc: yrl.pp-manager.tt@hitachi.com
Cc: Yinghai Lu <yinghai@kernel.org>
Cc: Alexander Gordeev <agordeev@redhat.com>
Link: http://lkml.kernel.org/r/20120726104732.2889.19144.stgit@kvmdev
Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
Родитель
d431adfbc9
Коммит
1d44b30f35
|
@ -1204,7 +1204,7 @@ static void __clear_irq_vector(int irq, struct irq_cfg *cfg)
|
|||
BUG_ON(!cfg->vector);
|
||||
|
||||
vector = cfg->vector;
|
||||
for_each_cpu(cpu, cfg->domain)
|
||||
for_each_cpu_and(cpu, cfg->domain, cpu_online_mask)
|
||||
per_cpu(vector_irq, cpu)[vector] = -1;
|
||||
|
||||
cfg->vector = 0;
|
||||
|
@ -1212,7 +1212,7 @@ static void __clear_irq_vector(int irq, struct irq_cfg *cfg)
|
|||
|
||||
if (likely(!cfg->move_in_progress))
|
||||
return;
|
||||
for_each_cpu(cpu, cfg->old_domain) {
|
||||
for_each_cpu_and(cpu, cfg->old_domain, cpu_online_mask) {
|
||||
for (vector = FIRST_EXTERNAL_VECTOR; vector < NR_VECTORS;
|
||||
vector++) {
|
||||
if (per_cpu(vector_irq, cpu)[vector] != irq)
|
||||
|
|
|
@ -328,6 +328,7 @@ void fixup_irqs(void)
|
|||
chip->irq_retrigger(data);
|
||||
raw_spin_unlock(&desc->lock);
|
||||
}
|
||||
__this_cpu_write(vector_irq[vector], -1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
Загрузка…
Ссылка в новой задаче