summaryrefslogtreecommitdiffstats
path: root/drivers/media/pci/cx23885
diff options
context:
space:
mode:
authorharperchen <harperchen1110@gmail.com>2023-03-02 13:39:05 +0100
committerMauro Carvalho Chehab <mchehab@kernel.org>2023-03-19 22:55:33 +0100
commit47e8b73bc35d7c54642f78e498697692f6358996 (patch)
tree7cf3c7da143b75e4d156d8fe3c484a24179f3db2 /drivers/media/pci/cx23885
parentmedia: amphion: decoder implement display delay enable (diff)
downloadlinux-47e8b73bc35d7c54642f78e498697692f6358996.tar.xz
linux-47e8b73bc35d7c54642f78e498697692f6358996.zip
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: harperchen <harperchen1110@gmail.com> Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>
Diffstat (limited to 'drivers/media/pci/cx23885')
-rw-r--r--drivers/media/pci/cx23885/cx23885-core.c4
-rw-r--r--drivers/media/pci/cx23885/cx23885-video.c13
2 files changed, 10 insertions, 7 deletions
diff --git a/drivers/media/pci/cx23885/cx23885-core.c b/drivers/media/pci/cx23885/cx23885-core.c
index 9232a966bcab..2ce2914576cf 100644
--- a/drivers/media/pci/cx23885/cx23885-core.c
+++ b/drivers/media/pci/cx23885/cx23885-core.c
@@ -1325,7 +1325,9 @@ void cx23885_free_buffer(struct cx23885_dev *dev, struct cx23885_buffer *buf)
{
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)
diff --git a/drivers/media/pci/cx23885/cx23885-video.c b/drivers/media/pci/cx23885/cx23885-video.c
index 3d03f5e95786..671fc0588e43 100644
--- a/drivers/media/pci/cx23885/cx23885-video.c
+++ b/drivers/media/pci/cx23885/cx23885-video.c
@@ -342,6 +342,7 @@ static int queue_setup(struct vb2_queue *q,
static int buffer_prepare(struct vb2_buffer *vb)
{
+ int ret;
struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct cx23885_dev *dev = vb->vb2_queue->drv_priv;
struct cx23885_buffer *buf =
@@ -358,12 +359,12 @@ static int buffer_prepare(struct vb2_buffer *vb)
switch (dev->field) {
case V4L2_FIELD_TOP:
- cx23885_risc_buffer(dev->pci, &buf->risc,
+ ret = cx23885_risc_buffer(dev->pci, &buf->risc,
sgt->sgl, 0, UNSET,
buf->bpl, 0, dev->height);
break;
case V4L2_FIELD_BOTTOM:
- cx23885_risc_buffer(dev->pci, &buf->risc,
+ ret = cx23885_risc_buffer(dev->pci, &buf->risc,
sgt->sgl, UNSET, 0,
buf->bpl, 0, dev->height);
break;
@@ -391,21 +392,21 @@ static int buffer_prepare(struct vb2_buffer *vb)
line0_offset = 0;
line1_offset = buf->bpl;
}
- cx23885_risc_buffer(dev->pci, &buf->risc,
+ ret = cx23885_risc_buffer(dev->pci, &buf->risc,
sgt->sgl, line0_offset,
line1_offset,
buf->bpl, buf->bpl,
dev->height >> 1);
break;
case V4L2_FIELD_SEQ_TB:
- cx23885_risc_buffer(dev->pci, &buf->risc,
+ ret = cx23885_risc_buffer(dev->pci, &buf->risc,
sgt->sgl,
0, buf->bpl * (dev->height >> 1),
buf->bpl, 0,
dev->height >> 1);
break;
case V4L2_FIELD_SEQ_BT:
- cx23885_risc_buffer(dev->pci, &buf->risc,
+ ret = cx23885_risc_buffer(dev->pci, &buf->risc,
sgt->sgl,
buf->bpl * (dev->height >> 1), 0,
buf->bpl, 0,
@@ -418,7 +419,7 @@ static int buffer_prepare(struct vb2_buffer *vb)
buf, buf->vb.vb2_buf.index,
dev->width, dev->height, dev->fmt->depth, dev->fmt->fourcc,
(unsigned long)buf->risc.dma);
- return 0;
+ return ret;
}
static void buffer_finish(struct vb2_buffer *vb)