diff options
author | Joerg Roedel <joerg.roedel@amd.com> | 2010-01-22 10:45:31 -0500 |
---|---|---|
committer | Joerg Roedel <joerg.roedel@amd.com> | 2010-01-22 11:32:31 -0500 |
commit | 2ca762790caf822f7b61430fbaffa3ae4219977f (patch) | |
tree | 66a4633af764df377f9915b63d8fbbba3f6ed4b6 /arch/x86/kernel/amd_iommu.c | |
parent | d91afd15b041f27d34859c79afa9e172018a86f4 (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/x86/kernel/amd_iommu.c')
-rw-r--r-- | arch/x86/kernel/amd_iommu.c | 7 |
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 |