On 20.03.20 21:55, Sean Christopherson wrote: > Reset the LRU slot if it becomes invalid when deleting a memslot to fix > an out-of-bounds/use-after-free access when searching through memslots. > > Explicitly check for there being no used slots in search_memslots(), and > in the caller of s390's approximation variant. > > Fixes: 36947254e5f9 ("KVM: Dynamically size memslot array based on number of used slots") > Reported-by: Qian Cai <cai@xxxxxx> > Cc: Peter Xu <peterx@xxxxxxxxxx> > Signed-off-by: Sean Christopherson <sean.j.christopherson@xxxxxxxxx> > --- > arch/s390/kvm/kvm-s390.c | 3 +++ > include/linux/kvm_host.h | 3 +++ > virt/kvm/kvm_main.c | 3 +++ > 3 files changed, 9 insertions(+) > > diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c > index 807ed6d722dd..cb15fdda1fee 100644 > --- a/arch/s390/kvm/kvm-s390.c > +++ b/arch/s390/kvm/kvm-s390.c > @@ -2002,6 +2002,9 @@ static int kvm_s390_get_cmma(struct kvm *kvm, struct kvm_s390_cmma_log *args, Adding Claudio, but > struct kvm_memslots *slots = kvm_memslots(kvm); > struct kvm_memory_slot *ms; > > + if (unlikely(!slots->used_slots)) > + return 0; > + this looks sane and like the right fix. Acked-by: Christian Borntraeger <borntraeger@xxxxxxxxxx> > cur_gfn = kvm_s390_next_dirty_cmma(slots, args->start_gfn); > ms = gfn_to_memslot(kvm, cur_gfn); > args->count = 0; > diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h > index 35bc52e187a2..b19dee4ed7d9 100644 > --- a/include/linux/kvm_host.h > +++ b/include/linux/kvm_host.h > @@ -1032,6 +1032,9 @@ search_memslots(struct kvm_memslots *slots, gfn_t gfn) > int slot = atomic_read(&slots->lru_slot); > struct kvm_memory_slot *memslots = slots->memslots; > > + if (unlikely(!slots->used_slots)) > + return NULL; > + > if (gfn >= memslots[slot].base_gfn && > gfn < memslots[slot].base_gfn + memslots[slot].npages) > return &memslots[slot]; > diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c > index 28eae681859f..f744bc603c53 100644 > --- a/virt/kvm/kvm_main.c > +++ b/virt/kvm/kvm_main.c > @@ -882,6 +882,9 @@ static inline void kvm_memslot_delete(struct kvm_memslots *slots, > > slots->used_slots--; > > + if (atomic_read(&slots->lru_slot) >= slots->used_slots) > + atomic_set(&slots->lru_slot, 0); > + > for (i = slots->id_to_index[memslot->id]; i < slots->used_slots; i++) { > mslots[i] = mslots[i + 1]; > slots->id_to_index[mslots[i].id] = i; >