* [PATCH] vhost/vdpa: reject overflowing PA map page counts
@ 2026-06-24 19:06 Yousef Alhouseen
2026-06-24 19:53 ` Michael S. Tsirkin
0 siblings, 1 reply; 2+ messages in thread
From: Yousef Alhouseen @ 2026-06-24 19:06 UTC (permalink / raw)
To: Michael S . Tsirkin, Jason Wang, Eugenio Pérez
Cc: kvm, virtualization, netdev, linux-kernel, Yousef Alhouseen
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. Also make the
memlock check subtraction-based so a large page count cannot wrap the
pinned page total.
Signed-off-by: Yousef Alhouseen <alhouseenyousef@gmail.com>
---
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
^ permalink raw reply related [flat|nested] 2+ messages in thread* Re: [PATCH] vhost/vdpa: reject overflowing PA map page counts
2026-06-24 19:06 [PATCH] vhost/vdpa: reject overflowing PA map page counts Yousef Alhouseen
@ 2026-06-24 19:53 ` Michael S. Tsirkin
0 siblings, 0 replies; 2+ messages in thread
From: Michael S. Tsirkin @ 2026-06-24 19:53 UTC (permalink / raw)
To: Yousef Alhouseen
Cc: Jason Wang, Eugenio Pérez, kvm, virtualization, netdev,
linux-kernel
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 <alhouseenyousef@gmail.com>
> ---
> 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
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-06-24 19:53 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-24 19:06 [PATCH] vhost/vdpa: reject overflowing PA map page counts Yousef Alhouseen
2026-06-24 19:53 ` Michael S. Tsirkin
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox