aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@redhat.com>2013-04-19 06:18:01 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2013-04-25 08:54:00 -0400
commit7f8414594e4755234fd0ca415630cfe2dfab42ce (patch)
tree4fc8507e954362d9f5898703e0c10dbd1651b2b8
parentb3404a8ef567de43b74018bbdbd989b53426d422 (diff)
[media] media: videobuf2: fix the length check for mmap
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>
-rw-r--r--drivers/media/v4l2-core/videobuf2-core.c21
-rw-r--r--drivers/media/v4l2-core/videobuf2-dma-contig.c3
-rw-r--r--drivers/media/v4l2-core/videobuf2-dma-sg.c3
3 files changed, 19 insertions, 8 deletions
diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c
index 58c17444d22f..7d833eefaf4e 100644
--- a/drivers/media/v4l2-core/videobuf2-core.c
+++ b/drivers/media/v4l2-core/videobuf2-core.c
@@ -54,10 +54,15 @@ static int __vb2_buf_mem_alloc(struct vb2_buffer *vb)
54 void *mem_priv; 54 void *mem_priv;
55 int plane; 55 int plane;
56 56
57 /* Allocate memory for all planes in this buffer */ 57 /*
58 * Allocate memory for all planes in this buffer
59 * NOTE: mmapped areas should be page aligned
60 */
58 for (plane = 0; plane < vb->num_planes; ++plane) { 61 for (plane = 0; plane < vb->num_planes; ++plane) {
62 unsigned long size = PAGE_ALIGN(q->plane_sizes[plane]);
63
59 mem_priv = call_memop(q, alloc, q->alloc_ctx[plane], 64 mem_priv = call_memop(q, alloc, q->alloc_ctx[plane],
60 q->plane_sizes[plane], q->gfp_flags); 65 size, q->gfp_flags);
61 if (IS_ERR_OR_NULL(mem_priv)) 66 if (IS_ERR_OR_NULL(mem_priv))
62 goto free; 67 goto free;
63 68
@@ -1852,6 +1857,7 @@ int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
1852 struct vb2_buffer *vb; 1857 struct vb2_buffer *vb;
1853 unsigned int buffer, plane; 1858 unsigned int buffer, plane;
1854 int ret; 1859 int ret;
1860 unsigned long length;
1855 1861
1856 if (q->memory != V4L2_MEMORY_MMAP) { 1862 if (q->memory != V4L2_MEMORY_MMAP) {
1857 dprintk(1, "Queue is not currently set up for mmap\n"); 1863 dprintk(1, "Queue is not currently set up for mmap\n");
@@ -1886,8 +1892,15 @@ int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
1886 1892
1887 vb = q->bufs[buffer]; 1893 vb = q->bufs[buffer];
1888 1894
1889 if (vb->v4l2_planes[plane].length < (vma->vm_end - vma->vm_start)) { 1895 /*
1890 dprintk(1, "Invalid length\n"); 1896 * MMAP requires page_aligned buffers.
1897 * The buffer length was page_aligned at __vb2_buf_mem_alloc(),
1898 * so, we need to do the same here.
1899 */
1900 length = PAGE_ALIGN(vb->v4l2_planes[plane].length);
1901 if (length < (vma->vm_end - vma->vm_start)) {
1902 dprintk(1,
1903 "MMAP invalid, as it would overflow buffer length\n");
1891 return -EINVAL; 1904 return -EINVAL;
1892 } 1905 }
1893 1906
diff --git a/drivers/media/v4l2-core/videobuf2-dma-contig.c b/drivers/media/v4l2-core/videobuf2-dma-contig.c
index ae35d255a430..fd56f2563201 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-contig.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-contig.c
@@ -162,9 +162,6 @@ static void *vb2_dc_alloc(void *alloc_ctx, unsigned long size, gfp_t gfp_flags)
162 if (!buf) 162 if (!buf)
163 return ERR_PTR(-ENOMEM); 163 return ERR_PTR(-ENOMEM);
164 164
165 /* align image size to PAGE_SIZE */
166 size = PAGE_ALIGN(size);
167
168 buf->vaddr = dma_alloc_coherent(dev, size, &buf->dma_addr, 165 buf->vaddr = dma_alloc_coherent(dev, size, &buf->dma_addr,
169 GFP_KERNEL | gfp_flags); 166 GFP_KERNEL | gfp_flags);
170 if (!buf->vaddr) { 167 if (!buf->vaddr) {
diff --git a/drivers/media/v4l2-core/videobuf2-dma-sg.c b/drivers/media/v4l2-core/videobuf2-dma-sg.c
index 59522b2ebae1..16ae3dcc7e29 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-sg.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-sg.c
@@ -55,7 +55,8 @@ static void *vb2_dma_sg_alloc(void *alloc_ctx, unsigned long size, gfp_t gfp_fla
55 buf->write = 0; 55 buf->write = 0;
56 buf->offset = 0; 56 buf->offset = 0;
57 buf->sg_desc.size = size; 57 buf->sg_desc.size = size;
58 buf->sg_desc.num_pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT; 58 /* size is already page aligned */
59 buf->sg_desc.num_pages = size >> PAGE_SHIFT;
59 60
60 buf->sg_desc.sglist = vzalloc(buf->sg_desc.num_pages * 61 buf->sg_desc.sglist = vzalloc(buf->sg_desc.num_pages *
61 sizeof(*buf->sg_desc.sglist)); 62 sizeof(*buf->sg_desc.sglist));