This is an automatic generated email to let you know that the following patch 
were queued:

Subject: media: pci: ivtv: Add check for DMA map result
Author:  Mikhail Kobuk <m.ko...@ispras.ru>
Date:    Thu Mar 28 02:32:23 2024 +0300

In case DMA fails, 'dma->SG_length' is 0. This value is later used to
access 'dma->SGarray[dma->SG_length - 1]', which will cause out of
bounds access.

Add check to return early on invalid value. Adjust warnings accordingly.

Found by Linux Verification Center (linuxtesting.org) with SVACE.

Fixes: 1932dc2f4cf6 ("media: pci/ivtv: switch from 'pci_' to 'dma_' API")
Signed-off-by: Mikhail Kobuk <m.ko...@ispras.ru>
Signed-off-by: Hans Verkuil <hverkuil-ci...@xs4all.nl>

 drivers/media/pci/ivtv/ivtv-udma.c | 8 ++++++++
 drivers/media/pci/ivtv/ivtv-yuv.c  | 6 ++++++
 drivers/media/pci/ivtv/ivtvfb.c    | 6 +++---
 3 files changed, 17 insertions(+), 3 deletions(-)

---

diff --git a/drivers/media/pci/ivtv/ivtv-udma.c 
b/drivers/media/pci/ivtv/ivtv-udma.c
index 99b9f55ca829..f467a00492f4 100644
--- a/drivers/media/pci/ivtv/ivtv-udma.c
+++ b/drivers/media/pci/ivtv/ivtv-udma.c
@@ -131,6 +131,8 @@ int ivtv_udma_setup(struct ivtv *itv, unsigned long 
ivtv_dest_addr,
 
        /* Fill SG List with new values */
        if (ivtv_udma_fill_sg_list(dma, &user_dma, 0) < 0) {
+               IVTV_DEBUG_WARN("%s: could not allocate bounce buffers for 
highmem userspace buffers\n",
+                               __func__);
                unpin_user_pages(dma->map, dma->page_count);
                dma->page_count = 0;
                return -ENOMEM;
@@ -139,6 +141,12 @@ int ivtv_udma_setup(struct ivtv *itv, unsigned long 
ivtv_dest_addr,
        /* Map SG List */
        dma->SG_length = dma_map_sg(&itv->pdev->dev, dma->SGlist,
                                    dma->page_count, DMA_TO_DEVICE);
+       if (!dma->SG_length) {
+               IVTV_DEBUG_WARN("%s: DMA map error, SG_length is 0\n", 
__func__);
+               unpin_user_pages(dma->map, dma->page_count);
+               dma->page_count = 0;
+               return -EINVAL;
+       }
 
        /* Fill SG Array with new values */
        ivtv_udma_fill_sg_array (dma, ivtv_dest_addr, 0, -1);
diff --git a/drivers/media/pci/ivtv/ivtv-yuv.c 
b/drivers/media/pci/ivtv/ivtv-yuv.c
index 582146f8d70d..2d9274537725 100644
--- a/drivers/media/pci/ivtv/ivtv-yuv.c
+++ b/drivers/media/pci/ivtv/ivtv-yuv.c
@@ -114,6 +114,12 @@ static int ivtv_yuv_prep_user_dma(struct ivtv *itv, struct 
ivtv_user_dma *dma,
        }
        dma->SG_length = dma_map_sg(&itv->pdev->dev, dma->SGlist,
                                    dma->page_count, DMA_TO_DEVICE);
+       if (!dma->SG_length) {
+               IVTV_DEBUG_WARN("%s: DMA map error, SG_length is 0\n", 
__func__);
+               unpin_user_pages(dma->map, dma->page_count);
+               dma->page_count = 0;
+               return -EINVAL;
+       }
 
        /* Fill SG Array with new values */
        ivtv_udma_fill_sg_array(dma, y_buffer_offset, uv_buffer_offset, y_size);
diff --git a/drivers/media/pci/ivtv/ivtvfb.c b/drivers/media/pci/ivtv/ivtvfb.c
index 410477e3e621..d1ab7fee0d05 100644
--- a/drivers/media/pci/ivtv/ivtvfb.c
+++ b/drivers/media/pci/ivtv/ivtvfb.c
@@ -281,10 +281,10 @@ static int ivtvfb_prep_dec_dma_to_device(struct ivtv *itv,
        /* Map User DMA */
        if (ivtv_udma_setup(itv, ivtv_dest_addr, userbuf, size_in_bytes) <= 0) {
                mutex_unlock(&itv->udma.lock);
-               IVTVFB_WARN("ivtvfb_prep_dec_dma_to_device, Error with 
pin_user_pages: %d bytes, %d pages returned\n",
-                              size_in_bytes, itv->udma.page_count);
+               IVTVFB_WARN("%s, Error in ivtv_udma_setup: %d bytes, %d pages 
returned\n",
+                              __func__, size_in_bytes, itv->udma.page_count);
 
-               /* pin_user_pages must have failed completely */
+               /* pin_user_pages or DMA must have failed completely */
                return -EIO;
        }
 

Reply via email to