>>> Weidong Han <weidong.han@xxxxxxxxx> 25.03.10 01:55 >>>
>Do you mean to know which case fails on length checking? How about below
>patch?
Yes, something like this. Although I'd prefer to have a general
sizeof(struct acpi_dmar_entry_header) check before the switch
statement (to avoid even looking at out of range header fields),
and "break"s instead of "goto disable"s.
Jan
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 Thu Mar 25 17:46:03 2010 +0800
@@ -664,21 +664,57 @@ static int __init acpi_parse_dmar(struct
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;
+ goto disable;
+ }
+
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;
+ goto disable;
+ }
+
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;
+ goto disable;
+ }
+
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;
+ goto disable;
+ }
+
ret = acpi_parse_one_rhsa(entry_header);
break;
default:
@@ -694,6 +730,7 @@ static int __init acpi_parse_dmar(struct
entry_header = ((void *)entry_header + entry_header->length);
}
+disable:
if ( ret )
{
printk(XENLOG_WARNING
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|