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

