aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/videobuf2-core.c
diff options
context:
space:
mode:
authorMarek Szyprowski <m.szyprowski@samsung.com>2011-08-24 05:36:26 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2011-09-06 14:03:49 -0400
commitc1426bc727b78808fb956f7402b689144c1506ee (patch)
treedd6f9667e01bfacd8f9674149c32ef774c2f0605 /drivers/media/video/videobuf2-core.c
parenta6bd62be5a3e3a2eee9c0c1d7c04cb52cff3e073 (diff)
[media] media: vb2: add a check if queued userptr buffer is large enough
Videobuf2 accepted any userptr buffer without verifying if its size is large enough to store the video data from the driver. The driver reports the minimal size of video data once in queue_setup and expects that videobuf2 provides buffers that match these requirements. This patch adds the required check. Reported-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com> CC: Pawel Osciak <pawel@osciak.com> Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/videobuf2-core.c')
-rw-r--r--drivers/media/video/videobuf2-core.c41
1 files changed, 24 insertions, 17 deletions
diff --git a/drivers/media/video/videobuf2-core.c b/drivers/media/video/videobuf2-core.c
index 3015e6000946..c3606276607e 100644
--- a/drivers/media/video/videobuf2-core.c
+++ b/drivers/media/video/videobuf2-core.c
@@ -43,8 +43,7 @@ module_param(debug, int, 0644);
43/** 43/**
44 * __vb2_buf_mem_alloc() - allocate video memory for the given buffer 44 * __vb2_buf_mem_alloc() - allocate video memory for the given buffer
45 */ 45 */
46static int __vb2_buf_mem_alloc(struct vb2_buffer *vb, 46static int __vb2_buf_mem_alloc(struct vb2_buffer *vb)
47 unsigned long *plane_sizes)
48{ 47{
49 struct vb2_queue *q = vb->vb2_queue; 48 struct vb2_queue *q = vb->vb2_queue;
50 void *mem_priv; 49 void *mem_priv;
@@ -53,13 +52,13 @@ static int __vb2_buf_mem_alloc(struct vb2_buffer *vb,
53 /* Allocate memory for all planes in this buffer */ 52 /* Allocate memory for all planes in this buffer */
54 for (plane = 0; plane < vb->num_planes; ++plane) { 53 for (plane = 0; plane < vb->num_planes; ++plane) {
55 mem_priv = call_memop(q, plane, alloc, q->alloc_ctx[plane], 54 mem_priv = call_memop(q, plane, alloc, q->alloc_ctx[plane],
56 plane_sizes[plane]); 55 q->plane_sizes[plane]);
57 if (IS_ERR_OR_NULL(mem_priv)) 56 if (IS_ERR_OR_NULL(mem_priv))
58 goto free; 57 goto free;
59 58
60 /* Associate allocator private data with this plane */ 59 /* Associate allocator private data with this plane */
61 vb->planes[plane].mem_priv = mem_priv; 60 vb->planes[plane].mem_priv = mem_priv;
62 vb->v4l2_planes[plane].length = plane_sizes[plane]; 61 vb->v4l2_planes[plane].length = q->plane_sizes[plane];
63 } 62 }
64 63
65 return 0; 64 return 0;
@@ -141,8 +140,7 @@ static void __setup_offsets(struct vb2_queue *q)
141 * Returns the number of buffers successfully allocated. 140 * Returns the number of buffers successfully allocated.
142 */ 141 */
143static int __vb2_queue_alloc(struct vb2_queue *q, enum v4l2_memory memory, 142static int __vb2_queue_alloc(struct vb2_queue *q, enum v4l2_memory memory,
144 unsigned int num_buffers, unsigned int num_planes, 143 unsigned int num_buffers, unsigned int num_planes)
145 unsigned long plane_sizes[])
146{ 144{
147 unsigned int buffer; 145 unsigned int buffer;
148 struct vb2_buffer *vb; 146 struct vb2_buffer *vb;
@@ -169,7 +167,7 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum v4l2_memory memory,
169 167
170 /* Allocate video buffer memory for the MMAP type */ 168 /* Allocate video buffer memory for the MMAP type */
171 if (memory == V4L2_MEMORY_MMAP) { 169 if (memory == V4L2_MEMORY_MMAP) {
172 ret = __vb2_buf_mem_alloc(vb, plane_sizes); 170 ret = __vb2_buf_mem_alloc(vb);
173 if (ret) { 171 if (ret) {
174 dprintk(1, "Failed allocating memory for " 172 dprintk(1, "Failed allocating memory for "
175 "buffer %d\n", buffer); 173 "buffer %d\n", buffer);
@@ -454,7 +452,6 @@ static bool __buffers_in_use(struct vb2_queue *q)
454int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req) 452int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
455{ 453{
456 unsigned int num_buffers, num_planes; 454 unsigned int num_buffers, num_planes;
457 unsigned long plane_sizes[VIDEO_MAX_PLANES];
458 int ret = 0; 455 int ret = 0;
459 456
460 if (q->fileio) { 457 if (q->fileio) {
@@ -516,7 +513,7 @@ int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
516 * Make sure the requested values and current defaults are sane. 513 * Make sure the requested values and current defaults are sane.
517 */ 514 */
518 num_buffers = min_t(unsigned int, req->count, VIDEO_MAX_FRAME); 515 num_buffers = min_t(unsigned int, req->count, VIDEO_MAX_FRAME);
519 memset(plane_sizes, 0, sizeof(plane_sizes)); 516 memset(q->plane_sizes, 0, sizeof(q->plane_sizes));
520 memset(q->alloc_ctx, 0, sizeof(q->alloc_ctx)); 517 memset(q->alloc_ctx, 0, sizeof(q->alloc_ctx));
521 q->memory = req->memory; 518 q->memory = req->memory;
522 519
@@ -525,13 +522,12 @@ int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
525 * Driver also sets the size and allocator context for each plane. 522 * Driver also sets the size and allocator context for each plane.
526 */ 523 */
527 ret = call_qop(q, queue_setup, q, &num_buffers, &num_planes, 524 ret = call_qop(q, queue_setup, q, &num_buffers, &num_planes,
528 plane_sizes, q->alloc_ctx); 525 q->plane_sizes, q->alloc_ctx);
529 if (ret) 526 if (ret)
530 return ret; 527 return ret;
531 528
532 /* Finally, allocate buffers and video memory */ 529 /* Finally, allocate buffers and video memory */
533 ret = __vb2_queue_alloc(q, req->memory, num_buffers, num_planes, 530 ret = __vb2_queue_alloc(q, req->memory, num_buffers, num_planes);
534 plane_sizes);
535 if (ret == 0) { 531 if (ret == 0) {
536 dprintk(1, "Memory allocation failed\n"); 532 dprintk(1, "Memory allocation failed\n");
537 return -ENOMEM; 533 return -ENOMEM;
@@ -545,7 +541,7 @@ int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
545 541
546 orig_num_buffers = num_buffers = ret; 542 orig_num_buffers = num_buffers = ret;
547 ret = call_qop(q, queue_setup, q, &num_buffers, &num_planes, 543 ret = call_qop(q, queue_setup, q, &num_buffers, &num_planes,
548 plane_sizes, q->alloc_ctx); 544 q->plane_sizes, q->alloc_ctx);
549 if (ret) 545 if (ret)
550 goto free_mem; 546 goto free_mem;
551 547
@@ -745,12 +741,20 @@ static int __qbuf_userptr(struct vb2_buffer *vb, struct v4l2_buffer *b)
745 dprintk(3, "qbuf: userspace address for plane %d changed, " 741 dprintk(3, "qbuf: userspace address for plane %d changed, "
746 "reacquiring memory\n", plane); 742 "reacquiring memory\n", plane);
747 743
744 /* Check if the provided plane buffer is large enough */
745 if (planes[plane].length < q->plane_sizes[plane]) {
746 ret = EINVAL;
747 goto err;
748 }
749
748 /* Release previously acquired memory if present */ 750 /* Release previously acquired memory if present */
749 if (vb->planes[plane].mem_priv) 751 if (vb->planes[plane].mem_priv)
750 call_memop(q, plane, put_userptr, 752 call_memop(q, plane, put_userptr,
751 vb->planes[plane].mem_priv); 753 vb->planes[plane].mem_priv);
752 754
753 vb->planes[plane].mem_priv = NULL; 755 vb->planes[plane].mem_priv = NULL;
756 vb->v4l2_planes[plane].m.userptr = 0;
757 vb->v4l2_planes[plane].length = 0;
754 758
755 /* Acquire each plane's memory */ 759 /* Acquire each plane's memory */
756 if (q->mem_ops->get_userptr) { 760 if (q->mem_ops->get_userptr) {
@@ -788,10 +792,13 @@ static int __qbuf_userptr(struct vb2_buffer *vb, struct v4l2_buffer *b)
788 return 0; 792 return 0;
789err: 793err:
790 /* In case of errors, release planes that were already acquired */ 794 /* In case of errors, release planes that were already acquired */
791 for (; plane > 0; --plane) { 795 for (plane = 0; plane < vb->num_planes; ++plane) {
792 call_memop(q, plane, put_userptr, 796 if (vb->planes[plane].mem_priv)
793 vb->planes[plane - 1].mem_priv); 797 call_memop(q, plane, put_userptr,
794 vb->planes[plane - 1].mem_priv = NULL; 798 vb->planes[plane].mem_priv);
799 vb->planes[plane].mem_priv = NULL;
800 vb->v4l2_planes[plane].m.userptr = 0;
801 vb->v4l2_planes[plane].length = 0;
795 } 802 }
796 803
797 return ret; 804 return ret;