]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
io_uring/memmap: bound io_pin_pages() by page array byte size
authorDeepanshu Kartikey <kartikey406@gmail.com>
Sun, 21 Jun 2026 01:29:33 +0000 (06:59 +0530)
committerJens Axboe <axboe@kernel.dk>
Mon, 22 Jun 2026 21:12:54 +0000 (15:12 -0600)
io_pin_pages() checks that nr_pages does not exceed INT_MAX, then
allocates a struct page * array of nr_pages entries. kvmalloc() limits
allocations to INT_MAX bytes, but the check counts pages, not bytes.
On 64-bit each entry is 8 bytes, so the array hits the INT_MAX byte
limit at INT_MAX / sizeof(struct page *) pages, well before the page
count check fires.

Since commit b4e41050b212 ("io_uring/rsrc: raise registered buffer 1GB
limit") raised the per-buffer cap to 1TB, a buffer near that cap maps
~2^28 pages, making the array allocation exceed INT_MAX bytes. This
passes the page count check, reaches kvmalloc(), and triggers the
WARN_ON_ONCE() for oversized allocations in __kvmalloc_node_noprof().

Check nr_pages against INT_MAX / sizeof(struct page *) so the buffer is
rejected with -EOVERFLOW before the allocation is attempted.

Reported-by: syzbot+f99b00a963915b6b52c6@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=f99b00a963915b6b52c6
Fixes: b4e41050b212 ("io_uring/rsrc: raise registered buffer 1GB limit")
Tested-by: syzbot+f99b00a963915b6b52c6@syzkaller.appspotmail.com
Signed-off-by: Deepanshu Kartikey <kartikey406@gmail.com>
Reviewed-by: Gabriel Krisman Bertazi <krisman@suse.de>
Link: https://patch.msgid.link/20260621012933.50571-1-kartikey406@gmail.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
io_uring/memmap.c

index 4f9b439319c466f1c365d05cb2e06af48570cdc5..da1f6c5d07f8a092ebbfbd5d2c716a497828557d 100644 (file)
@@ -53,7 +53,7 @@ struct page **io_pin_pages(unsigned long uaddr, unsigned long len, int *npages)
        nr_pages = end - start;
        if (WARN_ON_ONCE(!nr_pages))
                return ERR_PTR(-EINVAL);
-       if (WARN_ON_ONCE(nr_pages > INT_MAX))
+       if (nr_pages > INT_MAX / sizeof(struct page *))
                return ERR_PTR(-EOVERFLOW);
 
        pages = kvmalloc_objs(struct page *, nr_pages, GFP_KERNEL_ACCOUNT);