136 lines
4.0 KiB
Diff
136 lines
4.0 KiB
Diff
|
# Commit a8bc99b981c5ad773bd646f5986e616d26fb94d7
|
||
|
# Date 2015-07-16 11:50:07 +0200
|
||
|
# Author Elena Ufimtseva <elena.ufimtseva@oracle.com>
|
||
|
# Committer Jan Beulich <jbeulich@suse.com>
|
||
|
dmar: device scope mem leak fix
|
||
|
|
||
|
Release memory allocated for scope.devices dmar units on various
|
||
|
failure paths and when disabling dmar. Set device count after
|
||
|
sucessfull memory allocation, not before, in device scope parsing function.
|
||
|
|
||
|
Signed-off-by: Elena Ufimtseva <elena.ufimtseva@oracle.com>
|
||
|
Reviewed-by: Jan Beulich <jbeulich@suse.com>
|
||
|
Acked-by: Yang Zhang <yang.z.zhang@intel.com>
|
||
|
|
||
|
# Commit 132231d10343608faf5892785a08acc500326d04
|
||
|
# Date 2015-07-16 15:23:37 +0200
|
||
|
# Author Andrew Cooper <andrew.cooper3@citrix.com>
|
||
|
# Committer Jan Beulich <jbeulich@suse.com>
|
||
|
dmar: fix double free in error paths following c/s a8bc99b
|
||
|
|
||
|
Several error paths would end up freeing scope->devices twice.
|
||
|
|
||
|
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
|
||
|
Reviewed-by: Jan Beulich <jbeulich@suse.com>
|
||
|
|
||
|
--- a/xen/drivers/passthrough/vtd/dmar.c
|
||
|
+++ b/xen/drivers/passthrough/vtd/dmar.c
|
||
|
@@ -80,6 +80,16 @@ static int __init acpi_register_rmrr_uni
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
+static void scope_devices_free(struct dmar_scope *scope)
|
||
|
+{
|
||
|
+ if ( !scope )
|
||
|
+ return;
|
||
|
+
|
||
|
+ scope->devices_cnt = 0;
|
||
|
+ xfree(scope->devices);
|
||
|
+ scope->devices = NULL;
|
||
|
+}
|
||
|
+
|
||
|
static void __init disable_all_dmar_units(void)
|
||
|
{
|
||
|
struct acpi_drhd_unit *drhd, *_drhd;
|
||
|
@@ -89,16 +99,19 @@ static void __init disable_all_dmar_unit
|
||
|
list_for_each_entry_safe ( drhd, _drhd, &acpi_drhd_units, list )
|
||
|
{
|
||
|
list_del(&drhd->list);
|
||
|
+ scope_devices_free(&drhd->scope);
|
||
|
xfree(drhd);
|
||
|
}
|
||
|
list_for_each_entry_safe ( rmrr, _rmrr, &acpi_rmrr_units, list )
|
||
|
{
|
||
|
list_del(&rmrr->list);
|
||
|
+ scope_devices_free(&rmrr->scope);
|
||
|
xfree(rmrr);
|
||
|
}
|
||
|
list_for_each_entry_safe ( atsr, _atsr, &acpi_atsr_units, list )
|
||
|
{
|
||
|
list_del(&atsr->list);
|
||
|
+ scope_devices_free(&atsr->scope);
|
||
|
xfree(atsr);
|
||
|
}
|
||
|
}
|
||
|
@@ -317,13 +330,13 @@ static int __init acpi_parse_dev_scope(
|
||
|
if ( (cnt = scope_device_count(start, end)) < 0 )
|
||
|
return cnt;
|
||
|
|
||
|
- scope->devices_cnt = cnt;
|
||
|
if ( cnt > 0 )
|
||
|
{
|
||
|
scope->devices = xzalloc_array(u16, cnt);
|
||
|
if ( !scope->devices )
|
||
|
return -ENOMEM;
|
||
|
}
|
||
|
+ scope->devices_cnt = cnt;
|
||
|
|
||
|
while ( start < end )
|
||
|
{
|
||
|
@@ -426,7 +439,7 @@ static int __init acpi_parse_dev_scope(
|
||
|
|
||
|
out:
|
||
|
if ( ret )
|
||
|
- xfree(scope->devices);
|
||
|
+ scope_devices_free(scope);
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
@@ -541,6 +554,7 @@ acpi_parse_one_drhd(struct acpi_dmar_hea
|
||
|
" Workaround BIOS bug: ignore the DRHD due to all "
|
||
|
"devices under its scope are not PCI discoverable!\n");
|
||
|
|
||
|
+ scope_devices_free(&dmaru->scope);
|
||
|
iommu_free(dmaru);
|
||
|
xfree(dmaru);
|
||
|
}
|
||
|
@@ -561,9 +575,11 @@ acpi_parse_one_drhd(struct acpi_dmar_hea
|
||
|
out:
|
||
|
if ( ret )
|
||
|
{
|
||
|
+ scope_devices_free(&dmaru->scope);
|
||
|
iommu_free(dmaru);
|
||
|
xfree(dmaru);
|
||
|
}
|
||
|
+
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
@@ -657,6 +673,7 @@ acpi_parse_one_rmrr(struct acpi_dmar_hea
|
||
|
" Ignore the RMRR (%"PRIx64", %"PRIx64") due to "
|
||
|
"devices under its scope are not PCI discoverable!\n",
|
||
|
rmrru->base_address, rmrru->end_address);
|
||
|
+ scope_devices_free(&rmrru->scope);
|
||
|
xfree(rmrru);
|
||
|
}
|
||
|
else if ( base_addr > end_addr )
|
||
|
@@ -664,6 +681,7 @@ acpi_parse_one_rmrr(struct acpi_dmar_hea
|
||
|
dprintk(XENLOG_WARNING VTDPREFIX,
|
||
|
" The RMRR (%"PRIx64", %"PRIx64") is incorrect!\n",
|
||
|
rmrru->base_address, rmrru->end_address);
|
||
|
+ scope_devices_free(&rmrru->scope);
|
||
|
xfree(rmrru);
|
||
|
ret = -EFAULT;
|
||
|
}
|
||
|
@@ -726,7 +744,10 @@ acpi_parse_one_atsr(struct acpi_dmar_hea
|
||
|
}
|
||
|
|
||
|
if ( ret )
|
||
|
+ {
|
||
|
+ scope_devices_free(&atsru->scope);
|
||
|
xfree(atsru);
|
||
|
+ }
|
||
|
else
|
||
|
acpi_register_atsr_unit(atsru);
|
||
|
return ret;
|