From e5aebb6470384e4a934671691f209d846aca052a Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Mon, 17 Feb 2025 12:36:44 +0000 Subject: [PATCH] ANDROID: KVM: arm64: Ensure vCPU is initialised before publication When initialising a new vCPU, a pointer to the vCPU is inserted into the relevant index of 'hyp_vm->vcpus[]'. However, this is done without sufficient memory barriers, allowing a concurrent attempt to load the new vCPU to succeed with a partially initialised object. Ensure that the 'hyp_vm->vcpus[]' entry is set with release semantics and loaded with READ_ONCE() (relying on address dependency ordering) when 'hyp_vm->vcpus_lock' is not held on the vCPU loading path. Bug: 396117524 Bug: 357781595 Fixes: 7d9f60ddf77e ("ANDROID: KVM: arm64: Introduce new spinlock for hypervisor VM vCPUs[] array") Reported-by: Ben Simner Change-Id: I8c33a81fb5f0e5868781d8f28f266e94d08e8265 Signed-off-by: Will Deacon --- arch/arm64/kvm/hyp/nvhe/pkvm.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/arch/arm64/kvm/hyp/nvhe/pkvm.c b/arch/arm64/kvm/hyp/nvhe/pkvm.c index 1ff4677ca07a..73347743261e 100644 --- a/arch/arm64/kvm/hyp/nvhe/pkvm.c +++ b/arch/arm64/kvm/hyp/nvhe/pkvm.c @@ -389,7 +389,11 @@ struct pkvm_hyp_vcpu *pkvm_load_hyp_vcpu(pkvm_handle_t handle, if (!hyp_vm || hyp_vm->is_dying || hyp_vm->kvm.created_vcpus <= vcpu_idx) goto unlock; - hyp_vcpu = hyp_vm->vcpus[vcpu_idx]; + /* + * Synchronise with concurrent vCPU initialisation by relying on + * dependency ordering from the vCPU pointer. + */ + hyp_vcpu = READ_ONCE(hyp_vm->vcpus[vcpu_idx]); if (!hyp_vcpu) goto unlock; @@ -881,7 +885,11 @@ int __pkvm_init_vcpu(pkvm_handle_t handle, struct kvm_vcpu *host_vcpu) goto unlock_vcpus; } - hyp_vm->vcpus[idx] = hyp_vcpu; + /* + * Ensure the hyp_vcpu is initialised before publishing it to + * the vCPU-load path via 'hyp_vm->vcpus[]'. + */ + smp_store_release(&hyp_vm->vcpus[idx], hyp_vcpu); unlock_vcpus: hyp_spin_unlock(&hyp_vm->vcpus_lock);