---
.../media/common/videobuf2/videobuf2-core.c | 21 ++++++++++++++++---
.../media/common/videobuf2/videobuf2-v4l2.c | 8 +++----
include/uapi/linux/videodev2.h | 7 +++++--
3 files changed, 27 insertions(+), 9 deletions(-)
diff --git a/drivers/media/common/videobuf2/videobuf2-core.c b/drivers/media/common/videobuf2/videobuf2-core.c
index 02281d13505f..2cbde14af051 100644
--- a/drivers/media/common/videobuf2/videobuf2-core.c
+++ b/drivers/media/common/videobuf2/videobuf2-core.c
@@ -1205,6 +1205,7 @@ static int __prepare_dmabuf(struct vb2_buffer *vb)
for (plane = 0; plane < vb->num_planes; ++plane) {
struct dma_buf *dbuf = dma_buf_get(planes[plane].m.fd);
+ unsigned int bytesused;
if (IS_ERR_OR_NULL(dbuf)) {
dprintk(q, 1, "invalid dmabuf fd for plane %d\n",
@@ -1213,9 +1214,23 @@ static int __prepare_dmabuf(struct vb2_buffer *vb)
goto err;
}
- /* use DMABUF size if length is not provided */
- if (planes[plane].length == 0)
- planes[plane].length = dbuf->size;
+ planes[plane].length = dbuf->size;
+ bytesused = planes[plane].bytesused ?
+ planes[plane].bytesused : dbuf->size;
+
+ if (planes[plane].bytesused > planes[plane].length) {
+ dprintk(q, 1, "bytesused is bigger then dmabuf length for plane %d\n",
+ plane);
+ ret = -EINVAL;
+ goto err;
+ }
+
+ if (planes[plane].data_offset >= bytesused) {
+ dprintk(q, 1, "data_offset >= bytesused for plane %d\n",
+ plane);
+ ret = -EINVAL;
+ goto err;
+ }
if (planes[plane].length < vb->planes[plane].min_length) {
dprintk(q, 1, "invalid dmabuf length %u for plane %d, minimum length %u\n",
diff --git a/drivers/media/common/videobuf2/videobuf2-v4l2.c b/drivers/media/common/videobuf2/videobuf2-v4l2.c
index 7e96f67c60ba..ffc7ed46f74a 100644
--- a/drivers/media/common/videobuf2/videobuf2-v4l2.c
+++ b/drivers/media/common/videobuf2/videobuf2-v4l2.c
@@ -98,14 +98,14 @@ static int __verify_length(struct vb2_buffer *vb, const struct v4l2_buffer *b)
unsigned int bytesused;
unsigned int plane;
- if (V4L2_TYPE_IS_CAPTURE(b->type))
+ /* length check for dmabuf is performed in _prepare_dmabuf() */
+ if (V4L2_TYPE_IS_CAPTURE(b->type) || b->memory == VB2_MEMORY_DMABUF)
return 0;
if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) {
for (plane = 0; plane < vb->num_planes; ++plane) {
- length = (b->memory == VB2_MEMORY_USERPTR ||
- b->memory == VB2_MEMORY_DMABUF)
- ? b->m.planes[plane].length
+ length = b->memory == VB2_MEMORY_USERPTR
+ ? b->m.planes[plane].length
: vb->planes[plane].length;
bytesused = b->m.planes[plane].bytesused
? b->m.planes[plane].bytesused : length;
diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
index 8d15f6ccc4b4..79b3b2893513 100644
--- a/include/uapi/linux/videodev2.h
+++ b/include/uapi/linux/videodev2.h
@@ -968,7 +968,9 @@ struct v4l2_requestbuffers {
/**
* struct v4l2_plane - plane info for multi-planar buffers
* @bytesused: number of bytes occupied by data in the plane (payload)
- * @length: size of this plane (NOT the payload) in bytes
+ * @length: size of this plane (NOT the payload) in bytes. Filled
+ * by userspace for USERPTR and by the driver for DMABUF
+ * and MMAP.
* @mem_offset: when memory in the associated struct v4l2_buffer is
* V4L2_MEMORY_MMAP, equals the offset from the start of
* the device memory for this plane (or is a "cookie" that
@@ -1025,7 +1027,8 @@ struct v4l2_plane {
* @m: union of @offset, @userptr, @planes and @fd
* @length: size in bytes of the buffer (NOT its payload) for single-plane
* buffers (when type != *_MPLANE); number of elements in the
- * planes array for multi-plane buffers
+ * planes array for multi-plane buffers. Filled by userspace for
+ * USERPTR and by the driver for DMABUF and MMAP.
* @reserved2: drivers and applications must zero this field
* @request_fd: fd of the request that this buffer should use
* @reserved: for backwards compatibility with applications that do not know