From: Greg Kroah-Hartman Date: Thu, 18 Aug 2016 09:47:21 +0000 (+0200) Subject: 4.4-stable patches X-Git-Tag: v3.14.77~28 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=6169752c68db40fe826acf90bf08639c11aab653;p=thirdparty%2Fkernel%2Fstable-queue.git 4.4-stable patches added patches: mips-kvm-add-missing-gfn-range-check.patch mips-kvm-fix-gfn-range-check-in-kseg0-tlb-faults.patch mips-kvm-fix-mapped-fault-broken-commpage-handling.patch mips-kvm-propagate-kseg0-mapped-tlb-fault-errors.patch --- diff --git a/queue-4.4/mips-kvm-add-missing-gfn-range-check.patch b/queue-4.4/mips-kvm-add-missing-gfn-range-check.patch new file mode 100644 index 00000000000..7791783b1cb --- /dev/null +++ b/queue-4.4/mips-kvm-add-missing-gfn-range-check.patch @@ -0,0 +1,76 @@ +From james.hogan@imgtec.com Thu Aug 18 11:44:38 2016 +From: James Hogan +Date: Thu, 18 Aug 2016 10:05:30 +0100 +Subject: [PATCH BACKPORT 3.17-4.4 2/4] MIPS: KVM: Add missing gfn range check +To: +Cc: James Hogan , Paolo Bonzini , Radim Krčmář , Ralf Baechle , , +Message-ID: <5ae3371dc11534460b722864ea8c6ef27e8506d1.1471018436.git-series.james.hogan@imgtec.com> + +From: James Hogan + +commit 8985d50382359e5bf118fdbefc859d0dbf6cebc7 upstream. + +kvm_mips_handle_mapped_seg_tlb_fault() calculates the guest frame number +based on the guest TLB EntryLo values, however it is not range checked +to ensure it lies within the guest_pmap. If the physical memory the +guest refers to is out of range then dump the guest TLB and emit an +internal error. + +Fixes: 858dd5d45733 ("KVM/MIPS32: MMU/TLB operations for the Guest.") +Signed-off-by: James Hogan +Cc: Paolo Bonzini +Cc: "Radim Krčmář" +Cc: Ralf Baechle +Cc: linux-mips@linux-mips.org +Cc: kvm@vger.kernel.org +Signed-off-by: Radim Krčmář +[james.hogan@imgtec.com: Backport to v3.17.y - v4.4.y] +Signed-off-by: James Hogan +Signed-off-by: Greg Kroah-Hartman +--- + arch/mips/kvm/tlb.c | 23 +++++++++++++++-------- + 1 file changed, 15 insertions(+), 8 deletions(-) + +--- a/arch/mips/kvm/tlb.c ++++ b/arch/mips/kvm/tlb.c +@@ -361,6 +361,7 @@ int kvm_mips_handle_mapped_seg_tlb_fault + unsigned long entryhi = 0, entrylo0 = 0, entrylo1 = 0; + struct kvm *kvm = vcpu->kvm; + pfn_t pfn0, pfn1; ++ gfn_t gfn0, gfn1; + long tlb_lo[2]; + + tlb_lo[0] = tlb->tlb_lo0; +@@ -374,18 +375,24 @@ int kvm_mips_handle_mapped_seg_tlb_fault + VPN2_MASK & (PAGE_MASK << 1))) + tlb_lo[(KVM_GUEST_COMMPAGE_ADDR >> PAGE_SHIFT) & 1] = 0; + +- if (kvm_mips_map_page(kvm, mips3_tlbpfn_to_paddr(tlb_lo[0]) +- >> PAGE_SHIFT) < 0) ++ gfn0 = mips3_tlbpfn_to_paddr(tlb_lo[0]) >> PAGE_SHIFT; ++ gfn1 = mips3_tlbpfn_to_paddr(tlb_lo[1]) >> PAGE_SHIFT; ++ if (gfn0 >= kvm->arch.guest_pmap_npages || ++ gfn1 >= kvm->arch.guest_pmap_npages) { ++ kvm_err("%s: Invalid gfn: [%#llx, %#llx], EHi: %#lx\n", ++ __func__, gfn0, gfn1, tlb->tlb_hi); ++ kvm_mips_dump_guest_tlbs(vcpu); + return -1; ++ } + +- if (kvm_mips_map_page(kvm, mips3_tlbpfn_to_paddr(tlb_lo[1]) +- >> PAGE_SHIFT) < 0) ++ if (kvm_mips_map_page(kvm, gfn0) < 0) + return -1; + +- pfn0 = kvm->arch.guest_pmap[mips3_tlbpfn_to_paddr(tlb_lo[0]) +- >> PAGE_SHIFT]; +- pfn1 = kvm->arch.guest_pmap[mips3_tlbpfn_to_paddr(tlb_lo[1]) +- >> PAGE_SHIFT]; ++ if (kvm_mips_map_page(kvm, gfn1) < 0) ++ return -1; ++ ++ pfn0 = kvm->arch.guest_pmap[gfn0]; ++ pfn1 = kvm->arch.guest_pmap[gfn1]; + + if (hpa0) + *hpa0 = pfn0 << PAGE_SHIFT; diff --git a/queue-4.4/mips-kvm-fix-gfn-range-check-in-kseg0-tlb-faults.patch b/queue-4.4/mips-kvm-fix-gfn-range-check-in-kseg0-tlb-faults.patch new file mode 100644 index 00000000000..1db856e577e --- /dev/null +++ b/queue-4.4/mips-kvm-fix-gfn-range-check-in-kseg0-tlb-faults.patch @@ -0,0 +1,41 @@ +From james.hogan@imgtec.com Thu Aug 18 11:44:51 2016 +From: James Hogan +Date: Thu, 18 Aug 2016 10:05:31 +0100 +Subject: [PATCH BACKPORT 3.17-4.4 3/4] MIPS: KVM: Fix gfn range check in kseg0 tlb faults +To: +Cc: James Hogan , Paolo Bonzini , Radim Krčmář , Ralf Baechle , , +Message-ID: <2c09ac935cd3721a0212d82eca7f9290481d5b4c.1471018436.git-series.james.hogan@imgtec.com> + +From: James Hogan + +commit 0741f52d1b980dbeb290afe67d88fc2928edd8ab upstream. + +Two consecutive gfns are loaded into host TLB, so ensure the range check +isn't off by one if guest_pmap_npages is odd. + +Fixes: 858dd5d45733 ("KVM/MIPS32: MMU/TLB operations for the Guest.") +Signed-off-by: James Hogan +Cc: Paolo Bonzini +Cc: "Radim Krčmář" +Cc: Ralf Baechle +Cc: linux-mips@linux-mips.org +Cc: kvm@vger.kernel.org +Signed-off-by: Radim Krčmář +[james.hogan@imgtec.com: Backport to v3.17.y - v4.4.y] +Signed-off-by: James Hogan +Signed-off-by: Greg Kroah-Hartman +--- + arch/mips/kvm/tlb.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/mips/kvm/tlb.c ++++ b/arch/mips/kvm/tlb.c +@@ -276,7 +276,7 @@ int kvm_mips_handle_kseg0_tlb_fault(unsi + } + + gfn = (KVM_GUEST_CPHYSADDR(badvaddr) >> PAGE_SHIFT); +- if (gfn >= kvm->arch.guest_pmap_npages) { ++ if ((gfn | 1) >= kvm->arch.guest_pmap_npages) { + kvm_err("%s: Invalid gfn: %#llx, BadVaddr: %#lx\n", __func__, + gfn, badvaddr); + kvm_mips_dump_host_tlbs(); diff --git a/queue-4.4/mips-kvm-fix-mapped-fault-broken-commpage-handling.patch b/queue-4.4/mips-kvm-fix-mapped-fault-broken-commpage-handling.patch new file mode 100644 index 00000000000..53746c3387b --- /dev/null +++ b/queue-4.4/mips-kvm-fix-mapped-fault-broken-commpage-handling.patch @@ -0,0 +1,105 @@ +From james.hogan@imgtec.com Thu Aug 18 11:44:25 2016 +From: James Hogan +Date: Thu, 18 Aug 2016 10:05:29 +0100 +Subject: [PATCH BACKPORT 3.17-4.4 1/4] MIPS: KVM: Fix mapped fault broken commpage handling +To: +Cc: James Hogan , Paolo Bonzini , Radim Krčmář , Ralf Baechle , , +Message-ID: <68df6d553f95e9f40311c92f7e010d90a329843a.1471018436.git-series.james.hogan@imgtec.com> + +From: James Hogan + +commit c604cffa93478f8888bec62b23d6073dad03d43a upstream. + +kvm_mips_handle_mapped_seg_tlb_fault() appears to map the guest page at +virtual address 0 to PFN 0 if the guest has created its own mapping +there. The intention is unclear, but it may have been an attempt to +protect the zero page from being mapped to anything but the comm page in +code paths you wouldn't expect from genuine commpage accesses (guest +kernel mode cache instructions on that address, hitting trapping +instructions when executing from that address with a coincidental TLB +eviction during the KVM handling, and guest user mode accesses to that +address). + +Fix this to check for mappings exactly at KVM_GUEST_COMMPAGE_ADDR (it +may not be at address 0 since commit 42aa12e74e91 ("MIPS: KVM: Move +commpage so 0x0 is unmapped")), and set the corresponding EntryLo to be +interpreted as 0 (invalid). + +Fixes: 858dd5d45733 ("KVM/MIPS32: MMU/TLB operations for the Guest.") +Signed-off-by: James Hogan +Cc: Paolo Bonzini +Cc: "Radim Krčmář" +Cc: Ralf Baechle +Cc: linux-mips@linux-mips.org +Cc: kvm@vger.kernel.org +Signed-off-by: Radim Krčmář +[james.hogan@imgtec.com: Backport to v3.17.y - v4.4.y] +Signed-off-by: James Hogan +Signed-off-by: Greg Kroah-Hartman +--- + arch/mips/kvm/tlb.c | 45 ++++++++++++++++++++++++++------------------- + 1 file changed, 26 insertions(+), 19 deletions(-) + +--- a/arch/mips/kvm/tlb.c ++++ b/arch/mips/kvm/tlb.c +@@ -361,24 +361,31 @@ int kvm_mips_handle_mapped_seg_tlb_fault + unsigned long entryhi = 0, entrylo0 = 0, entrylo1 = 0; + struct kvm *kvm = vcpu->kvm; + pfn_t pfn0, pfn1; ++ long tlb_lo[2]; + +- if ((tlb->tlb_hi & VPN2_MASK) == 0) { +- pfn0 = 0; +- pfn1 = 0; +- } else { +- if (kvm_mips_map_page(kvm, mips3_tlbpfn_to_paddr(tlb->tlb_lo0) +- >> PAGE_SHIFT) < 0) +- return -1; +- +- if (kvm_mips_map_page(kvm, mips3_tlbpfn_to_paddr(tlb->tlb_lo1) +- >> PAGE_SHIFT) < 0) +- return -1; +- +- pfn0 = kvm->arch.guest_pmap[mips3_tlbpfn_to_paddr(tlb->tlb_lo0) +- >> PAGE_SHIFT]; +- pfn1 = kvm->arch.guest_pmap[mips3_tlbpfn_to_paddr(tlb->tlb_lo1) +- >> PAGE_SHIFT]; +- } ++ tlb_lo[0] = tlb->tlb_lo0; ++ tlb_lo[1] = tlb->tlb_lo1; ++ ++ /* ++ * The commpage address must not be mapped to anything else if the guest ++ * TLB contains entries nearby, or commpage accesses will break. ++ */ ++ if (!((tlb->tlb_hi ^ KVM_GUEST_COMMPAGE_ADDR) & ++ VPN2_MASK & (PAGE_MASK << 1))) ++ tlb_lo[(KVM_GUEST_COMMPAGE_ADDR >> PAGE_SHIFT) & 1] = 0; ++ ++ if (kvm_mips_map_page(kvm, mips3_tlbpfn_to_paddr(tlb_lo[0]) ++ >> PAGE_SHIFT) < 0) ++ return -1; ++ ++ if (kvm_mips_map_page(kvm, mips3_tlbpfn_to_paddr(tlb_lo[1]) ++ >> PAGE_SHIFT) < 0) ++ return -1; ++ ++ pfn0 = kvm->arch.guest_pmap[mips3_tlbpfn_to_paddr(tlb_lo[0]) ++ >> PAGE_SHIFT]; ++ pfn1 = kvm->arch.guest_pmap[mips3_tlbpfn_to_paddr(tlb_lo[1]) ++ >> PAGE_SHIFT]; + + if (hpa0) + *hpa0 = pfn0 << PAGE_SHIFT; +@@ -391,9 +398,9 @@ int kvm_mips_handle_mapped_seg_tlb_fault + kvm_mips_get_kernel_asid(vcpu) : + kvm_mips_get_user_asid(vcpu)); + entrylo0 = mips3_paddr_to_tlbpfn(pfn0 << PAGE_SHIFT) | (0x3 << 3) | +- (tlb->tlb_lo0 & MIPS3_PG_D) | (tlb->tlb_lo0 & MIPS3_PG_V); ++ (tlb_lo[0] & MIPS3_PG_D) | (tlb_lo[0] & MIPS3_PG_V); + entrylo1 = mips3_paddr_to_tlbpfn(pfn1 << PAGE_SHIFT) | (0x3 << 3) | +- (tlb->tlb_lo1 & MIPS3_PG_D) | (tlb->tlb_lo1 & MIPS3_PG_V); ++ (tlb_lo[1] & MIPS3_PG_D) | (tlb_lo[1] & MIPS3_PG_V); + + kvm_debug("@ %#lx tlb_lo0: 0x%08lx tlb_lo1: 0x%08lx\n", vcpu->arch.pc, + tlb->tlb_lo0, tlb->tlb_lo1); diff --git a/queue-4.4/mips-kvm-propagate-kseg0-mapped-tlb-fault-errors.patch b/queue-4.4/mips-kvm-propagate-kseg0-mapped-tlb-fault-errors.patch new file mode 100644 index 00000000000..705684791b6 --- /dev/null +++ b/queue-4.4/mips-kvm-propagate-kseg0-mapped-tlb-fault-errors.patch @@ -0,0 +1,120 @@ +From james.hogan@imgtec.com Thu Aug 18 11:45:02 2016 +From: James Hogan +Date: Thu, 18 Aug 2016 10:05:32 +0100 +Subject: [PATCH BACKPORT 3.17-4.4 4/4] MIPS: KVM: Propagate kseg0/mapped tlb fault errors +To: +Cc: James Hogan , Paolo Bonzini , Radim Krčmář , Ralf Baechle , , +Message-ID: + +From: James Hogan + +commit 9b731bcfdec4c159ad2e4312e25d69221709b96a upstream. + +Propagate errors from kvm_mips_handle_kseg0_tlb_fault() and +kvm_mips_handle_mapped_seg_tlb_fault(), usually triggering an internal +error since they normally indicate the guest accessed bad physical +memory or the commpage in an unexpected way. + +Fixes: 858dd5d45733 ("KVM/MIPS32: MMU/TLB operations for the Guest.") +Fixes: e685c689f3a8 ("KVM/MIPS32: Privileged instruction/target branch emulation.") +Signed-off-by: James Hogan +Cc: Paolo Bonzini +Cc: "Radim Krčmář" +Cc: Ralf Baechle +Cc: linux-mips@linux-mips.org +Cc: kvm@vger.kernel.org +Signed-off-by: Radim Krčmář +[james.hogan@imgtec.com: Backport to v3.17.y - v4.4.y] +Signed-off-by: James Hogan +Signed-off-by: Greg Kroah-Hartman +--- + arch/mips/kvm/emulate.c | 40 ++++++++++++++++++++++++++++------------ + arch/mips/kvm/tlb.c | 14 ++++++++++---- + 2 files changed, 38 insertions(+), 16 deletions(-) + +--- a/arch/mips/kvm/emulate.c ++++ b/arch/mips/kvm/emulate.c +@@ -1629,8 +1629,14 @@ enum emulation_result kvm_mips_emulate_c + + preempt_disable(); + if (KVM_GUEST_KSEGX(va) == KVM_GUEST_KSEG0) { +- if (kvm_mips_host_tlb_lookup(vcpu, va) < 0) +- kvm_mips_handle_kseg0_tlb_fault(va, vcpu); ++ if (kvm_mips_host_tlb_lookup(vcpu, va) < 0 && ++ kvm_mips_handle_kseg0_tlb_fault(va, vcpu)) { ++ kvm_err("%s: handling mapped kseg0 tlb fault for %lx, vcpu: %p, ASID: %#lx\n", ++ __func__, va, vcpu, read_c0_entryhi()); ++ er = EMULATE_FAIL; ++ preempt_enable(); ++ goto done; ++ } + } else if ((KVM_GUEST_KSEGX(va) < KVM_GUEST_KSEG0) || + KVM_GUEST_KSEGX(va) == KVM_GUEST_KSEG23) { + int index; +@@ -1665,14 +1671,19 @@ enum emulation_result kvm_mips_emulate_c + run, vcpu); + preempt_enable(); + goto dont_update_pc; +- } else { +- /* +- * We fault an entry from the guest tlb to the +- * shadow host TLB +- */ +- kvm_mips_handle_mapped_seg_tlb_fault(vcpu, tlb, +- NULL, +- NULL); ++ } ++ /* ++ * We fault an entry from the guest tlb to the ++ * shadow host TLB ++ */ ++ if (kvm_mips_handle_mapped_seg_tlb_fault(vcpu, tlb, ++ NULL, NULL)) { ++ kvm_err("%s: handling mapped seg tlb fault for %lx, index: %u, vcpu: %p, ASID: %#lx\n", ++ __func__, va, index, vcpu, ++ read_c0_entryhi()); ++ er = EMULATE_FAIL; ++ preempt_enable(); ++ goto done; + } + } + } else { +@@ -2633,8 +2644,13 @@ enum emulation_result kvm_mips_handle_tl + * OK we have a Guest TLB entry, now inject it into the + * shadow host TLB + */ +- kvm_mips_handle_mapped_seg_tlb_fault(vcpu, tlb, NULL, +- NULL); ++ if (kvm_mips_handle_mapped_seg_tlb_fault(vcpu, tlb, ++ NULL, NULL)) { ++ kvm_err("%s: handling mapped seg tlb fault for %lx, index: %u, vcpu: %p, ASID: %#lx\n", ++ __func__, va, index, vcpu, ++ read_c0_entryhi()); ++ er = EMULATE_FAIL; ++ } + } + } + +--- a/arch/mips/kvm/tlb.c ++++ b/arch/mips/kvm/tlb.c +@@ -808,10 +808,16 @@ uint32_t kvm_get_inst(uint32_t *opc, str + local_irq_restore(flags); + return KVM_INVALID_INST; + } +- kvm_mips_handle_mapped_seg_tlb_fault(vcpu, +- &vcpu->arch. +- guest_tlb[index], +- NULL, NULL); ++ if (kvm_mips_handle_mapped_seg_tlb_fault(vcpu, ++ &vcpu->arch.guest_tlb[index], ++ NULL, NULL)) { ++ kvm_err("%s: handling mapped seg tlb fault failed for %p, index: %u, vcpu: %p, ASID: %#lx\n", ++ __func__, opc, index, vcpu, ++ read_c0_entryhi()); ++ kvm_mips_dump_guest_tlbs(vcpu); ++ local_irq_restore(flags); ++ return KVM_INVALID_INST; ++ } + inst = *(opc); + } + local_irq_restore(flags); diff --git a/queue-4.4/series b/queue-4.4/series index 42ac9416edf..88c62ce7fca 100644 --- a/queue-4.4/series +++ b/queue-4.4/series @@ -55,3 +55,7 @@ random-properly-align-get_random_int_hash.patch random-initialize-the-non-blocking-pool-via-add_hwgenerator_randomness.patch random-print-a-warning-for-the-first-ten-uninitialized-random-users.patch random-add-interrupt-callback-to-vmbus-irq-handler.patch +mips-kvm-fix-mapped-fault-broken-commpage-handling.patch +mips-kvm-add-missing-gfn-range-check.patch +mips-kvm-fix-gfn-range-check-in-kseg0-tlb-faults.patch +mips-kvm-propagate-kseg0-mapped-tlb-fault-errors.patch