Skip to content

Commit 0664dc7

Browse files
committed
KVM: Verify there's at least one online vCPU when iterating over all vCPUs
Explicitly check that there is at least online vCPU before iterating over all vCPUs. Because the max index is an unsigned long, passing "0 - 1" in the online_vcpus==0 case results in xa_for_each_range() using an unlimited max, i.e. allows it to access vCPU0 when it shouldn't. This will allow KVM to safely _erase_ from vcpu_array if the last stages of vCPU creation fail, i.e. without generating a use-after-free if a different task happens to be concurrently iterating over all vCPUs. Note, because xa_for_each_range() is a macro, kvm_for_each_vcpu() subtly reloads online_vcpus after each iteration, i.e. adding an extra load doesn't meaningfully impact the total cost of iterating over all vCPUs. And because online_vcpus is never decremented, there is no risk of a reload triggering a walk of the entire xarray. Cc: Will Deacon <will@kernel.org> Cc: Michal Luczaj <mhal@rbox.co> Acked-by: Will Deacon <will@kernel.org> Link: https://lore.kernel.org/r/20241009150455.1057573-3-seanjc@google.com Signed-off-by: Sean Christopherson <seanjc@google.com>
1 parent 1e7381f commit 0664dc7

File tree

1 file changed

+4
-3
lines changed

1 file changed

+4
-3
lines changed

include/linux/kvm_host.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -979,9 +979,10 @@ static inline struct kvm_vcpu *kvm_get_vcpu(struct kvm *kvm, int i)
979979
return xa_load(&kvm->vcpu_array, i);
980980
}
981981

982-
#define kvm_for_each_vcpu(idx, vcpup, kvm) \
983-
xa_for_each_range(&kvm->vcpu_array, idx, vcpup, 0, \
984-
(atomic_read(&kvm->online_vcpus) - 1))
982+
#define kvm_for_each_vcpu(idx, vcpup, kvm) \
983+
if (atomic_read(&kvm->online_vcpus)) \
984+
xa_for_each_range(&kvm->vcpu_array, idx, vcpup, 0, \
985+
(atomic_read(&kvm->online_vcpus) - 1))
985986

986987
static inline struct kvm_vcpu *kvm_get_vcpu_by_id(struct kvm *kvm, int id)
987988
{

0 commit comments

Comments
 (0)