mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2024-12-28 16:52:18 +00:00
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>
This commit is contained in:
parent
1e7381f361
commit
0664dc74e9
@ -979,9 +979,10 @@ static inline struct kvm_vcpu *kvm_get_vcpu(struct kvm *kvm, int i)
|
||||
return xa_load(&kvm->vcpu_array, i);
|
||||
}
|
||||
|
||||
#define kvm_for_each_vcpu(idx, vcpup, kvm) \
|
||||
xa_for_each_range(&kvm->vcpu_array, idx, vcpup, 0, \
|
||||
(atomic_read(&kvm->online_vcpus) - 1))
|
||||
#define kvm_for_each_vcpu(idx, vcpup, kvm) \
|
||||
if (atomic_read(&kvm->online_vcpus)) \
|
||||
xa_for_each_range(&kvm->vcpu_array, idx, vcpup, 0, \
|
||||
(atomic_read(&kvm->online_vcpus) - 1))
|
||||
|
||||
static inline struct kvm_vcpu *kvm_get_vcpu_by_id(struct kvm *kvm, int id)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user