From 1d36cbcba44e0b0eb434541eb89518d4c1b5fdb3 Mon Sep 17 00:00:00 2001 From: Quentin Perret Date: Mon, 20 Jan 2025 16:12:57 +0000 Subject: [PATCH] ANDROID: BACKPORT: KVM: arm64: Handle races gracefully in pkvm_relax_perms() We may encounter a race between MMU notifiers and the perm fault path in KVM where the faulting PFN is gone from the maple tree by the time we check it in pkvm_relax_perms(). Although that race is benign, it currently causes the vCPU to exit with -EFAULT, which is generally fatal for the guest. To avoid this problem, let's return -EAGAIN instead and give the guest another chance. BACKPORT: adapted from android15-6.6 code which had a variation of the same bug. Bug: 389901612 Change-Id: Ie98e1162a558126c8c6e83f0621460966c09b7ad Signed-off-by: Quentin Perret --- arch/arm64/kvm/mmu.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c index 05997453905b..150f74bb192a 100644 --- a/arch/arm64/kvm/mmu.c +++ b/arch/arm64/kvm/mmu.c @@ -1654,18 +1654,12 @@ static int pkvm_relax_perms(struct kvm *kvm, u64 pfn, u64 gfn, struct kvm_pinned_page *ppage; int ret; + WARN_ON(kvm_vm_is_protected(kvm)); ppage = find_ppage(kvm, gfn << PAGE_SHIFT); - - /* - * In the rare case that we raced with an MMU notifier, the page might - * already be gone by now, so let's just try again. - */ - if (!ppage) - return kvm->arch.pkvm.enabled ? -EAGAIN : -EFAULT; - - if (page_to_pfn(ppage->page) != pfn) - return -EFAULT; + /* Try again if we raced with an MMU notifier. */ + if (!ppage || page_to_pfn(ppage->page) != pfn) + return -EAGAIN; if (!folio_test_swapbacked(page_folio(ppage->page))) return -EIO;