diff options
author | Keir Fraser <keir.fraser@citrix.com> | 2010-03-25 09:32:21 +0000 |
---|---|---|
committer | Keir Fraser <keir.fraser@citrix.com> | 2010-03-25 09:32:21 +0000 |
commit | f81bf6953cf77cdd623bea373026eb77dac4d40a (patch) | |
tree | 4d0e4b611499c7c75b29335225d38c46ad33360e | |
parent | 5fead6d6759d83cd1924534ef303c9eccb97ba3a (diff) | |
download | xen-f81bf6953cf77cdd623bea373026eb77dac4d40a.tar.gz xen-f81bf6953cf77cdd623bea373026eb77dac4d40a.tar.bz2 xen-f81bf6953cf77cdd623bea373026eb77dac4d40a.zip |
VT-d: Sanity check ACPI DMAR struct lengths.
Signed-off-by: Weidong Han <weidong.han@intel.com>
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
-rw-r--r-- | xen/drivers/passthrough/vtd/dmar.c | 36 |
1 files changed, 32 insertions, 4 deletions
diff --git a/xen/drivers/passthrough/vtd/dmar.c b/xen/drivers/passthrough/vtd/dmar.c index 857ba861d5..310a66da3e 100644 --- a/xen/drivers/passthrough/vtd/dmar.c +++ b/xen/drivers/passthrough/vtd/dmar.c @@ -361,6 +361,17 @@ static int __init acpi_parse_dev_scope(void *start, void *end, return 0; } +static int __init acpi_dmar_check_length( + struct acpi_dmar_entry_header *h, unsigned int min_len) +{ + if ( h->length >= min_len ) + return 0; + dprintk(XENLOG_ERR VTDPREFIX, + "Invalid ACPI DMAR entry length: 0x%x\n", + h->length); + return -EINVAL; +} + static int __init acpi_parse_one_drhd(struct acpi_dmar_entry_header *header) { @@ -368,9 +379,12 @@ acpi_parse_one_drhd(struct acpi_dmar_entry_header *header) void *dev_scope_start, *dev_scope_end; struct acpi_drhd_unit *dmaru; void *addr; - int ret = 0; + int ret; static int include_all = 0; + if ( (ret = acpi_dmar_check_length(header, sizeof(*drhd))) != 0 ) + return ret; + dmaru = xmalloc(struct acpi_drhd_unit); if ( !dmaru ) return -ENOMEM; @@ -470,7 +484,10 @@ acpi_parse_one_rmrr(struct acpi_dmar_entry_header *header) struct acpi_rmrr_unit *rmrru; void *dev_scope_start, *dev_scope_end; u64 base_addr = rmrr->base_address, end_addr = rmrr->end_address; - int ret = 0; + int ret; + + if ( (ret = acpi_dmar_check_length(header, sizeof(*rmrr))) != 0 ) + return ret; #ifdef CONFIG_X86 /* This check is here simply to detect when RMRR values are @@ -564,10 +581,13 @@ acpi_parse_one_atsr(struct acpi_dmar_entry_header *header) { struct acpi_table_atsr *atsr = (struct acpi_table_atsr *)header; struct acpi_atsr_unit *atsru; - int ret = 0; + int ret; static int all_ports; void *dev_scope_start, *dev_scope_end; + if ( (ret = acpi_dmar_check_length(header, sizeof(*atsr))) != 0 ) + return ret; + atsru = xmalloc(struct acpi_atsr_unit); if ( !atsru ) return -ENOMEM; @@ -610,7 +630,10 @@ acpi_parse_one_rhsa(struct acpi_dmar_entry_header *header) { struct acpi_table_rhsa *rhsa = (struct acpi_table_rhsa *)header; struct acpi_rhsa_unit *rhsau; - int ret = 0; + int ret; + + if ( (ret = acpi_dmar_check_length(header, sizeof(*rhsa))) != 0 ) + return ret; rhsau = xmalloc(struct acpi_rhsa_unit); if ( !rhsau ) @@ -659,6 +682,11 @@ static int __init acpi_parse_dmar(struct acpi_table_header *table) while ( ((unsigned long)entry_header) < (((unsigned long)dmar) + table->length) ) { + ret = acpi_dmar_check_length( + entry_header, sizeof(struct acpi_dmar_entry_header)); + if ( ret ) + break; + switch ( entry_header->type ) { case ACPI_DMAR_DRHD: |