]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/commitdiff
x86: io-apic - interrupt remapping fix
authorCyrill Gorcunov <gorcunov@gmail.com>
Thu, 18 Sep 2008 19:37:57 +0000 (23:37 +0400)
committerIngo Molnar <mingo@elte.hu>
Thu, 16 Oct 2008 14:53:11 +0000 (16:53 +0200)
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>
arch/x86/kernel/apic.c
arch/x86/kernel/io_apic.c

index 784116933c708e73e2091cc1091184846e3ba400..1f48bd1c9f2dd9775a121ff4574bd02f53c8f0c6 100644 (file)
@@ -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);
 
@@ -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
@@ -1386,6 +1392,7 @@ end:
        else
                reinit_intr_remapped_IO_APIC(x2apic_preenabled);
 
+end:
        unmask_8259A();
        local_irq_restore(flags);
 
index 01419fdc1d5df88717eac95d05335b4c2fbce171..4cc9cb64c81198876427e55891049cbe7c3d6e8e 100644 (file)
@@ -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++)
@@ -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)