Skip to content

Commit ab9ac47

Browse files
harperchensmb49
authored andcommitted
media: pci: tw68: Fix null-ptr-deref bug in buf prepare and finish
BugLink: https://bugs.launchpad.net/bugs/2028808 [ Upstream commit 1634b7a ] When the driver calls tw68_risc_buffer() to prepare the buffer, the function call dma_alloc_coherent may fail, resulting in a empty buffer buf->cpu. Later when we free the buffer or access the buffer, null ptr deref is triggered. This bug is similar to the following one: https://git.linuxtv.org/media_stage.git/commit/?id=2b064d91440b33fba5b452f2d1b31f13ae911d71. We believe the bug can be also dynamically triggered from user side. Similarly, we fix this by checking the return value of tw68_risc_buffer() and the value of buf->cpu before buffer free. Signed-off-by: harperchen <harperchen1110@gmail.com> Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org> Signed-off-by: Sasha Levin <sashal@kernel.org> Signed-off-by: Kamal Mostafa <kamal@canonical.com> Signed-off-by: Stefan Bader <stefan.bader@canonical.com>
1 parent b6b3432 commit ab9ac47

1 file changed

Lines changed: 9 additions & 7 deletions

File tree

drivers/media/pci/tw68/tw68-video.c

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -437,6 +437,7 @@ static void tw68_buf_queue(struct vb2_buffer *vb)
437437
*/
438438
static int tw68_buf_prepare(struct vb2_buffer *vb)
439439
{
440+
int ret;
440441
struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
441442
struct vb2_queue *vq = vb->vb2_queue;
442443
struct tw68_dev *dev = vb2_get_drv_priv(vq);
@@ -452,30 +453,30 @@ static int tw68_buf_prepare(struct vb2_buffer *vb)
452453
bpl = (dev->width * dev->fmt->depth) >> 3;
453454
switch (dev->field) {
454455
case V4L2_FIELD_TOP:
455-
tw68_risc_buffer(dev->pci, buf, dma->sgl,
456+
ret = tw68_risc_buffer(dev->pci, buf, dma->sgl,
456457
0, UNSET, bpl, 0, dev->height);
457458
break;
458459
case V4L2_FIELD_BOTTOM:
459-
tw68_risc_buffer(dev->pci, buf, dma->sgl,
460+
ret = tw68_risc_buffer(dev->pci, buf, dma->sgl,
460461
UNSET, 0, bpl, 0, dev->height);
461462
break;
462463
case V4L2_FIELD_SEQ_TB:
463-
tw68_risc_buffer(dev->pci, buf, dma->sgl,
464+
ret = tw68_risc_buffer(dev->pci, buf, dma->sgl,
464465
0, bpl * (dev->height >> 1),
465466
bpl, 0, dev->height >> 1);
466467
break;
467468
case V4L2_FIELD_SEQ_BT:
468-
tw68_risc_buffer(dev->pci, buf, dma->sgl,
469+
ret = tw68_risc_buffer(dev->pci, buf, dma->sgl,
469470
bpl * (dev->height >> 1), 0,
470471
bpl, 0, dev->height >> 1);
471472
break;
472473
case V4L2_FIELD_INTERLACED:
473474
default:
474-
tw68_risc_buffer(dev->pci, buf, dma->sgl,
475+
ret = tw68_risc_buffer(dev->pci, buf, dma->sgl,
475476
0, bpl, bpl, bpl, dev->height >> 1);
476477
break;
477478
}
478-
return 0;
479+
return ret;
479480
}
480481

481482
static void tw68_buf_finish(struct vb2_buffer *vb)
@@ -485,7 +486,8 @@ static void tw68_buf_finish(struct vb2_buffer *vb)
485486
struct tw68_dev *dev = vb2_get_drv_priv(vq);
486487
struct tw68_buf *buf = container_of(vbuf, struct tw68_buf, vb);
487488

488-
dma_free_coherent(&dev->pci->dev, buf->size, buf->cpu, buf->dma);
489+
if (buf->cpu)
490+
dma_free_coherent(&dev->pci->dev, buf->size, buf->cpu, buf->dma);
489491
}
490492

491493
static int tw68_start_streaming(struct vb2_queue *q, unsigned int count)

0 commit comments

Comments
 (0)