aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorJoerg Roedel <joerg.roedel@amd.com>2010-01-22 10:45:31 -0500
committerJoerg Roedel <joerg.roedel@amd.com>2010-01-22 11:32:31 -0500
commit2ca762790caf822f7b61430fbaffa3ae4219977f (patch)
tree66a4633af764df377f9915b63d8fbbba3f6ed4b6 /arch
parentd91afd15b041f27d34859c79afa9e172018a86f4 (diff)
x86/amd-iommu: Fix NULL pointer dereference in __detach_device()
In the __detach_device function the reference count for a device-domain binding may become zero. This results in the device being removed from the domain and dev_data->domain will be NULL. This is bad because this pointer is dereferenced when trying to unlock the domain->lock. This patch fixes the issue by keeping the domain in a seperate variable. Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/kernel/amd_iommu.c7
1 files changed, 5 insertions, 2 deletions
diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index c2ccbd7b862f..4478a48198a8 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -1489,11 +1489,14 @@ static void __detach_device(struct device *dev)
1489{ 1489{
1490 struct iommu_dev_data *dev_data = get_dev_data(dev); 1490 struct iommu_dev_data *dev_data = get_dev_data(dev);
1491 struct iommu_dev_data *alias_data; 1491 struct iommu_dev_data *alias_data;
1492 struct protection_domain *domain;
1492 unsigned long flags; 1493 unsigned long flags;
1493 1494
1494 BUG_ON(!dev_data->domain); 1495 BUG_ON(!dev_data->domain);
1495 1496
1496 spin_lock_irqsave(&dev_data->domain->lock, flags); 1497 domain = dev_data->domain;
1498
1499 spin_lock_irqsave(&domain->lock, flags);
1497 1500
1498 if (dev_data->alias != dev) { 1501 if (dev_data->alias != dev) {
1499 alias_data = get_dev_data(dev_data->alias); 1502 alias_data = get_dev_data(dev_data->alias);
@@ -1504,7 +1507,7 @@ static void __detach_device(struct device *dev)
1504 if (atomic_dec_and_test(&dev_data->bind)) 1507 if (atomic_dec_and_test(&dev_data->bind))
1505 do_detach(dev); 1508 do_detach(dev);
1506 1509
1507 spin_unlock_irqrestore(&dev_data->domain->lock, flags); 1510 spin_unlock_irqrestore(&domain->lock, flags);
1508 1511
1509 /* 1512 /*
1510 * If we run in passthrough mode the device must be assigned to the 1513 * If we run in passthrough mode the device must be assigned to the