Skip to content

Commit

Permalink
x86: io-apic - interrupt remapping fix
Browse files Browse the repository at this point in the history
Interrupt remapping could lead to NULL dereference in case of
kzalloc failed and memory leak in other way. So fix the
both cases.

Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Cc: "Maciej W. Rozycki" <macro@linux-mips.org>
Cc: Suresh Siddha <suresh.b.siddha@intel.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
  • Loading branch information
Cyrill Gorcunov authored and Ingo Molnar committed Oct 16, 2008
1 parent 2976fe2 commit 5ffa4eb
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 5 deletions.
13 changes: 10 additions & 3 deletions arch/x86/kernel/apic.c
Original file line number Diff line number Diff line change
Expand Up @@ -1360,7 +1360,12 @@ void enable_IR_x2apic(void)

local_irq_save(flags);
mask_8259A();
save_mask_IO_APIC_setup();

ret = save_mask_IO_APIC_setup();
if (ret) {
printk(KERN_INFO "Saving IO-APIC state failed: %d\n", ret);
goto end;
}

ret = enable_intr_remapping(1);

Expand All @@ -1370,14 +1375,15 @@ void enable_IR_x2apic(void)
}

if (ret)
goto end;
goto end_restore;

if (!x2apic) {
x2apic = 1;
apic_ops = &x2apic_ops;
enable_x2apic();
}
end:

end_restore:
if (ret)
/*
* IR enabling failed
Expand All @@ -1386,6 +1392,7 @@ void enable_IR_x2apic(void)
else
reinit_intr_remapped_IO_APIC(x2apic_preenabled);

end:
unmask_8259A();
local_irq_restore(flags);

Expand Down
19 changes: 17 additions & 2 deletions arch/x86/kernel/io_apic.c
Original file line number Diff line number Diff line change
Expand Up @@ -812,7 +812,7 @@ int save_mask_IO_APIC_setup(void)
kzalloc(sizeof(struct IO_APIC_route_entry) *
nr_ioapic_registers[apic], GFP_KERNEL);
if (!early_ioapic_entries[apic])
return -ENOMEM;
goto nomem;
}

for (apic = 0; apic < nr_ioapics; apic++)
Expand All @@ -826,17 +826,32 @@ int save_mask_IO_APIC_setup(void)
ioapic_write_entry(apic, pin, entry);
}
}

return 0;

nomem:
for (; apic > 0; apic--)
kfree(early_ioapic_entries[apic]);
kfree(early_ioapic_entries[apic]);
memset(early_ioapic_entries, 0,
ARRAY_SIZE(early_ioapic_entries));

return -ENOMEM;
}

void restore_IO_APIC_setup(void)
{
int apic, pin;

for (apic = 0; apic < nr_ioapics; apic++)
for (apic = 0; apic < nr_ioapics; apic++) {
if (!early_ioapic_entries[apic])
break;
for (pin = 0; pin < nr_ioapic_registers[apic]; pin++)
ioapic_write_entry(apic, pin,
early_ioapic_entries[apic][pin]);
kfree(early_ioapic_entries[apic]);
early_ioapic_entries[apic] = NULL;
}
}

void reinit_intr_remapped_IO_APIC(int intr_remapping)
Expand Down

0 comments on commit 5ffa4eb

Please sign in to comment.