From: Greg Kroah-Hartman Date: Tue, 23 May 2017 17:22:12 +0000 (+0200) Subject: 4.11-stable patches X-Git-Tag: v3.18.55~17 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=6e3b5ddfb5ff47e6fe3a0a40a9e4bd195d6cb5c2;p=thirdparty%2Fkernel%2Fstable-queue.git 4.11-stable patches added patches: kvm-arm-arm64-fix-race-in-resetting-stage2-pgd.patch --- diff --git a/queue-4.11/kvm-arm-arm64-fix-race-in-resetting-stage2-pgd.patch b/queue-4.11/kvm-arm-arm64-fix-race-in-resetting-stage2-pgd.patch new file mode 100644 index 00000000000..25dbe0f2670 --- /dev/null +++ b/queue-4.11/kvm-arm-arm64-fix-race-in-resetting-stage2-pgd.patch @@ -0,0 +1,108 @@ +From 6c0d706b563af732adb094c5bf807437e8963e84 Mon Sep 17 00:00:00 2001 +From: Suzuki K Poulose +Date: Wed, 3 May 2017 15:17:51 +0100 +Subject: kvm: arm/arm64: Fix race in resetting stage2 PGD +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Suzuki K Poulose + +commit 6c0d706b563af732adb094c5bf807437e8963e84 upstream. + +In kvm_free_stage2_pgd() we check the stage2 PGD before holding +the lock and proceed to take the lock if it is valid. And we unmap +the page tables, followed by releasing the lock. We reset the PGD +only after dropping this lock, which could cause a race condition +where another thread waiting on or even holding the lock, could +potentially see that the PGD is still valid and proceed to perform +a stage2 operation and later encounter a NULL PGD. + +[223090.242280] Unable to handle kernel NULL pointer dereference at +virtual address 00000040 +[223090.262330] PC is at unmap_stage2_range+0x8c/0x428 +[223090.262332] LR is at kvm_unmap_hva_handler+0x2c/0x3c +[223090.262531] Call trace: +[223090.262533] [] unmap_stage2_range+0x8c/0x428 +[223090.262535] [] kvm_unmap_hva_handler+0x2c/0x3c +[223090.262537] [] handle_hva_to_gpa+0xb0/0x104 +[223090.262539] [] kvm_unmap_hva+0x5c/0xbc +[223090.262543] [] +kvm_mmu_notifier_invalidate_page+0x50/0x8c +[223090.262547] [] +__mmu_notifier_invalidate_page+0x5c/0x84 +[223090.262551] [] try_to_unmap_one+0x1d0/0x4a0 +[223090.262553] [] rmap_walk+0x1cc/0x2e0 +[223090.262555] [] try_to_unmap+0x74/0xa4 +[223090.262557] [] migrate_pages+0x31c/0x5ac +[223090.262561] [] compact_zone+0x3fc/0x7ac +[223090.262563] [] compact_zone_order+0x94/0xb0 +[223090.262564] [] try_to_compact_pages+0x108/0x290 +[223090.262569] [] __alloc_pages_direct_compact+0x70/0x1ac +[223090.262571] [] __alloc_pages_nodemask+0x434/0x9f4 +[223090.262572] [] alloc_pages_vma+0x230/0x254 +[223090.262574] [] do_huge_pmd_anonymous_page+0x114/0x538 +[223090.262576] [] handle_mm_fault+0xd40/0x17a4 +[223090.262577] [] __get_user_pages+0x12c/0x36c +[223090.262578] [] get_user_pages_unlocked+0xa4/0x1b8 +[223090.262579] [] __gfn_to_pfn_memslot+0x280/0x31c +[223090.262580] [] gfn_to_pfn_prot+0x4c/0x5c +[223090.262582] [] kvm_handle_guest_abort+0x240/0x774 +[223090.262584] [] handle_exit+0x11c/0x1ac +[223090.262586] [] kvm_arch_vcpu_ioctl_run+0x31c/0x648 +[223090.262587] [] kvm_vcpu_ioctl+0x378/0x768 +[223090.262590] [] do_vfs_ioctl+0x324/0x5a4 +[223090.262591] [] SyS_ioctl+0x90/0xa4 +[223090.262595] [] el0_svc_naked+0x38/0x3c + +This patch moves the stage2 PGD manipulation under the lock. + +Reported-by: Alexander Graf +Cc: Mark Rutland +Cc: Marc Zyngier +Cc: Paolo Bonzini +Cc: Radim Krčmář +Reviewed-by: Christoffer Dall +Reviewed-by: Marc Zyngier +Signed-off-by: Suzuki K Poulose +Signed-off-by: Christoffer Dall +Signed-off-by: Greg Kroah-Hartman + + +--- + arch/arm/kvm/mmu.c | 16 ++++++++-------- + 1 file changed, 8 insertions(+), 8 deletions(-) + +--- a/arch/arm/kvm/mmu.c ++++ b/arch/arm/kvm/mmu.c +@@ -829,22 +829,22 @@ void stage2_unmap_vm(struct kvm *kvm) + * Walks the level-1 page table pointed to by kvm->arch.pgd and frees all + * underlying level-2 and level-3 tables before freeing the actual level-1 table + * and setting the struct pointer to NULL. +- * +- * Note we don't need locking here as this is only called when the VM is +- * destroyed, which can only be done once. + */ + void kvm_free_stage2_pgd(struct kvm *kvm) + { +- if (kvm->arch.pgd == NULL) +- return; ++ void *pgd = NULL; + + spin_lock(&kvm->mmu_lock); +- unmap_stage2_range(kvm, 0, KVM_PHYS_SIZE); ++ if (kvm->arch.pgd) { ++ unmap_stage2_range(kvm, 0, KVM_PHYS_SIZE); ++ pgd = kvm->arch.pgd; ++ kvm->arch.pgd = NULL; ++ } + spin_unlock(&kvm->mmu_lock); + + /* Free the HW pgd, one page at a time */ +- free_pages_exact(kvm->arch.pgd, S2_PGD_SIZE); +- kvm->arch.pgd = NULL; ++ if (pgd) ++ free_pages_exact(pgd, S2_PGD_SIZE); + } + + static pud_t *stage2_get_pud(struct kvm *kvm, struct kvm_mmu_memory_cache *cache, diff --git a/queue-4.11/series b/queue-4.11/series index 7b12e4be00b..784ec67d02f 100644 --- a/queue-4.11/series +++ b/queue-4.11/series @@ -163,3 +163,4 @@ uwb-fix-device-quirk-on-big-endian-hosts.patch genirq-fix-chained-interrupt-data-ordering.patch nvme-unmap-cmb-and-remove-sysfs-file-in-reset-path.patch mips-loongson-3-select-mips_l1_cache_shift_6.patch +kvm-arm-arm64-fix-race-in-resetting-stage2-pgd.patch