History

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()

Linus Torvalds committed 10 years ago

Commit ccdd96b2 parents 3273cba 7f8312a2 files · +38 −2Browse files

Unified · Split

2 files
  1. drivers/iommu/amd_iommu_v2.c +18 −2
  2. drivers/iommu/intel-svm.c +20 −0
drivers/iommu/amd_iommu_v2.c+18−2
@@ -494,6 +494,22 @@ static void handle_fault_error(struct fault *fault) · 493 unmodified lines
494494 }
495495 }
496496
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+
497513 static void do_fault(struct work_struct *work)
498514 {
499515 struct fault *fault = container_of(work, struct fault, work);
@@ -516,8 +532,8 @@ static void do_fault(struct work_struct *work) · 16 unmodified lines
516532 goto out;
517533 }
518534
519− if (!(vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE))) {
520− /* handle_mm_fault would BUG_ON() */
535+ /* Check if we have the right permissions on the vma */
536+ if (access_error(vma, fault)) {
521537 up_read(&mm->mmap_sem);
522538 handle_fault_error(fault);
523539 goto out;
drivers/iommu/intel-svm.c+20−0
@@ -484,6 +484,23 @@ struct page_req_dsc { · 483 unmodified lines
484484 };
485485
486486 #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+
487504 static irqreturn_t prq_event_thread(int irq, void *d)
488505 {
489506 struct intel_iommu *iommu = d;
@@ -539,6 +556,9 @@ static irqreturn_t prq_event_thread(int irq, void *d) · 49 unmodified lines
539556 if (!vma || address < vma->vm_start)
540557 goto invalid;
541558
559+ if (access_error(vma, req))
560+ goto invalid;
561+
542562 ret = handle_mm_fault(svm->mm, vma, address,
543563 req->wr_req ? FAULT_FLAG_WRITE : 0);
544564 if (ret & VM_FAULT_ERROR)