Skip to content

Commit 0e02219

Browse files
Quentin PerretMarc Zyngier
authored andcommitted
KVM: arm64: Don't free hyp pages with pKVM on GICv2
Marc reported that enabling protected mode on a device with GICv2 doesn't fail gracefully as one would expect, and leads to a host kernel crash. As it turns out, the first half of pKVM init happens before the vgic probe, and so by the time we find out we have a GICv2 we're already committed to keeping the pKVM vectors installed at EL2 -- pKVM rejects stub HVCs for obvious security reasons. However, the error path on KVM init leads to teardown_hyp_mode() which unconditionally frees hypervisor allocations (including the EL2 stacks and per-cpu pages) under the assumption that a previous cpu_hyp_uninit() execution has reset the vectors back to the stubs, which is false with pKVM. Interestingly, host stage-2 protection is not enabled yet at this point, so this use-after-free may go unnoticed for a while. The issue becomes more obvious after the finalize_pkvm() call. Fix this by keeping track of the CPUs on which pKVM is initialized in the kvm_hyp_initialized per-cpu variable, and use it from teardown_hyp_mode() to skip freeing pages that are in fact used. Fixes: a770ee8 ("KVM: arm64: pkvm: Disable GICv2 support") Reported-by: Marc Zyngier <[email protected]> Signed-off-by: Quentin Perret <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Marc Zyngier <[email protected]>
1 parent 9a2b941 commit 0e02219

File tree

1 file changed

+4
-1
lines changed

1 file changed

+4
-1
lines changed

arch/arm64/kvm/arm.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2129,7 +2129,7 @@ static void cpu_hyp_init(void *discard)
21292129

21302130
static void cpu_hyp_uninit(void *discard)
21312131
{
2132-
if (__this_cpu_read(kvm_hyp_initialized)) {
2132+
if (!is_protected_kvm_enabled() && __this_cpu_read(kvm_hyp_initialized)) {
21332133
cpu_hyp_reset();
21342134
__this_cpu_write(kvm_hyp_initialized, 0);
21352135
}
@@ -2345,6 +2345,9 @@ static void __init teardown_hyp_mode(void)
23452345

23462346
free_hyp_pgds();
23472347
for_each_possible_cpu(cpu) {
2348+
if (per_cpu(kvm_hyp_initialized, cpu))
2349+
continue;
2350+
23482351
free_pages(per_cpu(kvm_arm_hyp_stack_base, cpu), NVHE_STACK_SHIFT - PAGE_SHIFT);
23492352

23502353
if (!kvm_nvhe_sym(kvm_arm_hyp_percpu_base)[cpu])

0 commit comments

Comments
 (0)