Skip to content

Commit

Permalink
[media] media: videobuf2: fix the length check for mmap
Browse files Browse the repository at this point in the history
Memory maps typically require that the buffer size to be page
aligned. Currently, two memops drivers do such alignment
internally, but videobuf-vmalloc doesn't.
Also, the buffer overflow check doesn't take it into account.
So, instead of doing it at each memops driver, enforce it at
VB2 core.

Reported-by: Prabhakar lad <prabhakar.csengg@gmail.com>
Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Acked-by: Marek Szyprowski <m.szyprowski@samsung.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
  • Loading branch information
Mauro Carvalho Chehab committed Apr 25, 2013
1 parent b3404a8 commit 7f84145
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 8 deletions.
21 changes: 17 additions & 4 deletions drivers/media/v4l2-core/videobuf2-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,15 @@ static int __vb2_buf_mem_alloc(struct vb2_buffer *vb)
void *mem_priv;
int plane;

/* Allocate memory for all planes in this buffer */
/*
* Allocate memory for all planes in this buffer
* NOTE: mmapped areas should be page aligned
*/
for (plane = 0; plane < vb->num_planes; ++plane) {
unsigned long size = PAGE_ALIGN(q->plane_sizes[plane]);

mem_priv = call_memop(q, alloc, q->alloc_ctx[plane],
q->plane_sizes[plane], q->gfp_flags);
size, q->gfp_flags);
if (IS_ERR_OR_NULL(mem_priv))
goto free;

Expand Down Expand Up @@ -1852,6 +1857,7 @@ int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
struct vb2_buffer *vb;
unsigned int buffer, plane;
int ret;
unsigned long length;

if (q->memory != V4L2_MEMORY_MMAP) {
dprintk(1, "Queue is not currently set up for mmap\n");
Expand Down Expand Up @@ -1886,8 +1892,15 @@ int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma)

vb = q->bufs[buffer];

if (vb->v4l2_planes[plane].length < (vma->vm_end - vma->vm_start)) {
dprintk(1, "Invalid length\n");
/*
* MMAP requires page_aligned buffers.
* The buffer length was page_aligned at __vb2_buf_mem_alloc(),
* so, we need to do the same here.
*/
length = PAGE_ALIGN(vb->v4l2_planes[plane].length);
if (length < (vma->vm_end - vma->vm_start)) {
dprintk(1,
"MMAP invalid, as it would overflow buffer length\n");
return -EINVAL;
}

Expand Down
3 changes: 0 additions & 3 deletions drivers/media/v4l2-core/videobuf2-dma-contig.c
Original file line number Diff line number Diff line change
Expand Up @@ -162,9 +162,6 @@ static void *vb2_dc_alloc(void *alloc_ctx, unsigned long size, gfp_t gfp_flags)
if (!buf)
return ERR_PTR(-ENOMEM);

/* align image size to PAGE_SIZE */
size = PAGE_ALIGN(size);

buf->vaddr = dma_alloc_coherent(dev, size, &buf->dma_addr,
GFP_KERNEL | gfp_flags);
if (!buf->vaddr) {
Expand Down
3 changes: 2 additions & 1 deletion drivers/media/v4l2-core/videobuf2-dma-sg.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ static void *vb2_dma_sg_alloc(void *alloc_ctx, unsigned long size, gfp_t gfp_fla
buf->write = 0;
buf->offset = 0;
buf->sg_desc.size = size;
buf->sg_desc.num_pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
/* size is already page aligned */
buf->sg_desc.num_pages = size >> PAGE_SHIFT;

buf->sg_desc.sglist = vzalloc(buf->sg_desc.num_pages *
sizeof(*buf->sg_desc.sglist));
Expand Down

0 comments on commit 7f84145

Please sign in to comment.