diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-12-18 15:38:35 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-12-18 15:38:35 -0500 |
| commit | ccdd96be43a2e27fc69152df8fcfd30f2902b255 (patch) | |
| tree | 1cb10bc7a358fabf15df6ed4153e1cb0bfa69e07 /drivers | |
| parent | 3273cba1956437820ae25d98e3ae57d1c094205c (diff) | |
| parent | 7f8312a3b31de5676144d9e75f2f2647c8b4b769 (diff) | |
Merge tag 'iommu-fixes-v4.4-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu
Pull IOMMU fixes from Joerg Roedel:
"Two similar fixes for the Intel and AMD IOMMU drivers to add proper
access checks before calling handle_mm_fault"
* tag 'iommu-fixes-v4.4-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu:
iommu/vt-d: Do access checks before calling handle_mm_fault()
iommu/amd: Do proper access checking before calling handle_mm_fault()
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/iommu/amd_iommu_v2.c | 20 | ||||
| -rw-r--r-- | drivers/iommu/intel-svm.c | 20 |
2 files changed, 38 insertions, 2 deletions
diff --git a/drivers/iommu/amd_iommu_v2.c b/drivers/iommu/amd_iommu_v2.c index d21d4edf7236..7caf2fa237f2 100644 --- a/drivers/iommu/amd_iommu_v2.c +++ b/drivers/iommu/amd_iommu_v2.c | |||
| @@ -494,6 +494,22 @@ static void handle_fault_error(struct fault *fault) | |||
| 494 | } | 494 | } |
| 495 | } | 495 | } |
| 496 | 496 | ||
| 497 | static bool access_error(struct vm_area_struct *vma, struct fault *fault) | ||
| 498 | { | ||
| 499 | unsigned long requested = 0; | ||
| 500 | |||
| 501 | if (fault->flags & PPR_FAULT_EXEC) | ||
| 502 | requested |= VM_EXEC; | ||
| 503 | |||
| 504 | if (fault->flags & PPR_FAULT_READ) | ||
| 505 | requested |= VM_READ; | ||
| 506 | |||
| 507 | if (fault->flags & PPR_FAULT_WRITE) | ||
| 508 | requested |= VM_WRITE; | ||
| 509 | |||
| 510 | return (requested & ~vma->vm_flags) != 0; | ||
| 511 | } | ||
| 512 | |||
| 497 | static void do_fault(struct work_struct *work) | 513 | static void do_fault(struct work_struct *work) |
| 498 | { | 514 | { |
| 499 | struct fault *fault = container_of(work, struct fault, work); | 515 | struct fault *fault = container_of(work, struct fault, work); |
| @@ -516,8 +532,8 @@ static void do_fault(struct work_struct *work) | |||
| 516 | goto out; | 532 | goto out; |
| 517 | } | 533 | } |
| 518 | 534 | ||
| 519 | if (!(vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE))) { | 535 | /* Check if we have the right permissions on the vma */ |
| 520 | /* handle_mm_fault would BUG_ON() */ | 536 | if (access_error(vma, fault)) { |
| 521 | up_read(&mm->mmap_sem); | 537 | up_read(&mm->mmap_sem); |
| 522 | handle_fault_error(fault); | 538 | handle_fault_error(fault); |
| 523 | goto out; | 539 | goto out; |
diff --git a/drivers/iommu/intel-svm.c b/drivers/iommu/intel-svm.c index c69e3f9ec958..50464833d0b8 100644 --- a/drivers/iommu/intel-svm.c +++ b/drivers/iommu/intel-svm.c | |||
| @@ -484,6 +484,23 @@ struct page_req_dsc { | |||
| 484 | }; | 484 | }; |
| 485 | 485 | ||
| 486 | #define PRQ_RING_MASK ((0x1000 << PRQ_ORDER) - 0x10) | 486 | #define PRQ_RING_MASK ((0x1000 << PRQ_ORDER) - 0x10) |
| 487 | |||
| 488 | static bool access_error(struct vm_area_struct *vma, struct page_req_dsc *req) | ||
| 489 | { | ||
| 490 | unsigned long requested = 0; | ||
| 491 | |||
| 492 | if (req->exe_req) | ||
| 493 | requested |= VM_EXEC; | ||
| 494 | |||
| 495 | if (req->rd_req) | ||
| 496 | requested |= VM_READ; | ||
| 497 | |||
| 498 | if (req->wr_req) | ||
| 499 | requested |= VM_WRITE; | ||
| 500 | |||
| 501 | return (requested & ~vma->vm_flags) != 0; | ||
| 502 | } | ||
| 503 | |||
| 487 | static irqreturn_t prq_event_thread(int irq, void *d) | 504 | static irqreturn_t prq_event_thread(int irq, void *d) |
| 488 | { | 505 | { |
| 489 | struct intel_iommu *iommu = d; | 506 | struct intel_iommu *iommu = d; |
| @@ -539,6 +556,9 @@ static irqreturn_t prq_event_thread(int irq, void *d) | |||
| 539 | if (!vma || address < vma->vm_start) | 556 | if (!vma || address < vma->vm_start) |
| 540 | goto invalid; | 557 | goto invalid; |
| 541 | 558 | ||
| 559 | if (access_error(vma, req)) | ||
| 560 | goto invalid; | ||
| 561 | |||
| 542 | ret = handle_mm_fault(svm->mm, vma, address, | 562 | ret = handle_mm_fault(svm->mm, vma, address, |
| 543 | req->wr_req ? FAULT_FLAG_WRITE : 0); | 563 | req->wr_req ? FAULT_FLAG_WRITE : 0); |
| 544 | if (ret & VM_FAULT_ERROR) | 564 | if (ret & VM_FAULT_ERROR) |
