Quoting Nico Boehr (2023-03-24 15:54:23) > The KVM_S390_GET_CMMA_BITS ioctl may return incorrect values when userspace > specifies a start_gfn outside of memslots. > > This can occur when a VM has multiple memslots with a hole in between: > > +-----+----------+--------+--------+ > | ... | Slot N-1 | <hole> | Slot N | > +-----+----------+--------+--------+ > ^ ^ ^ ^ > | | | | > GFN A A+B | | > A+B+C | > A+B+C+D > > When userspace specifies a GFN in [A+B, A+B+C), it would expect to get the > CMMA values of the first dirty page in Slot N. However, userspace may get a > start_gfn of A+B+C+D with a count of 0, hence completely skipping over any > dirty pages in slot N. > > The error is in kvm_s390_next_dirty_cmma(), which assumes > gfn_to_memslot_approx() will return the memslot _below_ the specified GFN > when the specified GFN lies outside a memslot. In reality it may return > either the memslot below or above the specified GFN. > > When a memslot above the specified GFN is returned this happens: > > - ofs is calculated, but since the memslot's base_gfn is larger than the > specified cur_gfn, ofs will underflow to a huge number. > - ofs is passed to find_next_bit(). Since ofs will exceed the memslot's > number of pages, the number of pages in the memslot is returned, > completely skipping over all bits in the memslot userspace would be > interested in. > > Fix this by resetting ofs to zero when a memslot _above_ cur_gfn is > returned (cur_gfn < ms->base_gfn). > > Signed-off-by: Nico Boehr <nrb@xxxxxxxxxxxxx> > Reviewed-by: Claudio Imbrenda <imbrenda@xxxxxxxxxxxxx> Since Janosch asked for it, I would suggest the following Fixes tag: Fixes: afdad61615cc ("KVM: s390: Fix storage attributes migration with memory slots")