mirror of
https://github.com/torvalds/linux.git
synced 2025-04-12 06:49:52 +00:00
media: pci: ivtv: Add check for DMA map result
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.kobuk@ispras.ru> Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
This commit is contained in:
parent
dd40472dc6
commit
629913d6d7
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user