On Tue, Oct 25, 2022 at 03:12:18PM -0300, Jason Gunthorpe wrote: > +struct iopt_area *iopt_area_contig_init(struct iopt_area_contig_iter *iter, > + struct io_pagetable *iopt, > + unsigned long iova, > + unsigned long last_iova) > +{ > + lockdep_assert_held(&iopt->iova_rwsem); > + > + iter->cur_iova = iova; > + iter->last_iova = last_iova; > + iter->area = iopt_area_iter_first(iopt, iova, last_iova); > + if (!iter->area) > + return NULL; This one is a bit neat, syzkaller discovered that if a copy range is requested with a partial area in it then things go wrong. The contigous iterator is supposed to step over areas that completely cover a range. The little thinko is that interval_tree_iter_first(), when given a range, will return the lowest tree node that intersects the range. Thus a leading partial intersection of the range to the areas will not result in the iterator failing. Instead we want to find the area that includes the starting iova, or fail if it is not found: @@ -35,7 +35,7 @@ struct iopt_area *iopt_area_contig_init(struct iopt_area_contig_iter *iter, iter->cur_iova = iova; iter->last_iova = last_iova; - iter->area = iopt_area_iter_first(iopt, iova, last_iova); + iter->area = iopt_area_iter_first(iopt, iova, iova); if (!iter->area) return NULL; if (!iter->area->pages) { Add a test to cover as well. Jason