Skip to content

Commit e07fc9e

Browse files
Fuad TabbaMarc Zyngier
authored andcommitted
KVM: arm64: Fix page leak in user_mem_abort() on atomic fault
When a guest performs an atomic/exclusive operation on memory lacking the required attributes, user_mem_abort() injects a data abort and returns early. However, it fails to release the reference to the host page acquired via __kvm_faultin_pfn(). A malicious guest could repeatedly trigger this fault, leaking host page references and eventually causing host memory exhaustion (OOM). Fix this by consolidating the early error returns to a new out_put_page label that correctly calls kvm_release_page_unused(). Fixes: 2937aee ("KVM: arm64: Handle DABT caused by LS64* instructions on unsupported memory") Signed-off-by: Fuad Tabba <tabba@google.com> Reviewed-by: Yuan Yao <yaoyuan@linux.alibaba.com> Link: https://patch.msgid.link/20260304162222.836152-2-tabba@google.com Signed-off-by: Marc Zyngier <maz@kernel.org>
1 parent eb54fa1 commit e07fc9e

1 file changed

Lines changed: 8 additions & 5 deletions

File tree

arch/arm64/kvm/mmu.c

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1837,10 +1837,8 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
18371837
if (exec_fault && s2_force_noncacheable)
18381838
ret = -ENOEXEC;
18391839

1840-
if (ret) {
1841-
kvm_release_page_unused(page);
1842-
return ret;
1843-
}
1840+
if (ret)
1841+
goto out_put_page;
18441842

18451843
/*
18461844
* Guest performs atomic/exclusive operations on memory with unsupported
@@ -1850,7 +1848,8 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
18501848
*/
18511849
if (esr_fsc_is_excl_atomic_fault(kvm_vcpu_get_esr(vcpu))) {
18521850
kvm_inject_dabt_excl_atomic(vcpu, kvm_vcpu_get_hfar(vcpu));
1853-
return 1;
1851+
ret = 1;
1852+
goto out_put_page;
18541853
}
18551854

18561855
if (nested)
@@ -1936,6 +1935,10 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
19361935
mark_page_dirty_in_slot(kvm, memslot, gfn);
19371936

19381937
return ret != -EAGAIN ? ret : 0;
1938+
1939+
out_put_page:
1940+
kvm_release_page_unused(page);
1941+
return ret;
19391942
}
19401943

19411944
/* Resolve the access fault by making the page young again. */

0 commit comments

Comments
 (0)