summaryrefslogtreecommitdiff
path: root/drivers/iommu
diff options
context:
space:
mode:
authorDavid Woodhouse <David.Woodhouse@intel.com>2015-10-15 23:12:56 +0300
committerDavid Woodhouse <David.Woodhouse@intel.com>2015-10-15 23:16:22 +0300
commit26322ab55aa90717c7e4bdbd8cf60a70854636f5 (patch)
treec3917aaa63647b39f416393652ece849e50d9e02 /drivers/iommu
parent5cec753709adf1a20c8b15edf8e5245cf4fd4e82 (diff)
downloadlinux-26322ab55aa90717c7e4bdbd8cf60a70854636f5.tar.xz
iommu/vt-d: Fix NULL pointer dereference in page request error case
Dan Carpenter pointed out an error path which could lead to us dereferencing the 'svm' pointer after we know it to be NULL because the PASID lookup failed. Fix that, and make it less likely to happen again. Fixes: a222a7f0bb6c ('iommu/vt-d: Implement page request handling') Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Diffstat (limited to 'drivers/iommu')
-rw-r--r--drivers/iommu/intel-svm.c12
1 files changed, 8 insertions, 4 deletions
diff --git a/drivers/iommu/intel-svm.c b/drivers/iommu/intel-svm.c
index 817be769e94f..b7e923aae4d8 100644
--- a/drivers/iommu/intel-svm.c
+++ b/drivers/iommu/intel-svm.c
@@ -510,7 +510,7 @@ static irqreturn_t prq_event_thread(int irq, void *d)
pr_err("%s: Page request for invalid PASID %d: %08llx %08llx\n",
iommu->name, req->pasid, ((unsigned long long *)req)[0],
((unsigned long long *)req)[1]);
- goto bad_req;
+ goto no_pasid;
}
}
@@ -552,7 +552,11 @@ static irqreturn_t prq_event_thread(int irq, void *d)
(req->wr_req << 1) | (req->exe_req);
sdev->ops->fault_cb(sdev->dev, req->pasid, req->addr, req->private, rwxp, result);
}
-
+ /* We get here in the error case where the PASID lookup failed,
+ and these can be NULL. Do not use them below this point! */
+ sdev = NULL;
+ svm = NULL;
+ no_pasid:
if (req->lpig) {
/* Page Group Response */
resp.low = QI_PGRP_PASID(req->pasid) |
@@ -562,7 +566,7 @@ static irqreturn_t prq_event_thread(int irq, void *d)
resp.high = QI_PGRP_IDX(req->prg_index) |
QI_PGRP_PRIV(req->private) | QI_PGRP_RESP_CODE(result);
- qi_submit_sync(&resp, svm->iommu);
+ qi_submit_sync(&resp, iommu);
} else if (req->srr) {
/* Page Stream Response */
resp.low = QI_PSTRM_IDX(req->prg_index) |
@@ -571,7 +575,7 @@ static irqreturn_t prq_event_thread(int irq, void *d)
resp.high = QI_PSTRM_ADDR(address) | QI_PSTRM_DEVFN(req->devfn) |
QI_PSTRM_RESP_CODE(result);
- qi_submit_sync(&resp, svm->iommu);
+ qi_submit_sync(&resp, iommu);
}
head = (head + sizeof(*req)) & PRQ_RING_MASK;