On Wed, Jun 24, 2026 at 01:53:38PM -0400, Michael S. Tsirkin wrote: > You should add "on 32 bit systems" - I do not see how it can > overflow on 64 bit.
Right, the overflow I was trying to cover is the unsigned long page-count calculation on 32-bit systems, where size can be wider than unsigned long and the page offset is added before PFN_UP(). I should have made that scope explicit in the changelog. > I don't see how this can happen at all - pinned_vm is in units of pages. Agreed, that part is not needed for this fix. I'll drop the memlock check change and send a v2 with the changelog clarified to say this is for 32-bit systems. Thanks, Yousef On Wed, 24 Jun 2026 15:53:38 -0400, "Michael S. Tsirkin" <[email protected]> wrote: > On Wed, Jun 24, 2026 at 09:06:53PM +0200, Yousef Alhouseen wrote: > > vhost_vdpa_pa_map() adds the IOVA page offset to the user-controlled map > > size before computing the number of pages to pin. If that addition wraps, > > the code can pin and map fewer pages than the requested IOTLB range. > > > > Reject sizes that overflow the page-count calculation. > > You should add "on 32 bit systems" - I do not see how it can > overflow on 64 bit. > > > Also make the > > memlock check subtraction-based so a large page count cannot wrap the > > pinned page total. > > I don't see how this can happen at all - pinned_vm is in units of pages. > > > Signed-off-by: Yousef Alhouseen <[email protected]> > > --- > > drivers/vhost/vdpa.c | 12 ++++++++++-- > > 1 file changed, 10 insertions(+), 2 deletions(-) > > > > diff --git a/drivers/vhost/vdpa.c b/drivers/vhost/vdpa.c > > index ac55275fa..090cb8693 100644 > > --- a/drivers/vhost/vdpa.c > > +++ b/drivers/vhost/vdpa.c > > @@ -1102,6 +1102,8 @@ static int vhost_vdpa_pa_map(struct vhost_vdpa *v, > > unsigned int gup_flags = FOLL_LONGTERM; > > unsigned long npages, cur_base, map_pfn, last_pfn = 0; > > unsigned long lock_limit, sz2pin, nchunks, i; > > + unsigned long page_offset; > > + u64 pinned_vm; > > u64 start = iova; > > long pinned; > > int ret = 0; > > @@ -1114,7 +1116,12 @@ static int vhost_vdpa_pa_map(struct vhost_vdpa *v, > > if (perm & VHOST_ACCESS_WO) > > gup_flags |= FOLL_WRITE; > > > > - npages = PFN_UP(size + (iova & ~PAGE_MASK)); > > + page_offset = iova & ~PAGE_MASK; > > + if (size > ULONG_MAX - page_offset) { > > + ret = -EINVAL; > > + goto free; > > + } > > + npages = PFN_UP(size + page_offset); > > if (!npages) { > > ret = -EINVAL; > > goto free; > > @@ -1123,7 +1130,8 @@ static int vhost_vdpa_pa_map(struct vhost_vdpa *v, > > mmap_read_lock(dev->mm); > > > > lock_limit = PFN_DOWN(rlimit(RLIMIT_MEMLOCK)); > > - if (npages + atomic64_read(&dev->mm->pinned_vm) > lock_limit) { > > + pinned_vm = atomic64_read(&dev->mm->pinned_vm); > > + if (npages > lock_limit || pinned_vm > lock_limit - npages) { > > ret = -ENOMEM; > > goto unlock; > > } > > -- > > 2.54.0

