diff -r a4eac162dcb9 xen/drivers/passthrough/vtd/dmar.c --- a/xen/drivers/passthrough/vtd/dmar.c Thu Mar 25 01:05:03 2010 +0800 +++ b/xen/drivers/passthrough/vtd/dmar.c Fri Mar 26 01:59:55 2010 +0800 @@ -659,26 +659,71 @@ static int __init acpi_parse_dmar(struct while ( ((unsigned long)entry_header) < (((unsigned long)dmar) + table->length) ) { + if ( entry_header->length < sizeof(struct acpi_dmar_entry_header) ) + { + dprintk(XENLOG_ERR VTDPREFIX, + "Invalid ACPI DMAR entry length: 0x%x\n", + entry_header->length); + ret = -EINVAL; + break; + } + switch ( entry_header->type ) { case ACPI_DMAR_DRHD: if ( iommu_verbose ) dprintk(VTDPREFIX, "found ACPI_DMAR_DRHD:\n"); + + if ( entry_header->length < sizeof(struct acpi_table_drhd) ) + { + dprintk(XENLOG_ERR VTDPREFIX, + " Invalid length: 0x%x\n", entry_header->length); + ret = -EINVAL; + break; + } + ret = acpi_parse_one_drhd(entry_header); break; case ACPI_DMAR_RMRR: if ( iommu_verbose ) dprintk(VTDPREFIX, "found ACPI_DMAR_RMRR:\n"); + + if ( entry_header->length < sizeof(struct acpi_table_rmrr) ) + { + dprintk(XENLOG_ERR VTDPREFIX, + " Invalid length: 0x%x\n", entry_header->length); + ret = -EINVAL; + break; + } + ret = acpi_parse_one_rmrr(entry_header); break; case ACPI_DMAR_ATSR: if ( iommu_verbose ) dprintk(VTDPREFIX, "found ACPI_DMAR_ATSR:\n"); + + if ( entry_header->length < sizeof(struct acpi_table_atsr) ) + { + dprintk(XENLOG_ERR VTDPREFIX, + " Invalid length: 0x%x\n", entry_header->length); + ret = -EINVAL; + break; + } + ret = acpi_parse_one_atsr(entry_header); break; case ACPI_DMAR_RHSA: if ( iommu_verbose ) dprintk(VTDPREFIX, "found ACPI_DMAR_RHSA:\n"); + + if ( entry_header->length < sizeof(struct acpi_table_rhsa) ) + { + dprintk(XENLOG_ERR VTDPREFIX, + " Invalid length: 0x%x\n", entry_header->length); + ret = -EINVAL; + break; + } + ret = acpi_parse_one_rhsa(entry_header); break; default: