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; }
#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: "
#ifdef CONFIG_ACPI_PCI
......@@ -204,12 +208,13 @@ acpi_parse_madt (
static int __init
acpi_parse_lapic (
acpi_table_entry_header *header)
acpi_table_entry_header *header, const unsigned long end)
{
struct acpi_table_lapic *processor = NULL;
processor = (struct acpi_table_lapic*) header;
if (!processor)
if (BAD_MADT_ENTRY(processor, end))
return -EINVAL;
acpi_table_print_madt_entry(header);
......@@ -225,15 +230,15 @@ acpi_parse_lapic (
return 0;
}
static int __init
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;
lapic_addr_ovr = (struct acpi_table_lapic_addr_ovr*) header;
if (!lapic_addr_ovr)
if (BAD_MADT_ENTRY(lapic_addr_ovr, end))
return -EINVAL;
acpi_lapic_addr = lapic_addr_ovr->address;
......@@ -243,12 +248,13 @@ acpi_parse_lapic_addr_ovr (
static int __init
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;
lapic_nmi = (struct acpi_table_lapic_nmi*) header;
if (!lapic_nmi)
if (BAD_MADT_ENTRY(lapic_nmi, end))
return -EINVAL;
acpi_table_print_madt_entry(header);
......@@ -266,12 +272,13 @@ acpi_parse_lapic_nmi (
static int __init
acpi_parse_ioapic (
acpi_table_entry_header *header)
acpi_table_entry_header *header, const unsigned long end)
{
struct acpi_table_ioapic *ioapic = NULL;
ioapic = (struct acpi_table_ioapic*) header;
if (!ioapic)
if (BAD_MADT_ENTRY(ioapic, end))
return -EINVAL;
acpi_table_print_madt_entry(header);
......@@ -320,12 +327,13 @@ acpi_sci_ioapic_setup(u32 gsi, u16 polarity, u16 trigger)
static int __init
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;
intsrc = (struct acpi_table_int_src_ovr*) header;
if (!intsrc)
if (BAD_MADT_ENTRY(intsrc, end))
return -EINVAL;
acpi_table_print_madt_entry(header);
......@@ -354,12 +362,13 @@ acpi_parse_int_src_ovr (
static int __init
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;
nmi_src = (struct acpi_table_nmi_src*) header;
if (!nmi_src)
if (BAD_MADT_ENTRY(nmi_src, end))
return -EINVAL;
acpi_table_print_madt_entry(header);
......@@ -729,6 +738,13 @@ acpi_process_madt(void)
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
return;
......
......@@ -52,6 +52,9 @@
#include <asm/sal.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: "
......@@ -158,12 +161,14 @@ static u8 has_8259;
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;
lapic = (struct acpi_table_lapic_addr_ovr *) header;
if (!lapic)
if (BAD_MADT_ENTRY(lapic, end))
return -EINVAL;
acpi_table_print_madt_entry(header);
......@@ -177,12 +182,13 @@ acpi_parse_lapic_addr_ovr (acpi_table_entry_header *header)
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;
lsapic = (struct acpi_table_lsapic *) header;
if (!lsapic)
if (BAD_MADT_ENTRY(lsapic, end))
return -EINVAL;
acpi_table_print_madt_entry(header);
......@@ -210,12 +216,13 @@ acpi_parse_lsapic (acpi_table_entry_header *header)
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;
lacpi_nmi = (struct acpi_table_lapic_nmi*) header;
if (!lacpi_nmi)
if (BAD_MADT_ENTRY(lacpi_nmi, end))
return -EINVAL;
acpi_table_print_madt_entry(header);
......@@ -226,12 +233,13 @@ acpi_parse_lapic_nmi (acpi_table_entry_header *header)
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;
iosapic = (struct acpi_table_iosapic *) header;
if (!iosapic)
if (BAD_MADT_ENTRY(iosapic, end))
return -EINVAL;
acpi_table_print_madt_entry(header);
......@@ -243,13 +251,15 @@ acpi_parse_iosapic (acpi_table_entry_header *header)
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;
int vector;
plintsrc = (struct acpi_table_plat_int_src *) header;
if (!plintsrc)
if (BAD_MADT_ENTRY(plintsrc, end))
return -EINVAL;
acpi_table_print_madt_entry(header);
......@@ -272,12 +282,14 @@ acpi_parse_plat_int_src (acpi_table_entry_header *header)
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;
p = (struct acpi_table_int_src_ovr *) header;
if (!p)
if (BAD_MADT_ENTRY(p, end))
return -EINVAL;
acpi_table_print_madt_entry(header);
......@@ -290,12 +302,13 @@ acpi_parse_int_src_ovr (acpi_table_entry_header *header)
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;
nmi_src = (struct acpi_table_nmi_src*) header;
if (!nmi_src)
if (BAD_MADT_ENTRY(nmi_src, end))
return -EINVAL;
acpi_table_print_madt_entry(header);
......
......@@ -343,10 +343,11 @@ acpi_table_parse_madt_family (
entry = (acpi_table_entry_header *)
((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 &&
(!max_entries || count++ < max_entries))
handler(entry);
if (handler(entry, madt_end))
return -EINVAL;
entry = (acpi_table_entry_header *)
((unsigned long) entry + entry->length);
......
......@@ -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];
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);
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