Commit 47e8b73b authored by harperchen's avatar harperchen Committed by Mauro Carvalho Chehab

media: cx23885: Fix a null-ptr-deref bug in buffer_prepare() and buffer_finish()

When the driver calls cx23885_risc_buffer() to prepare the buffer, the
function call dma_alloc_coherent may fail, resulting in a empty buffer
risc->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 cx23885_risc_buffer()
and the value of risc->cpu before buffer free.
Signed-off-by: default avatarharperchen <harperchen1110@gmail.com>
Signed-off-by: default avatarHans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@kernel.org>
parent ffa331d9
...@@ -1325,7 +1325,9 @@ void cx23885_free_buffer(struct cx23885_dev *dev, struct cx23885_buffer *buf) ...@@ -1325,7 +1325,9 @@ void cx23885_free_buffer(struct cx23885_dev *dev, struct cx23885_buffer *buf)
{ {
struct cx23885_riscmem *risc = &buf->risc; struct cx23885_riscmem *risc = &buf->risc;
dma_free_coherent(&dev->pci->dev, risc->size, risc->cpu, risc->dma); if (risc->cpu)
dma_free_coherent(&dev->pci->dev, risc->size, risc->cpu, risc->dma);
memset(risc, 0, sizeof(*risc));
} }
static void cx23885_tsport_reg_dump(struct cx23885_tsport *port) static void cx23885_tsport_reg_dump(struct cx23885_tsport *port)
......
...@@ -342,6 +342,7 @@ static int queue_setup(struct vb2_queue *q, ...@@ -342,6 +342,7 @@ static int queue_setup(struct vb2_queue *q,
static int buffer_prepare(struct vb2_buffer *vb) static int buffer_prepare(struct vb2_buffer *vb)
{ {
int ret;
struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct cx23885_dev *dev = vb->vb2_queue->drv_priv; struct cx23885_dev *dev = vb->vb2_queue->drv_priv;
struct cx23885_buffer *buf = struct cx23885_buffer *buf =
...@@ -358,12 +359,12 @@ static int buffer_prepare(struct vb2_buffer *vb) ...@@ -358,12 +359,12 @@ static int buffer_prepare(struct vb2_buffer *vb)
switch (dev->field) { switch (dev->field) {
case V4L2_FIELD_TOP: case V4L2_FIELD_TOP:
cx23885_risc_buffer(dev->pci, &buf->risc, ret = cx23885_risc_buffer(dev->pci, &buf->risc,
sgt->sgl, 0, UNSET, sgt->sgl, 0, UNSET,
buf->bpl, 0, dev->height); buf->bpl, 0, dev->height);
break; break;
case V4L2_FIELD_BOTTOM: case V4L2_FIELD_BOTTOM:
cx23885_risc_buffer(dev->pci, &buf->risc, ret = cx23885_risc_buffer(dev->pci, &buf->risc,
sgt->sgl, UNSET, 0, sgt->sgl, UNSET, 0,
buf->bpl, 0, dev->height); buf->bpl, 0, dev->height);
break; break;
...@@ -391,21 +392,21 @@ static int buffer_prepare(struct vb2_buffer *vb) ...@@ -391,21 +392,21 @@ static int buffer_prepare(struct vb2_buffer *vb)
line0_offset = 0; line0_offset = 0;
line1_offset = buf->bpl; line1_offset = buf->bpl;
} }
cx23885_risc_buffer(dev->pci, &buf->risc, ret = cx23885_risc_buffer(dev->pci, &buf->risc,
sgt->sgl, line0_offset, sgt->sgl, line0_offset,
line1_offset, line1_offset,
buf->bpl, buf->bpl, buf->bpl, buf->bpl,
dev->height >> 1); dev->height >> 1);
break; break;
case V4L2_FIELD_SEQ_TB: case V4L2_FIELD_SEQ_TB:
cx23885_risc_buffer(dev->pci, &buf->risc, ret = cx23885_risc_buffer(dev->pci, &buf->risc,
sgt->sgl, sgt->sgl,
0, buf->bpl * (dev->height >> 1), 0, buf->bpl * (dev->height >> 1),
buf->bpl, 0, buf->bpl, 0,
dev->height >> 1); dev->height >> 1);
break; break;
case V4L2_FIELD_SEQ_BT: case V4L2_FIELD_SEQ_BT:
cx23885_risc_buffer(dev->pci, &buf->risc, ret = cx23885_risc_buffer(dev->pci, &buf->risc,
sgt->sgl, sgt->sgl,
buf->bpl * (dev->height >> 1), 0, buf->bpl * (dev->height >> 1), 0,
buf->bpl, 0, buf->bpl, 0,
...@@ -418,7 +419,7 @@ static int buffer_prepare(struct vb2_buffer *vb) ...@@ -418,7 +419,7 @@ static int buffer_prepare(struct vb2_buffer *vb)
buf, buf->vb.vb2_buf.index, buf, buf->vb.vb2_buf.index,
dev->width, dev->height, dev->fmt->depth, dev->fmt->fourcc, dev->width, dev->height, dev->fmt->depth, dev->fmt->fourcc,
(unsigned long)buf->risc.dma); (unsigned long)buf->risc.dma);
return 0; return ret;
} }
static void buffer_finish(struct vb2_buffer *vb) static void buffer_finish(struct vb2_buffer *vb)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment