iommu/vt-d: Fix NULL pointer dereference in page request error case
authorDavid Woodhouse <David.Woodhouse@intel.com>
Thu, 15 Oct 2015 20:12:56 +0000 (21:12 +0100)
committerDavid Woodhouse <David.Woodhouse@intel.com>
Thu, 15 Oct 2015 20:16:22 +0000 (21:16 +0100)
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>
drivers/iommu/intel-svm.c

index 817be769e94f733981e309dcfa670a188fc6b5bc..b7e923aae4d87e4952333d1e061521f68a85688a 100644 (file)
@@ -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;
This page took 0.025343 seconds and 5 git commands to generate.