From: tabba@google.com Date: Fri, 29 May 2026 12:17:55 +0000 (+0100) Subject: KVM: arm64: Roll back partial shares on kvm_share_hyp() failure X-Git-Url: http://git.ipfire.org/gitweb/?a=commitdiff_plain;h=f4411f9308c0187c211577b7c489545b0bdae455;p=thirdparty%2Fkernel%2Flinux.git KVM: arm64: Roll back partial shares on kvm_share_hyp() failure kvm_share_hyp() shares a range one page at a time. If share_pfn_hyp() fails partway through, the pages already shared by this call are left shared, while the caller treats the whole range as failed and never unshares them. Unshare those pages before returning the error. If an unshare itself fails the page is leaked: it stays shared with the hypervisor and is no longer reusable for pKVM, but no isolation guarantee is broken, so WARN and continue. Not expected in practice. Fixes: a83e2191b7f1 ("KVM: arm64: pkvm: Refcount the pages shared with EL2") Suggested-by: Vincent Donnefort Signed-off-by: Fuad Tabba Reviewed-by: Vincent Donnefort Link: https://patch.msgid.link/20260529121755.2923500-4-tabba@google.com Signed-off-by: Marc Zyngier --- diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c index c82d4ececab8..f18b287c98b6 100644 --- a/arch/arm64/kvm/mmu.c +++ b/arch/arm64/kvm/mmu.c @@ -544,8 +544,8 @@ unlock: int kvm_share_hyp(void *from, void *to) { phys_addr_t start, end, cur; + int ret = 0; u64 pfn; - int ret; if (is_kernel_in_hyp_mode()) return 0; @@ -567,10 +567,24 @@ int kvm_share_hyp(void *from, void *to) pfn = __phys_to_pfn(cur); ret = share_pfn_hyp(pfn); if (ret) - return ret; + break; } - return 0; + if (!ret) + return 0; + + /* + * Roll back the pages shared by this call. A failed unshare leaks + * the page (it stays shared with the hypervisor and is no longer + * reusable for pKVM) but breaks no isolation guarantee, so warn and + * continue. Not expected in practice. + */ + for (end = cur, cur = start; cur < end; cur += PAGE_SIZE) { + pfn = __phys_to_pfn(cur); + WARN_ON(unshare_pfn_hyp(pfn)); + } + + return ret; } void kvm_unshare_hyp(void *from, void *to)