media: omap_vout: potential buffer overflow in vidioc_dqbuf()

Message ID 20190409112924.GA13643@kadam (mailing list archive)
State Changes Requested, archived
Delegated to: Hans Verkuil
Headers

Commit Message

Dan Carpenter April 9, 2019, 11:29 a.m. UTC
  The "b->index" is a u32 the comes from the user in the ioctl.  It hasn't
been checked.  We aren't supposed to use it but we're instead supposed
to use the value that gets written to it when we call videobuf_dqbuf().

The videobuf_dqbuf() first memsets it to zero and then re-initializes it
inside the videobuf_status() function.  It's this final value which we
want.

Fixes: 72915e851da9 ("[media] V4L2: OMAP: VOUT: dma map and unmap v4l2 buffers in qbuf and dqbuf")
Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
---
UNTESTED!  I think I understand this code now, but I have struggled to
read it correctly in the past.  Please review carefully.


 drivers/media/platform/omap/omap_vout.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
  

Comments

Hans Verkuil April 10, 2019, 10:50 a.m. UTC | #1
On 4/9/19 1:29 PM, Dan Carpenter wrote:
> The "b->index" is a u32 the comes from the user in the ioctl.  It hasn't
> been checked.  We aren't supposed to use it but we're instead supposed
> to use the value that gets written to it when we call videobuf_dqbuf().
> 
> The videobuf_dqbuf() first memsets it to zero and then re-initializes it
> inside the videobuf_status() function.  It's this final value which we
> want.
> 
> Fixes: 72915e851da9 ("[media] V4L2: OMAP: VOUT: dma map and unmap v4l2 buffers in qbuf and dqbuf")
> Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
> ---
> UNTESTED!  I think I understand this code now, but I have struggled to
> read it correctly in the past.  Please review carefully.
> 
> 
>  drivers/media/platform/omap/omap_vout.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/media/platform/omap/omap_vout.c b/drivers/media/platform/omap/omap_vout.c
> index 37f0d7146dfa..15e38990e85a 100644
> --- a/drivers/media/platform/omap/omap_vout.c
> +++ b/drivers/media/platform/omap/omap_vout.c
> @@ -1527,8 +1527,6 @@ static int vidioc_dqbuf(struct file *file, void *fh, struct v4l2_buffer *b)
>  	unsigned long size;
>  	struct videobuf_buffer *vb;
>  
> -	vb = q->bufs[b->index];
> -
>  	if (!vout->streaming)
>  		return -EINVAL;
>  
> @@ -1539,6 +1537,8 @@ static int vidioc_dqbuf(struct file *file, void *fh, struct v4l2_buffer *b)
>  		/* Call videobuf_dqbuf for  blocking mode */
>  		ret = videobuf_dqbuf(q, (struct v4l2_buffer *)b, 0);

We need a:

	if (ret)
		return ret;

here. Or alternatively, add 'if (!ret)' around the next five lines.

b->index is only valid if the videobuf_dqbuf call returned 0.

Regards,

	Hans

>  
> +	vb = q->bufs[b->index];
> +
>  	addr = (unsigned long) vout->buf_phy_addr[vb->i];
>  	size = (unsigned long) vb->size;
>  	dma_unmap_single(vout->vid_dev->v4l2_dev.dev,  addr,
>
  
Dan Carpenter April 10, 2019, 11:14 a.m. UTC | #2
On Wed, Apr 10, 2019 at 12:50:31PM +0200, Hans Verkuil wrote:
> On 4/9/19 1:29 PM, Dan Carpenter wrote:
> > diff --git a/drivers/media/platform/omap/omap_vout.c b/drivers/media/platform/omap/omap_vout.c
> > index 37f0d7146dfa..15e38990e85a 100644
> > --- a/drivers/media/platform/omap/omap_vout.c
> > +++ b/drivers/media/platform/omap/omap_vout.c
> > @@ -1527,8 +1527,6 @@ static int vidioc_dqbuf(struct file *file, void *fh, struct v4l2_buffer *b)
> >  	unsigned long size;
> >  	struct videobuf_buffer *vb;
> >  
> > -	vb = q->bufs[b->index];
> > -
> >  	if (!vout->streaming)
> >  		return -EINVAL;
> >  
> > @@ -1539,6 +1537,8 @@ static int vidioc_dqbuf(struct file *file, void *fh, struct v4l2_buffer *b)
> >  		/* Call videobuf_dqbuf for  blocking mode */
> >  		ret = videobuf_dqbuf(q, (struct v4l2_buffer *)b, 0);
> 
> We need a:
> 
> 	if (ret)
> 		return ret;
> 
> here. Or alternatively, add 'if (!ret)' around the next five lines.
> 
> b->index is only valid if the videobuf_dqbuf call returned 0.
> 

Doh.  Thanks.

regards,
dan carpenter
  
Amber Jain April 10, 2019, 2:05 p.m. UTC | #3
I think you might have the wrong Amber copied on this email. 

Amber

-----Original Message-----
From: Dan Carpenter [mailto:dan.carpenter@oracle.com] 
Sent: Wednesday, April 10, 2019 6:14 AM
To: Hans Verkuil
Cc: Mauro Carvalho Chehab; Scheurer, Amber; Niklas Söderlund; Philipp Zabel; Parrot, Benoit; linux-media@vger.kernel.org; kernel-janitors@vger.kernel.org; Andrzej Hajda
Subject: [EXTERNAL] Re: [PATCH] media: omap_vout: potential buffer overflow in vidioc_dqbuf()

On Wed, Apr 10, 2019 at 12:50:31PM +0200, Hans Verkuil wrote:
> On 4/9/19 1:29 PM, Dan Carpenter wrote:
> > diff --git a/drivers/media/platform/omap/omap_vout.c b/drivers/media/platform/omap/omap_vout.c
> > index 37f0d7146dfa..15e38990e85a 100644
> > --- a/drivers/media/platform/omap/omap_vout.c
> > +++ b/drivers/media/platform/omap/omap_vout.c
> > @@ -1527,8 +1527,6 @@ static int vidioc_dqbuf(struct file *file, void *fh, struct v4l2_buffer *b)
> >  	unsigned long size;
> >  	struct videobuf_buffer *vb;
> >  
> > -	vb = q->bufs[b->index];
> > -
> >  	if (!vout->streaming)
> >  		return -EINVAL;
> >  
> > @@ -1539,6 +1537,8 @@ static int vidioc_dqbuf(struct file *file, void *fh, struct v4l2_buffer *b)
> >  		/* Call videobuf_dqbuf for  blocking mode */
> >  		ret = videobuf_dqbuf(q, (struct v4l2_buffer *)b, 0);
> 
> We need a:
> 
> 	if (ret)
> 		return ret;
> 
> here. Or alternatively, add 'if (!ret)' around the next five lines.
> 
> b->index is only valid if the videobuf_dqbuf call returned 0.
> 

Doh.  Thanks.

regards,
dan carpenter
  

Patch

diff --git a/drivers/media/platform/omap/omap_vout.c b/drivers/media/platform/omap/omap_vout.c
index 37f0d7146dfa..15e38990e85a 100644
--- a/drivers/media/platform/omap/omap_vout.c
+++ b/drivers/media/platform/omap/omap_vout.c
@@ -1527,8 +1527,6 @@  static int vidioc_dqbuf(struct file *file, void *fh, struct v4l2_buffer *b)
 	unsigned long size;
 	struct videobuf_buffer *vb;
 
-	vb = q->bufs[b->index];
-
 	if (!vout->streaming)
 		return -EINVAL;
 
@@ -1539,6 +1537,8 @@  static int vidioc_dqbuf(struct file *file, void *fh, struct v4l2_buffer *b)
 		/* Call videobuf_dqbuf for  blocking mode */
 		ret = videobuf_dqbuf(q, (struct v4l2_buffer *)b, 0);
 
+	vb = q->bufs[b->index];
+
 	addr = (unsigned long) vout->buf_phy_addr[vb->i];
 	size = (unsigned long) vb->size;
 	dma_unmap_single(vout->vid_dev->v4l2_dev.dev,  addr,