From ee389019c509f25fe77a81a0c2923b8dd8736e45 Mon Sep 17 00:00:00 2001 From: Afonso Oliveira Date: Mon, 21 Sep 2026 11:16:16 +0100 Subject: [PATCH 1/2] media: intel/ipu7: prevent userptr page-array size overflow The userptr length reaches the page-array allocation without range checks. The pointer-array byte count is narrowed into an int, so a request for 0x20000001 pages on x86-64 allocates only eight bytes while GUP still receives the original count. Validate the address interval before calculating its page count, reject counts that cannot be passed to GUP, and use kvcalloc to check the array-size multiplication. Preserve the existing pinning flags, VMA checks and partial-pin cleanup without adding an arbitrary byte-length cap. Signed-off-by: Afonso Oliveira --- drivers/media/pci/intel/ipu7/psys/ipu-psys.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/drivers/media/pci/intel/ipu7/psys/ipu-psys.c b/drivers/media/pci/intel/ipu7/psys/ipu-psys.c index ce16e4c..03fac83 100644 --- a/drivers/media/pci/intel/ipu7/psys/ipu-psys.c +++ b/drivers/media/pci/intel/ipu7/psys/ipu-psys.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -50,18 +51,25 @@ static DEFINE_MUTEX(ipu7_psys_mutex); static int ipu7_psys_get_userpages(struct ipu7_dma_buf_attach *attach) { struct vm_area_struct *vma; - unsigned long start, end; - int npages, array_size; + unsigned long start, last, count; + int npages; struct page **pages; struct sg_table *sgt; int ret = -ENOMEM; int nr = 0; u32 flags; + if (!attach->len || attach->len > ULONG_MAX) + return -EINVAL; + start = (unsigned long)attach->userptr; - end = PAGE_ALIGN(start + attach->len); - npages = PHYS_PFN(end - (start & PAGE_MASK)); - array_size = npages * sizeof(struct page *); + if (check_add_overflow(start, (unsigned long)attach->len - 1, &last)) + return -EOVERFLOW; + + count = (last >> PAGE_SHIFT) - (start >> PAGE_SHIFT) + 1; + if (count > INT_MAX) + return -E2BIG; + npages = count; sgt = kzalloc(sizeof(*sgt), GFP_KERNEL); if (!sgt) @@ -69,7 +77,7 @@ static int ipu7_psys_get_userpages(struct ipu7_dma_buf_attach *attach) WARN_ON_ONCE(attach->npages); - pages = kvzalloc(array_size, GFP_KERNEL); + pages = kvcalloc(npages, sizeof(*pages), GFP_KERNEL); if (!pages) goto free_sgt; From d2fbb40a4e6e3c95de5fb1a3bbf8be2a8497bc9b Mon Sep 17 00:00:00 2001 From: Afonso Oliveira Date: Mon, 21 Sep 2026 11:16:16 +0100 Subject: [PATCH 2/2] media: intel/ipu7: clear attachment state after map failure A failed dma_buf_attach leaves an error pointer in db_attach. A later map or vmap failure instead detaches the attachment but leaves the freed pointer in the surviving exported userptr buffer. The dma-buf release callback subsequently dereferences that pointer. Clear the failed attachment and mapping state at the shared failure label, before dropping the local dma-buf reference. Preserve the existing detach, list removal and imported-buffer ownership rules. Signed-off-by: Afonso Oliveira --- drivers/media/pci/intel/ipu7/psys/ipu-psys.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/media/pci/intel/ipu7/psys/ipu-psys.c b/drivers/media/pci/intel/ipu7/psys/ipu-psys.c index 03fac83..f6f634d 100644 --- a/drivers/media/pci/intel/ipu7/psys/ipu-psys.c +++ b/drivers/media/pci/intel/ipu7/psys/ipu-psys.c @@ -792,6 +792,9 @@ static int ipu7_psys_mapbuf_locked(int fd, struct ipu7_psys_fh *fh, dma_buf_detach(kbuf->dbuf, kbuf->db_attach); attach_fail: + kbuf->db_attach = NULL; + kbuf->sgt = NULL; + kbuf->dbuf = NULL; list_del(&kbuf->list); if (!kbuf->userptr) kfree(kbuf);