mirror of
https://github.com/torvalds/linux.git
synced 2026-07-28 10:09:10 +02:00
KVM: arm64: Add fail-safe for refcounted pages in __pkvm_hyp_donate_host
A previous bug in __pkvm_init_vm error path showed that the hypervisor could leak refcounted pages, (i.e. losing access to a page while its refcount is still elevated). This poses a threat to the pKVM state machine. Address this by introducing a fail-safe in __pkvm_hyp_donate_host. Transitions are not a hot path so added security is worth the extra check. Reviewed-by: Fuad Tabba <tabba@google.com> Tested-by: Fuad Tabba <tabba@google.com> Signed-off-by: Vincent Donnefort <vdonnefort@google.com> Link: https://patch.msgid.link/20260521143626.1005660-4-vdonnefort@google.com Signed-off-by: Marc Zyngier <maz@kernel.org>
This commit is contained in:
parent
20d2753295
commit
5c30c9fc11
|
|
@ -833,6 +833,16 @@ static int __hyp_check_page_state_range(phys_addr_t phys, u64 size, enum pkvm_pa
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int __hyp_check_page_count_range(phys_addr_t phys, u64 size)
|
||||
{
|
||||
for_each_hyp_page(page, phys, size) {
|
||||
if (page->refcount)
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool guest_pte_is_poisoned(kvm_pte_t pte)
|
||||
{
|
||||
if (kvm_pte_valid(pte))
|
||||
|
|
@ -1031,7 +1041,6 @@ int __pkvm_guest_unshare_host(struct pkvm_hyp_vcpu *vcpu, u64 gfn)
|
|||
int __pkvm_host_unshare_hyp(u64 pfn)
|
||||
{
|
||||
u64 phys = hyp_pfn_to_phys(pfn);
|
||||
u64 virt = (u64)__hyp_va(phys);
|
||||
u64 size = PAGE_SIZE;
|
||||
int ret;
|
||||
|
||||
|
|
@ -1044,10 +1053,9 @@ int __pkvm_host_unshare_hyp(u64 pfn)
|
|||
ret = __hyp_check_page_state_range(phys, size, PKVM_PAGE_SHARED_BORROWED);
|
||||
if (ret)
|
||||
goto unlock;
|
||||
if (hyp_page_count((void *)virt)) {
|
||||
ret = -EBUSY;
|
||||
ret = __hyp_check_page_count_range(phys, size);
|
||||
if (ret)
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
__hyp_set_page_state_range(phys, size, PKVM_NOPAGE);
|
||||
WARN_ON(__host_set_page_state_range(phys, size, PKVM_PAGE_OWNED));
|
||||
|
|
@ -1110,6 +1118,10 @@ int __pkvm_hyp_donate_host(u64 pfn, u64 nr_pages)
|
|||
if (ret)
|
||||
goto unlock;
|
||||
|
||||
ret = __hyp_check_page_count_range(phys, size);
|
||||
if (ret)
|
||||
goto unlock;
|
||||
|
||||
__hyp_set_page_state_range(phys, size, PKVM_NOPAGE);
|
||||
WARN_ON(kvm_pgtable_hyp_unmap(&pkvm_pgtable, virt, size) != size);
|
||||
WARN_ON(host_stage2_set_owner_locked(phys, size, PKVM_ID_HOST));
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user