aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoerg Roedel <jroedel@suse.de>2015-10-09 10:23:33 -0400
committerJoerg Roedel <jroedel@suse.de>2015-10-09 11:59:33 -0400
commit5adad9915472e180712030d730cdc476c6f8a60b (patch)
treea389220151e1a30590004ad0d2fa74911fd22d9c
parentcbbc00be2ce3af5d708226a9563fa27cb4e6b6b8 (diff)
iommu/amd: Fix NULL pointer deref on device detach
When a device group is detached from its domain, the iommu core code calls into the iommu driver to detach each device individually. Before this functionality went into the iommu core code, it was implemented in the drivers, also in the AMD IOMMU driver as the device alias handling code. This code is still present, as there might be aliases that don't exist as real PCI devices (and are therefore invisible to the iommu core code). Unfortunatly it might happen now, that a device is unbound multiple times from its domain, first by the alias handling code and then by the iommu core code (or vice verca). This ends up in the do_detach function which dereferences the dev_data->domain pointer. When the device is already detached, this pointer is NULL and we get a kernel oops. Removing the alias code completly is not an option, as that would also remove the code which handles invisible aliases. The code could be simplified, but this is too big of a change outside the merge window. For now, just check the dev_data->domain pointer in do_detach and bail out if it is NULL. Reported-by: Andreas Hartmann <andihartmann@freenet.de> Signed-off-by: Joerg Roedel <jroedel@suse.de>
-rw-r--r--drivers/iommu/amd_iommu.c9
1 files changed, 9 insertions, 0 deletions
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index f82060e778a2..08d2775887f7 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -2006,6 +2006,15 @@ static void do_detach(struct iommu_dev_data *dev_data)
2006{ 2006{
2007 struct amd_iommu *iommu; 2007 struct amd_iommu *iommu;
2008 2008
2009 /*
2010 * First check if the device is still attached. It might already
2011 * be detached from its domain because the generic
2012 * iommu_detach_group code detached it and we try again here in
2013 * our alias handling.
2014 */
2015 if (!dev_data->domain)
2016 return;
2017
2009 iommu = amd_iommu_rlookup_table[dev_data->devid]; 2018 iommu = amd_iommu_rlookup_table[dev_data->devid];
2010 2019
2011 /* decrease reference counters */ 2020 /* decrease reference counters */