udmabuf_create() derives the number of pages to allocate directly from
the size supplied by userspace, bounded only by the size_limit_mb module
parameter. Since commit 44e9eb5a7621 ("dma-buf/udmabuf: Disable the size
limit by default") that parameter defaults to INT_MAX, which puts the
page count limit at roughly 5.5e11 pages, i.e. no limit in practice.init_udmabuf() then asks kvmalloc_objs() for pgcnt * sizeof(struct page *) bytes. __kvmalloc_node_noprof() refuses any request larger than INT_MAX and splats WARN_ON_ONCE(!(flags & __GFP_NOWARN)) on its way out, while kvmalloc_objs() defaults to a plain GFP_KERNEL. A single UDMABUF_CREATE against /dev/udmabuf with a sufficiently large size is therefore all it takes to trigger: ------------[ cut here ]------------ WARNING: mm/slub.c:7022 at __kvmalloc_node_noprof+0x412/0x5a0 Call Trace: udmabuf_create+0x11f/0x540 udmabuf_ioctl+0xf1/0x190 __x64_sys_ioctl+0x91/0xe0 do_syscall_64+0xdd/0x4a0 The size is entirely userspace-controlled and allocation failure is already handled by returning -ENOMEM to the caller, so this is not a condition the kernel needs to complain about. Pass __GFP_NOWARN and let the existing error path do its job. Note that capping the limit instead would change the error reported to userspace from -ENOMEM to -EINVAL and would reintroduce a fixed ceiling that the above commit deliberately removed, so __GFP_NOWARN seems the more faithful fix. Reported-by: [email protected] Closes: https://syzkaller.appspot.com/bug?extid=bfeed181d1ce9ec87a8f Fixes: 44e9eb5a7621 ("dma-buf/udmabuf: Disable the size limit by default") Signed-off-by: Priyanka Mani <[email protected]> --- drivers/dma-buf/udmabuf.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/dma-buf/udmabuf.c b/drivers/dma-buf/udmabuf.c index df6dd0046242..127369e502a3 100644 --- a/drivers/dma-buf/udmabuf.c +++ b/drivers/dma-buf/udmabuf.c @@ -190,11 +190,13 @@ static void unpin_all_folios(struct udmabuf *ubuf) static __always_inline int init_udmabuf(struct udmabuf *ubuf, pgoff_t pgcnt) { - ubuf->pages = kvmalloc_objs(*ubuf->pages, pgcnt); + ubuf->pages = kvmalloc_objs(*ubuf->pages, pgcnt, + GFP_KERNEL | __GFP_NOWARN); if (!ubuf->pages) return -ENOMEM; - ubuf->pinned_folios = kvmalloc_objs(*ubuf->pinned_folios, pgcnt); + ubuf->pinned_folios = kvmalloc_objs(*ubuf->pinned_folios, pgcnt, + GFP_KERNEL | __GFP_NOWARN); if (!ubuf->pinned_folios) return -ENOMEM; -- 2.43.0
