Commit a2e1b35b authored by Jes Sorensen's avatar Jes Sorensen Committed by Len Brown

[ACPI] Check for overflow when parsing MADT entries

from Jes Sorensen
parent 3a464adc
...@@ -43,8 +43,8 @@ ...@@ -43,8 +43,8 @@
int acpi_noirq __initdata = 0; /* skip ACPI IRQ initialization */ int acpi_noirq __initdata = 0; /* skip ACPI IRQ initialization */
int acpi_ht __initdata = 1; /* enable HT */ int acpi_ht __initdata = 1; /* enable HT */
int acpi_lapic = 0; int acpi_lapic;
int acpi_ioapic = 0; int acpi_ioapic;
/* -------------------------------------------------------------------------- /* --------------------------------------------------------------------------
Boot-time Configuration Boot-time Configuration
...@@ -456,7 +456,7 @@ acpi_boot_init (void) ...@@ -456,7 +456,7 @@ acpi_boot_init (void)
* and (optionally) overriden by a LAPIC_ADDR_OVR entry (64-bit value). * and (optionally) overriden by a LAPIC_ADDR_OVR entry (64-bit value).
*/ */
result = acpi_table_parse_madt(ACPI_MADT_LAPIC_ADDR_OVR, acpi_parse_lapic_addr_ovr); result = acpi_table_parse_madt(ACPI_MADT_LAPIC_ADDR_OVR, acpi_parse_lapic_addr_ovr, 0);
if (result < 0) { if (result < 0) {
printk(KERN_ERR PREFIX "Error parsing LAPIC address override entry\n"); printk(KERN_ERR PREFIX "Error parsing LAPIC address override entry\n");
return result; return result;
...@@ -464,7 +464,8 @@ acpi_boot_init (void) ...@@ -464,7 +464,8 @@ acpi_boot_init (void)
mp_register_lapic_address(acpi_lapic_addr); mp_register_lapic_address(acpi_lapic_addr);
result = acpi_table_parse_madt(ACPI_MADT_LAPIC, acpi_parse_lapic); result = acpi_table_parse_madt(ACPI_MADT_LAPIC, acpi_parse_lapic,
MAX_APICS);
if (!result) { if (!result) {
printk(KERN_ERR PREFIX "No LAPIC entries present\n"); printk(KERN_ERR PREFIX "No LAPIC entries present\n");
/* TBD: Cleanup to allow fallback to MPS */ /* TBD: Cleanup to allow fallback to MPS */
...@@ -476,7 +477,7 @@ acpi_boot_init (void) ...@@ -476,7 +477,7 @@ acpi_boot_init (void)
return result; return result;
} }
result = acpi_table_parse_madt(ACPI_MADT_LAPIC_NMI, acpi_parse_lapic_nmi); result = acpi_table_parse_madt(ACPI_MADT_LAPIC_NMI, acpi_parse_lapic_nmi, 0);
if (result < 0) { if (result < 0) {
printk(KERN_ERR PREFIX "Error parsing LAPIC NMI entry\n"); printk(KERN_ERR PREFIX "Error parsing LAPIC NMI entry\n");
/* TBD: Cleanup to allow fallback to MPS */ /* TBD: Cleanup to allow fallback to MPS */
...@@ -513,8 +514,8 @@ acpi_boot_init (void) ...@@ -513,8 +514,8 @@ acpi_boot_init (void)
return 1; return 1;
} }
result = acpi_table_parse_madt(ACPI_MADT_IOAPIC, acpi_parse_ioapic); result = acpi_table_parse_madt(ACPI_MADT_IOAPIC, acpi_parse_ioapic, MAX_IO_APICS);
if (!result) { if (!result) {
printk(KERN_ERR PREFIX "No IOAPIC entries present\n"); printk(KERN_ERR PREFIX "No IOAPIC entries present\n");
return -ENODEV; return -ENODEV;
} }
...@@ -526,14 +527,14 @@ acpi_boot_init (void) ...@@ -526,14 +527,14 @@ acpi_boot_init (void)
/* Build a default routing table for legacy (ISA) interrupts. */ /* Build a default routing table for legacy (ISA) interrupts. */
mp_config_acpi_legacy_irqs(); mp_config_acpi_legacy_irqs();
result = acpi_table_parse_madt(ACPI_MADT_INT_SRC_OVR, acpi_parse_int_src_ovr); result = acpi_table_parse_madt(ACPI_MADT_INT_SRC_OVR, acpi_parse_int_src_ovr, NR_IRQ_VECTORS);
if (result < 0) { if (result < 0) {
printk(KERN_ERR PREFIX "Error parsing interrupt source overrides entry\n"); printk(KERN_ERR PREFIX "Error parsing interrupt source overrides entry\n");
/* TBD: Cleanup to allow fallback to MPS */ /* TBD: Cleanup to allow fallback to MPS */
return result; return result;
} }
result = acpi_table_parse_madt(ACPI_MADT_NMI_SRC, acpi_parse_nmi_src); result = acpi_table_parse_madt(ACPI_MADT_NMI_SRC, acpi_parse_nmi_src, NR_IRQ_VECTORS);
if (result < 0) { if (result < 0) {
printk(KERN_ERR PREFIX "Error parsing NMI SRC entry\n"); printk(KERN_ERR PREFIX "Error parsing NMI SRC entry\n");
/* TBD: Cleanup to allow fallback to MPS */ /* TBD: Cleanup to allow fallback to MPS */
......
...@@ -189,8 +189,6 @@ acpi_parse_lsapic (acpi_table_entry_header *header) ...@@ -189,8 +189,6 @@ acpi_parse_lsapic (acpi_table_entry_header *header)
if (!lsapic->flags.enabled) if (!lsapic->flags.enabled)
printk(" disabled"); printk(" disabled");
else if (available_cpus >= NR_CPUS)
printk(" ignored (increase NR_CPUS)");
else { else {
printk(" enabled"); printk(" enabled");
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
...@@ -393,12 +391,6 @@ acpi_numa_memory_affinity_init (struct acpi_table_memory_affinity *ma) ...@@ -393,12 +391,6 @@ acpi_numa_memory_affinity_init (struct acpi_table_memory_affinity *ma)
size = ma->length_hi; size = ma->length_hi;
size = (size << 32) | ma->length_lo; size = (size << 32) | ma->length_lo;
if (num_memblks >= NR_MEMBLKS) {
printk(KERN_ERR "Too many mem chunks in SRAT. Ignoring %ld MBytes at %lx\n",
size/(1024*1024), paddr);
return;
}
/* Ignore disabled entries */ /* Ignore disabled entries */
if (!ma->flags.enabled) if (!ma->flags.enabled)
return; return;
...@@ -550,29 +542,29 @@ acpi_boot_init (void) ...@@ -550,29 +542,29 @@ acpi_boot_init (void)
/* Local APIC */ /* Local APIC */
if (acpi_table_parse_madt(ACPI_MADT_LAPIC_ADDR_OVR, acpi_parse_lapic_addr_ovr) < 0) if (acpi_table_parse_madt(ACPI_MADT_LAPIC_ADDR_OVR, acpi_parse_lapic_addr_ovr, 0) < 0)
printk(KERN_ERR PREFIX "Error parsing LAPIC address override entry\n"); printk(KERN_ERR PREFIX "Error parsing LAPIC address override entry\n");
if (acpi_table_parse_madt(ACPI_MADT_LSAPIC, acpi_parse_lsapic) < 1) if (acpi_table_parse_madt(ACPI_MADT_LSAPIC, acpi_parse_lsapic, NR_CPUS) < 1)
printk(KERN_ERR PREFIX "Error parsing MADT - no LAPIC entries\n"); printk(KERN_ERR PREFIX "Error parsing MADT - no LAPIC entries\n");
if (acpi_table_parse_madt(ACPI_MADT_LAPIC_NMI, acpi_parse_lapic_nmi) < 0) if (acpi_table_parse_madt(ACPI_MADT_LAPIC_NMI, acpi_parse_lapic_nmi, 0) < 0)
printk(KERN_ERR PREFIX "Error parsing LAPIC NMI entry\n"); printk(KERN_ERR PREFIX "Error parsing LAPIC NMI entry\n");
/* I/O APIC */ /* I/O APIC */
if (acpi_table_parse_madt(ACPI_MADT_IOSAPIC, acpi_parse_iosapic) < 1) if (acpi_table_parse_madt(ACPI_MADT_IOSAPIC, acpi_parse_iosapic, NR_IOSAPICS) < 1)
printk(KERN_ERR PREFIX "Error parsing MADT - no IOSAPIC entries\n"); printk(KERN_ERR PREFIX "Error parsing MADT - no IOSAPIC entries\n");
/* System-Level Interrupt Routing */ /* System-Level Interrupt Routing */
if (acpi_table_parse_madt(ACPI_MADT_PLAT_INT_SRC, acpi_parse_plat_int_src) < 0) if (acpi_table_parse_madt(ACPI_MADT_PLAT_INT_SRC, acpi_parse_plat_int_src, ACPI_MAX_PLATFORM_INTERRUPTS) < 0)
printk(KERN_ERR PREFIX "Error parsing platform interrupt source entry\n"); printk(KERN_ERR PREFIX "Error parsing platform interrupt source entry\n");
if (acpi_table_parse_madt(ACPI_MADT_INT_SRC_OVR, acpi_parse_int_src_ovr) < 0) if (acpi_table_parse_madt(ACPI_MADT_INT_SRC_OVR, acpi_parse_int_src_ovr, 0) < 0)
printk(KERN_ERR PREFIX "Error parsing interrupt source overrides entry\n"); printk(KERN_ERR PREFIX "Error parsing interrupt source overrides entry\n");
if (acpi_table_parse_madt(ACPI_MADT_NMI_SRC, acpi_parse_nmi_src) < 0) if (acpi_table_parse_madt(ACPI_MADT_NMI_SRC, acpi_parse_nmi_src, 0) < 0)
printk(KERN_ERR PREFIX "Error parsing NMI SRC entry\n"); printk(KERN_ERR PREFIX "Error parsing NMI SRC entry\n");
skip_madt: skip_madt:
......
...@@ -114,7 +114,7 @@ static struct iosapic { ...@@ -114,7 +114,7 @@ static struct iosapic {
char *addr; /* base address of IOSAPIC */ char *addr; /* base address of IOSAPIC */
unsigned int gsi_base; /* first GSI assigned to this IOSAPIC */ unsigned int gsi_base; /* first GSI assigned to this IOSAPIC */
unsigned short num_rte; /* number of RTE in this IOSAPIC */ unsigned short num_rte; /* number of RTE in this IOSAPIC */
} iosapic_lists[256]; } iosapic_lists[NR_IOSAPICS];
static int num_iosapic; static int num_iosapic;
......
...@@ -51,8 +51,8 @@ ...@@ -51,8 +51,8 @@
int acpi_noirq __initdata = 0; /* skip ACPI IRQ initialization */ int acpi_noirq __initdata = 0; /* skip ACPI IRQ initialization */
int acpi_ht __initdata = 1; /* enable HT */ int acpi_ht __initdata = 1; /* enable HT */
int acpi_lapic = 0; int acpi_lapic;
int acpi_ioapic = 0; int acpi_ioapic;
/* -------------------------------------------------------------------------- /* --------------------------------------------------------------------------
Boot-time Configuration Boot-time Configuration
...@@ -439,7 +439,7 @@ acpi_boot_init (void) ...@@ -439,7 +439,7 @@ acpi_boot_init (void)
* and (optionally) overriden by a LAPIC_ADDR_OVR entry (64-bit value). * and (optionally) overriden by a LAPIC_ADDR_OVR entry (64-bit value).
*/ */
result = acpi_table_parse_madt(ACPI_MADT_LAPIC_ADDR_OVR, acpi_parse_lapic_addr_ovr); result = acpi_table_parse_madt(ACPI_MADT_LAPIC_ADDR_OVR, acpi_parse_lapic_addr_ovr, 0);
if (result < 0) { if (result < 0) {
printk(KERN_ERR PREFIX "Error parsing LAPIC address override entry\n"); printk(KERN_ERR PREFIX "Error parsing LAPIC address override entry\n");
return result; return result;
...@@ -447,7 +447,8 @@ acpi_boot_init (void) ...@@ -447,7 +447,8 @@ acpi_boot_init (void)
mp_register_lapic_address(acpi_lapic_addr); mp_register_lapic_address(acpi_lapic_addr);
result = acpi_table_parse_madt(ACPI_MADT_LAPIC, acpi_parse_lapic); result = acpi_table_parse_madt(ACPI_MADT_LAPIC, acpi_parse_lapic,
MAX_APICS);
if (!result) { if (!result) {
printk(KERN_ERR PREFIX "No LAPIC entries present\n"); printk(KERN_ERR PREFIX "No LAPIC entries present\n");
/* TBD: Cleanup to allow fallback to MPS */ /* TBD: Cleanup to allow fallback to MPS */
...@@ -459,7 +460,7 @@ acpi_boot_init (void) ...@@ -459,7 +460,7 @@ acpi_boot_init (void)
return result; return result;
} }
result = acpi_table_parse_madt(ACPI_MADT_LAPIC_NMI, acpi_parse_lapic_nmi); result = acpi_table_parse_madt(ACPI_MADT_LAPIC_NMI, acpi_parse_lapic_nmi, 0);
if (result < 0) { if (result < 0) {
printk(KERN_ERR PREFIX "Error parsing LAPIC NMI entry\n"); printk(KERN_ERR PREFIX "Error parsing LAPIC NMI entry\n");
/* TBD: Cleanup to allow fallback to MPS */ /* TBD: Cleanup to allow fallback to MPS */
...@@ -496,8 +497,8 @@ acpi_boot_init (void) ...@@ -496,8 +497,8 @@ acpi_boot_init (void)
return 1; return 1;
} }
result = acpi_table_parse_madt(ACPI_MADT_IOAPIC, acpi_parse_ioapic); result = acpi_table_parse_madt(ACPI_MADT_IOAPIC, acpi_parse_ioapic, MAX_IO_APICS);
if (!result) { if (!result) {
printk(KERN_ERR PREFIX "No IOAPIC entries present\n"); printk(KERN_ERR PREFIX "No IOAPIC entries present\n");
return -ENODEV; return -ENODEV;
} }
...@@ -509,14 +510,15 @@ acpi_boot_init (void) ...@@ -509,14 +510,15 @@ acpi_boot_init (void)
/* Build a default routing table for legacy (ISA) interrupts. */ /* Build a default routing table for legacy (ISA) interrupts. */
mp_config_acpi_legacy_irqs(); mp_config_acpi_legacy_irqs();
result = acpi_table_parse_madt(ACPI_MADT_INT_SRC_OVR, acpi_parse_int_src_ovr); result = acpi_table_parse_madt(ACPI_MADT_INT_SRC_OVR, acpi_parse_int_src_ovr, NR_IRQ_VECTORS);
if (result < 0) { if (result < 0) {
printk(KERN_ERR PREFIX "Error parsing interrupt source overrides entry\n"); printk(KERN_ERR PREFIX "Error parsing interrupt source overrides entry\n");
/* TBD: Cleanup to allow fallback to MPS */ /* TBD: Cleanup to allow fallback to MPS */
return result; return result;
} }
result = acpi_table_parse_madt(ACPI_MADT_NMI_SRC, acpi_parse_nmi_src); result = acpi_table_parse_madt(ACPI_MADT_NMI_SRC, acpi_parse_nmi_src,
NR_IRQ_VECTORS);
if (result < 0) { if (result < 0) {
printk(KERN_ERR PREFIX "Error parsing NMI SRC entry\n"); printk(KERN_ERR PREFIX "Error parsing NMI SRC entry\n");
/* TBD: Cleanup to allow fallback to MPS */ /* TBD: Cleanup to allow fallback to MPS */
......
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
#include <linux/acpi.h> #include <linux/acpi.h>
#include <acpi/acpi_bus.h> #include <acpi/acpi_bus.h>
extern int __init acpi_table_parse_madt_family (enum acpi_table_id id, unsigned long madt_size, int entry_id, acpi_madt_entry_handler handler); extern int __init acpi_table_parse_madt_family (enum acpi_table_id id, unsigned long madt_size, int entry_id, acpi_madt_entry_handler handler, unsigned int max_entries);
void __init void __init
acpi_table_print_srat_entry ( acpi_table_print_srat_entry (
...@@ -149,10 +149,11 @@ acpi_parse_srat (unsigned long phys_addr, unsigned long size) ...@@ -149,10 +149,11 @@ acpi_parse_srat (unsigned long phys_addr, unsigned long size)
int __init int __init
acpi_table_parse_srat ( acpi_table_parse_srat (
enum acpi_srat_entry_id id, enum acpi_srat_entry_id id,
acpi_madt_entry_handler handler) acpi_madt_entry_handler handler,
unsigned int max_entries)
{ {
return acpi_table_parse_madt_family(ACPI_SRAT, sizeof(struct acpi_table_srat), return acpi_table_parse_madt_family(ACPI_SRAT, sizeof(struct acpi_table_srat),
id, handler); id, handler, max_entries);
} }
...@@ -166,9 +167,11 @@ acpi_numa_init() ...@@ -166,9 +167,11 @@ acpi_numa_init()
if (result > 0) { if (result > 0) {
result = acpi_table_parse_srat(ACPI_SRAT_PROCESSOR_AFFINITY, result = acpi_table_parse_srat(ACPI_SRAT_PROCESSOR_AFFINITY,
acpi_parse_processor_affinity); acpi_parse_processor_affinity,
NR_CPUS);
result = acpi_table_parse_srat(ACPI_SRAT_MEMORY_AFFINITY, result = acpi_table_parse_srat(ACPI_SRAT_MEMORY_AFFINITY,
acpi_parse_memory_affinity); acpi_parse_memory_affinity,
NR_MEMBLKS);
} else { } else {
/* FIXME */ /* FIXME */
printk("Warning: acpi_table_parse(ACPI_SRAT) returned %d!\n",result); printk("Warning: acpi_table_parse(ACPI_SRAT) returned %d!\n",result);
......
...@@ -302,13 +302,14 @@ acpi_table_parse_madt_family ( ...@@ -302,13 +302,14 @@ acpi_table_parse_madt_family (
enum acpi_table_id id, enum acpi_table_id id,
unsigned long madt_size, unsigned long madt_size,
int entry_id, int entry_id,
acpi_madt_entry_handler handler) acpi_madt_entry_handler handler,
unsigned int max_entries)
{ {
void *madt = NULL; void *madt = NULL;
acpi_table_entry_header *entry = NULL; acpi_table_entry_header *entry;
unsigned long count = 0; unsigned int count = 0;
unsigned long madt_end = 0; unsigned long madt_end;
unsigned int i = 0; unsigned int i;
if (!handler) if (!handler)
return -EINVAL; return -EINVAL;
...@@ -342,13 +343,18 @@ acpi_table_parse_madt_family ( ...@@ -342,13 +343,18 @@ acpi_table_parse_madt_family (
((unsigned long) madt + madt_size); ((unsigned long) madt + madt_size);
while (((unsigned long) entry) < madt_end) { while (((unsigned long) entry) < madt_end) {
if (entry->type == entry_id) { if (entry->type == entry_id &&
count++; (!max_entries || count++ < max_entries))
handler(entry); handler(entry);
}
entry = (acpi_table_entry_header *) entry = (acpi_table_entry_header *)
((unsigned long) entry + entry->length); ((unsigned long) entry + entry->length);
} }
if (max_entries && count > max_entries) {
printk(KERN_WARNING PREFIX "[%s:0x%02x] ignored %i entries of "
"%i found\n", acpi_table_signatures[id], entry_id,
count - max_entries, count);
}
return count; return count;
} }
...@@ -357,10 +363,11 @@ acpi_table_parse_madt_family ( ...@@ -357,10 +363,11 @@ acpi_table_parse_madt_family (
int __init int __init
acpi_table_parse_madt ( acpi_table_parse_madt (
enum acpi_madt_entry_id id, enum acpi_madt_entry_id id,
acpi_madt_entry_handler handler) acpi_madt_entry_handler handler,
unsigned int max_entries)
{ {
return acpi_table_parse_madt_family(ACPI_APIC, sizeof(struct acpi_table_madt), return acpi_table_parse_madt_family(ACPI_APIC, sizeof(struct acpi_table_madt),
id, handler); id, handler, max_entries);
} }
...@@ -585,4 +592,3 @@ acpi_table_init (void) ...@@ -585,4 +592,3 @@ acpi_table_init (void)
return 0; return 0;
} }
...@@ -52,6 +52,9 @@ ...@@ -52,6 +52,9 @@
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
#ifdef CONFIG_IOSAPIC #ifdef CONFIG_IOSAPIC
#define NR_IOSAPICS 256
extern void __init iosapic_system_init (int pcat_compat); extern void __init iosapic_system_init (int pcat_compat);
extern void __init iosapic_init (unsigned long address, extern void __init iosapic_init (unsigned long address,
unsigned int gsi_base); unsigned int gsi_base);
......
...@@ -355,8 +355,8 @@ int acpi_numa_init (void); ...@@ -355,8 +355,8 @@ int acpi_numa_init (void);
int acpi_table_init (void); int acpi_table_init (void);
int acpi_table_parse (enum acpi_table_id id, acpi_table_handler handler); int acpi_table_parse (enum acpi_table_id id, acpi_table_handler handler);
int acpi_get_table_header_early (enum acpi_table_id id, struct acpi_table_header **header); int acpi_get_table_header_early (enum acpi_table_id id, struct acpi_table_header **header);
int acpi_table_parse_madt (enum acpi_madt_entry_id id, acpi_madt_entry_handler handler); int acpi_table_parse_madt (enum acpi_madt_entry_id id, acpi_madt_entry_handler handler, unsigned int max_entries);
int acpi_table_parse_srat (enum acpi_srat_entry_id id, acpi_madt_entry_handler handler); int acpi_table_parse_srat (enum acpi_srat_entry_id id, acpi_madt_entry_handler handler, unsigned int max_entries);
void acpi_table_print (struct acpi_table_header *header, unsigned long phys_addr); void acpi_table_print (struct acpi_table_header *header, unsigned long phys_addr);
void acpi_table_print_madt_entry (acpi_table_entry_header *madt); void acpi_table_print_madt_entry (acpi_table_entry_header *madt);
void acpi_table_print_srat_entry (acpi_table_entry_header *srat); void acpi_table_print_srat_entry (acpi_table_entry_header *srat);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment