Commit 6c3d6ae4 authored by Len Brown's avatar Len Brown

[ACPI] Add MADT error checking (Yi Zhu)

http://bugzilla.kernel.org/show_bug.cgi?id=1434
parent b1cf0694
...@@ -51,6 +51,10 @@ static inline int ioapic_setup_disabled(void) { return 0; } ...@@ -51,6 +51,10 @@ static inline int ioapic_setup_disabled(void) { return 0; }
#endif /* X86 */ #endif /* X86 */
#define BAD_MADT_ENTRY(entry, end) ( \
(!entry) || (unsigned long)entry + sizeof(*entry) > end || \
((acpi_table_entry_header *)entry)->length != sizeof(*entry))
#define PREFIX "ACPI: " #define PREFIX "ACPI: "
#ifdef CONFIG_ACPI_PCI #ifdef CONFIG_ACPI_PCI
...@@ -204,12 +208,13 @@ acpi_parse_madt ( ...@@ -204,12 +208,13 @@ acpi_parse_madt (
static int __init static int __init
acpi_parse_lapic ( acpi_parse_lapic (
acpi_table_entry_header *header) acpi_table_entry_header *header, const unsigned long end)
{ {
struct acpi_table_lapic *processor = NULL; struct acpi_table_lapic *processor = NULL;
processor = (struct acpi_table_lapic*) header; processor = (struct acpi_table_lapic*) header;
if (!processor)
if (BAD_MADT_ENTRY(processor, end))
return -EINVAL; return -EINVAL;
acpi_table_print_madt_entry(header); acpi_table_print_madt_entry(header);
...@@ -225,15 +230,15 @@ acpi_parse_lapic ( ...@@ -225,15 +230,15 @@ acpi_parse_lapic (
return 0; return 0;
} }
static int __init static int __init
acpi_parse_lapic_addr_ovr ( acpi_parse_lapic_addr_ovr (
acpi_table_entry_header *header) acpi_table_entry_header *header, const unsigned long end)
{ {
struct acpi_table_lapic_addr_ovr *lapic_addr_ovr = NULL; struct acpi_table_lapic_addr_ovr *lapic_addr_ovr = NULL;
lapic_addr_ovr = (struct acpi_table_lapic_addr_ovr*) header; lapic_addr_ovr = (struct acpi_table_lapic_addr_ovr*) header;
if (!lapic_addr_ovr)
if (BAD_MADT_ENTRY(lapic_addr_ovr, end))
return -EINVAL; return -EINVAL;
acpi_lapic_addr = lapic_addr_ovr->address; acpi_lapic_addr = lapic_addr_ovr->address;
...@@ -243,12 +248,13 @@ acpi_parse_lapic_addr_ovr ( ...@@ -243,12 +248,13 @@ acpi_parse_lapic_addr_ovr (
static int __init static int __init
acpi_parse_lapic_nmi ( acpi_parse_lapic_nmi (
acpi_table_entry_header *header) acpi_table_entry_header *header, const unsigned long end)
{ {
struct acpi_table_lapic_nmi *lapic_nmi = NULL; struct acpi_table_lapic_nmi *lapic_nmi = NULL;
lapic_nmi = (struct acpi_table_lapic_nmi*) header; lapic_nmi = (struct acpi_table_lapic_nmi*) header;
if (!lapic_nmi)
if (BAD_MADT_ENTRY(lapic_nmi, end))
return -EINVAL; return -EINVAL;
acpi_table_print_madt_entry(header); acpi_table_print_madt_entry(header);
...@@ -266,12 +272,13 @@ acpi_parse_lapic_nmi ( ...@@ -266,12 +272,13 @@ acpi_parse_lapic_nmi (
static int __init static int __init
acpi_parse_ioapic ( acpi_parse_ioapic (
acpi_table_entry_header *header) acpi_table_entry_header *header, const unsigned long end)
{ {
struct acpi_table_ioapic *ioapic = NULL; struct acpi_table_ioapic *ioapic = NULL;
ioapic = (struct acpi_table_ioapic*) header; ioapic = (struct acpi_table_ioapic*) header;
if (!ioapic)
if (BAD_MADT_ENTRY(ioapic, end))
return -EINVAL; return -EINVAL;
acpi_table_print_madt_entry(header); acpi_table_print_madt_entry(header);
...@@ -320,12 +327,13 @@ acpi_sci_ioapic_setup(u32 gsi, u16 polarity, u16 trigger) ...@@ -320,12 +327,13 @@ acpi_sci_ioapic_setup(u32 gsi, u16 polarity, u16 trigger)
static int __init static int __init
acpi_parse_int_src_ovr ( acpi_parse_int_src_ovr (
acpi_table_entry_header *header) acpi_table_entry_header *header, const unsigned long end)
{ {
struct acpi_table_int_src_ovr *intsrc = NULL; struct acpi_table_int_src_ovr *intsrc = NULL;
intsrc = (struct acpi_table_int_src_ovr*) header; intsrc = (struct acpi_table_int_src_ovr*) header;
if (!intsrc)
if (BAD_MADT_ENTRY(intsrc, end))
return -EINVAL; return -EINVAL;
acpi_table_print_madt_entry(header); acpi_table_print_madt_entry(header);
...@@ -354,12 +362,13 @@ acpi_parse_int_src_ovr ( ...@@ -354,12 +362,13 @@ acpi_parse_int_src_ovr (
static int __init static int __init
acpi_parse_nmi_src ( acpi_parse_nmi_src (
acpi_table_entry_header *header) acpi_table_entry_header *header, const unsigned long end)
{ {
struct acpi_table_nmi_src *nmi_src = NULL; struct acpi_table_nmi_src *nmi_src = NULL;
nmi_src = (struct acpi_table_nmi_src*) header; nmi_src = (struct acpi_table_nmi_src*) header;
if (!nmi_src)
if (BAD_MADT_ENTRY(nmi_src, end))
return -EINVAL; return -EINVAL;
acpi_table_print_madt_entry(header); acpi_table_print_madt_entry(header);
...@@ -729,6 +738,13 @@ acpi_process_madt(void) ...@@ -729,6 +738,13 @@ acpi_process_madt(void)
clustered_apic_check(); clustered_apic_check();
} }
} }
if (error == -EINVAL) {
/*
* Dell Precision Workstation 410, 610 come here.
*/
printk(KERN_ERR PREFIX "Invalid BIOS MADT, disabling ACPI\n");
disable_acpi();
}
} }
#endif #endif
return; return;
......
...@@ -52,6 +52,9 @@ ...@@ -52,6 +52,9 @@
#include <asm/sal.h> #include <asm/sal.h>
#include <asm/cyclone.h> #include <asm/cyclone.h>
#define BAD_MADT_ENTRY(entry, end) ( \
(!entry) || (unsigned long)entry + sizeof(*entry) > end || \
((acpi_table_entry_header *)entry)->length != sizeof(*entry))
#define PREFIX "ACPI: " #define PREFIX "ACPI: "
...@@ -158,12 +161,14 @@ static u8 has_8259; ...@@ -158,12 +161,14 @@ static u8 has_8259;
static int __init static int __init
acpi_parse_lapic_addr_ovr (acpi_table_entry_header *header) acpi_parse_lapic_addr_ovr (
acpi_table_entry_header *header, const unsigned long end)
{ {
struct acpi_table_lapic_addr_ovr *lapic; struct acpi_table_lapic_addr_ovr *lapic;
lapic = (struct acpi_table_lapic_addr_ovr *) header; lapic = (struct acpi_table_lapic_addr_ovr *) header;
if (!lapic)
if (BAD_MADT_ENTRY(lapic, end))
return -EINVAL; return -EINVAL;
acpi_table_print_madt_entry(header); acpi_table_print_madt_entry(header);
...@@ -177,12 +182,13 @@ acpi_parse_lapic_addr_ovr (acpi_table_entry_header *header) ...@@ -177,12 +182,13 @@ acpi_parse_lapic_addr_ovr (acpi_table_entry_header *header)
static int __init static int __init
acpi_parse_lsapic (acpi_table_entry_header *header) acpi_parse_lsapic (acpi_table_entry_header *header, const unsigned long end)
{ {
struct acpi_table_lsapic *lsapic; struct acpi_table_lsapic *lsapic;
lsapic = (struct acpi_table_lsapic *) header; lsapic = (struct acpi_table_lsapic *) header;
if (!lsapic)
if (BAD_MADT_ENTRY(lsapic, end))
return -EINVAL; return -EINVAL;
acpi_table_print_madt_entry(header); acpi_table_print_madt_entry(header);
...@@ -210,12 +216,13 @@ acpi_parse_lsapic (acpi_table_entry_header *header) ...@@ -210,12 +216,13 @@ acpi_parse_lsapic (acpi_table_entry_header *header)
static int __init static int __init
acpi_parse_lapic_nmi (acpi_table_entry_header *header) acpi_parse_lapic_nmi (acpi_table_entry_header *header, const unsigned long end)
{ {
struct acpi_table_lapic_nmi *lacpi_nmi; struct acpi_table_lapic_nmi *lacpi_nmi;
lacpi_nmi = (struct acpi_table_lapic_nmi*) header; lacpi_nmi = (struct acpi_table_lapic_nmi*) header;
if (!lacpi_nmi)
if (BAD_MADT_ENTRY(lacpi_nmi, end))
return -EINVAL; return -EINVAL;
acpi_table_print_madt_entry(header); acpi_table_print_madt_entry(header);
...@@ -226,12 +233,13 @@ acpi_parse_lapic_nmi (acpi_table_entry_header *header) ...@@ -226,12 +233,13 @@ acpi_parse_lapic_nmi (acpi_table_entry_header *header)
static int __init static int __init
acpi_parse_iosapic (acpi_table_entry_header *header) acpi_parse_iosapic (acpi_table_entry_header *header, const unsigned long end)
{ {
struct acpi_table_iosapic *iosapic; struct acpi_table_iosapic *iosapic;
iosapic = (struct acpi_table_iosapic *) header; iosapic = (struct acpi_table_iosapic *) header;
if (!iosapic)
if (BAD_MADT_ENTRY(iosapic, end))
return -EINVAL; return -EINVAL;
acpi_table_print_madt_entry(header); acpi_table_print_madt_entry(header);
...@@ -243,13 +251,15 @@ acpi_parse_iosapic (acpi_table_entry_header *header) ...@@ -243,13 +251,15 @@ acpi_parse_iosapic (acpi_table_entry_header *header)
static int __init static int __init
acpi_parse_plat_int_src (acpi_table_entry_header *header) acpi_parse_plat_int_src (
acpi_table_entry_header *header, const unsigned long end)
{ {
struct acpi_table_plat_int_src *plintsrc; struct acpi_table_plat_int_src *plintsrc;
int vector; int vector;
plintsrc = (struct acpi_table_plat_int_src *) header; plintsrc = (struct acpi_table_plat_int_src *) header;
if (!plintsrc)
if (BAD_MADT_ENTRY(plintsrc, end))
return -EINVAL; return -EINVAL;
acpi_table_print_madt_entry(header); acpi_table_print_madt_entry(header);
...@@ -272,12 +282,14 @@ acpi_parse_plat_int_src (acpi_table_entry_header *header) ...@@ -272,12 +282,14 @@ acpi_parse_plat_int_src (acpi_table_entry_header *header)
static int __init static int __init
acpi_parse_int_src_ovr (acpi_table_entry_header *header) acpi_parse_int_src_ovr (
acpi_table_entry_header *header, const unsigned long end)
{ {
struct acpi_table_int_src_ovr *p; struct acpi_table_int_src_ovr *p;
p = (struct acpi_table_int_src_ovr *) header; p = (struct acpi_table_int_src_ovr *) header;
if (!p)
if (BAD_MADT_ENTRY(p, end))
return -EINVAL; return -EINVAL;
acpi_table_print_madt_entry(header); acpi_table_print_madt_entry(header);
...@@ -290,12 +302,13 @@ acpi_parse_int_src_ovr (acpi_table_entry_header *header) ...@@ -290,12 +302,13 @@ acpi_parse_int_src_ovr (acpi_table_entry_header *header)
static int __init static int __init
acpi_parse_nmi_src (acpi_table_entry_header *header) acpi_parse_nmi_src (acpi_table_entry_header *header, const unsigned long end)
{ {
struct acpi_table_nmi_src *nmi_src; struct acpi_table_nmi_src *nmi_src;
nmi_src = (struct acpi_table_nmi_src*) header; nmi_src = (struct acpi_table_nmi_src*) header;
if (!nmi_src)
if (BAD_MADT_ENTRY(nmi_src, end))
return -EINVAL; return -EINVAL;
acpi_table_print_madt_entry(header); acpi_table_print_madt_entry(header);
......
...@@ -343,10 +343,11 @@ acpi_table_parse_madt_family ( ...@@ -343,10 +343,11 @@ acpi_table_parse_madt_family (
entry = (acpi_table_entry_header *) entry = (acpi_table_entry_header *)
((unsigned long) madt + madt_size); ((unsigned long) madt + madt_size);
while (((unsigned long) entry) < madt_end) { while (((unsigned long) entry) + sizeof(acpi_table_entry_header) < madt_end) {
if (entry->type == entry_id && if (entry->type == entry_id &&
(!max_entries || count++ < max_entries)) (!max_entries || count++ < max_entries))
handler(entry); if (handler(entry, madt_end))
return -EINVAL;
entry = (acpi_table_entry_header *) entry = (acpi_table_entry_header *)
((unsigned long) entry + entry->length); ((unsigned long) entry + entry->length);
......
...@@ -374,7 +374,7 @@ typedef int (*acpi_table_handler) (unsigned long phys_addr, unsigned long size); ...@@ -374,7 +374,7 @@ typedef int (*acpi_table_handler) (unsigned long phys_addr, unsigned long size);
extern acpi_table_handler acpi_table_ops[ACPI_TABLE_COUNT]; extern acpi_table_handler acpi_table_ops[ACPI_TABLE_COUNT];
typedef int (*acpi_madt_entry_handler) (acpi_table_entry_header *header); typedef int (*acpi_madt_entry_handler) (acpi_table_entry_header *header, const unsigned long end);
char * __acpi_map_table (unsigned long phys_addr, unsigned long size); char * __acpi_map_table (unsigned long phys_addr, unsigned long size);
unsigned long acpi_find_rsdp (void); unsigned long acpi_find_rsdp (void);
......
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