All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCHv4 0/5] vb2: add buf_out_validate callback
@ 2019-01-16 12:01 hverkuil-cisco
  2019-01-16 12:01 ` [PATCHv4 1/5] " hverkuil-cisco
                   ` (4 more replies)
  0 siblings, 5 replies; 7+ messages in thread
From: hverkuil-cisco @ 2019-01-16 12:01 UTC (permalink / raw)
  To: linux-media; +Cc: Sakari Ailus, Paul Kocialkowski

From: Hans Verkuil <hverkuil-cisco@xs4all.nl>

When queueing a buffer to a request the 'field' value is not validated.
That field is only validated when the _buf_prepare() is called,
which happens when the request is queued.

However, this validation should happen at QBUF time, since you want
to know about this as soon as possible. Also, the spec requires that
the 'field' value is validated at QBUF time.

This patch adds a new buf_out_validate callback to validate the
output buffer at buf_prepare time or when QBUF queues an unprepared
buffer to a request. This callback is mandatory for output queues
that support requests.

This issue was found by v4l2-compliance since it failed to replace
V4L2_FIELD_ANY by a proper field value when testing the vivid video
output in combination with requests.

This patch series adds a new buf_out_validate callback and implements
it for the three drivers that support requests for output queues:
vivid, vim2m and cedrus.

The final patch adds a check that this new callback is implemented
for output queues supporting requests since it is easy to forget.

Regards,

	Hans

Changes since v3:

- Implement the callback for the cedrus driver, add check that the
  callback is implemented when it is required.
- Previous versions claimed that there was also a problem when
  requests are not in use, but that turned out to be wrong. This is
  request specific.
- Call the new callback as well when preparing a buffer.
- When calling it from qbuf, only call it when queueing an unprepared
  buffer to a request. This is the actual fix.

Changes since v2:

- drop test whether the queue is an output queue. This callback is only
  called for output queues, so this test is not needed anymore.

Changes since v1:

- Renamed buf_validate to buf_out_validate since this is output
  specific.
- Clarify in the commit log of the first patch that this isn't
  request API specific, but fixes a long standing problem that
  just wasn't noticed until now.

Hans Verkuil (5):
  vb2: add buf_out_validate callback
  vim2m: add buf_out_validate callback
  vivid: add buf_out_validate callback
  cedrus: add buf_out_validate callback
  vb2: check that buf_out_validate is present

 .../media/common/videobuf2/videobuf2-core.c   | 22 ++++++++++++---
 .../media/common/videobuf2/videobuf2-v4l2.c   |  7 +++++
 drivers/media/platform/vim2m.c                | 27 +++++++++++--------
 drivers/media/platform/vivid/vivid-vid-out.c  | 23 +++++++++++-----
 .../staging/media/sunxi/cedrus/cedrus_video.c |  9 +++++++
 include/media/videobuf2-core.h                |  5 ++++
 6 files changed, 72 insertions(+), 21 deletions(-)

-- 
2.20.1


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCHv4 1/5] vb2: add buf_out_validate callback
  2019-01-16 12:01 [PATCHv4 0/5] vb2: add buf_out_validate callback hverkuil-cisco
@ 2019-01-16 12:01 ` hverkuil-cisco
  2019-01-16 12:01 ` [PATCHv4 2/5] vim2m: " hverkuil-cisco
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 7+ messages in thread
From: hverkuil-cisco @ 2019-01-16 12:01 UTC (permalink / raw)
  To: linux-media; +Cc: Sakari Ailus, Paul Kocialkowski, Hans Verkuil

From: Hans Verkuil <hverkuil-cisco@xs4all.nl>

When queueing a buffer to a request the 'field' value is not validated.
That field is only validated when the _buf_prepare() is called,
which happens when the request is queued.

However, this validation should happen at QBUF time, since you want
to know about this as soon as possible. Also, the spec requires that
the 'field' value is validated at QBUF time.

This patch adds a new buf_out_validate callback to validate the
output buffer at buf_prepare time or when QBUF queues an unprepared
buffer to a request. This callback is mandatory for output queues
that support requests.

This issue was found by v4l2-compliance since it failed to replace
V4L2_FIELD_ANY by a proper field value when testing the vivid video
output in combination with requests.

Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
---
 .../media/common/videobuf2/videobuf2-core.c   | 22 ++++++++++++++++---
 include/media/videobuf2-core.h                |  5 +++++
 2 files changed, 24 insertions(+), 3 deletions(-)

diff --git a/drivers/media/common/videobuf2/videobuf2-core.c b/drivers/media/common/videobuf2/videobuf2-core.c
index 70e8c3366f9c..607c13caca92 100644
--- a/drivers/media/common/videobuf2/videobuf2-core.c
+++ b/drivers/media/common/videobuf2/videobuf2-core.c
@@ -499,9 +499,9 @@ static int __vb2_queue_free(struct vb2_queue *q, unsigned int buffers)
 			pr_info("     buf_init: %u buf_cleanup: %u buf_prepare: %u buf_finish: %u\n",
 				vb->cnt_buf_init, vb->cnt_buf_cleanup,
 				vb->cnt_buf_prepare, vb->cnt_buf_finish);
-			pr_info("     buf_queue: %u buf_done: %u buf_request_complete: %u\n",
-				vb->cnt_buf_queue, vb->cnt_buf_done,
-				vb->cnt_buf_request_complete);
+			pr_info("     buf_out_validate: %u buf_queue: %u buf_done: %u buf_request_complete: %u\n",
+				vb->cnt_buf_out_validate, vb->cnt_buf_queue,
+				vb->cnt_buf_done, vb->cnt_buf_request_complete);
 			pr_info("     alloc: %u put: %u prepare: %u finish: %u mmap: %u\n",
 				vb->cnt_mem_alloc, vb->cnt_mem_put,
 				vb->cnt_mem_prepare, vb->cnt_mem_finish,
@@ -1274,6 +1274,14 @@ static int __buf_prepare(struct vb2_buffer *vb)
 		return 0;
 	WARN_ON(vb->synced);
 
+	if (q->is_output) {
+		ret = call_vb_qop(vb, buf_out_validate, vb);
+		if (ret) {
+			dprintk(1, "buffer validation failed\n");
+			return ret;
+		}
+	}
+
 	vb->state = VB2_BUF_STATE_PREPARING;
 
 	switch (q->memory) {
@@ -1520,6 +1528,14 @@ int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb,
 			return -EINVAL;
 		}
 
+		if (q->is_output && !vb->prepared) {
+			ret = call_vb_qop(vb, buf_out_validate, vb);
+			if (ret) {
+				dprintk(1, "buffer validation failed\n");
+				return ret;
+			}
+		}
+
 		media_request_object_init(&vb->req_obj);
 
 		/* Make sure the request is in a safe state for updating. */
diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index 4a737b2c610b..4849b865b908 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -296,6 +296,7 @@ struct vb2_buffer {
 	u32		cnt_mem_num_users;
 	u32		cnt_mem_mmap;
 
+	u32		cnt_buf_out_validate;
 	u32		cnt_buf_init;
 	u32		cnt_buf_prepare;
 	u32		cnt_buf_finish;
@@ -342,6 +343,9 @@ struct vb2_buffer {
  * @wait_finish:	reacquire all locks released in the previous callback;
  *			required to continue operation after sleeping while
  *			waiting for a new buffer to arrive.
+ * @buf_out_validate:	called when the output buffer is prepared or queued
+ *			to a request; drivers can use this to validate
+ *			userspace-provided information; optional.
  * @buf_init:		called once after allocating a buffer (in MMAP case)
  *			or after acquiring a new USERPTR buffer; drivers may
  *			perform additional buffer-related initialization;
@@ -409,6 +413,7 @@ struct vb2_ops {
 	void (*wait_prepare)(struct vb2_queue *q);
 	void (*wait_finish)(struct vb2_queue *q);
 
+	int (*buf_out_validate)(struct vb2_buffer *vb);
 	int (*buf_init)(struct vb2_buffer *vb);
 	int (*buf_prepare)(struct vb2_buffer *vb);
 	void (*buf_finish)(struct vb2_buffer *vb);
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCHv4 2/5] vim2m: add buf_out_validate callback
  2019-01-16 12:01 [PATCHv4 0/5] vb2: add buf_out_validate callback hverkuil-cisco
  2019-01-16 12:01 ` [PATCHv4 1/5] " hverkuil-cisco
@ 2019-01-16 12:01 ` hverkuil-cisco
  2019-01-16 12:01 ` [PATCHv4 3/5] vivid: " hverkuil-cisco
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 7+ messages in thread
From: hverkuil-cisco @ 2019-01-16 12:01 UTC (permalink / raw)
  To: linux-media; +Cc: Sakari Ailus, Paul Kocialkowski, Hans Verkuil

From: Hans Verkuil <hverkuil-cisco@xs4all.nl>

Validate the field for an output buffer. This ensures that the
field is validated when the buffer is queued to a request, and
not when the request itself is queued, which is too late.

Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
---
 drivers/media/platform/vim2m.c | 27 ++++++++++++++++-----------
 1 file changed, 16 insertions(+), 11 deletions(-)

diff --git a/drivers/media/platform/vim2m.c b/drivers/media/platform/vim2m.c
index 33397d4a1402..b2a6131469c4 100644
--- a/drivers/media/platform/vim2m.c
+++ b/drivers/media/platform/vim2m.c
@@ -743,25 +743,29 @@ static int vim2m_queue_setup(struct vb2_queue *vq,
 	return 0;
 }
 
-static int vim2m_buf_prepare(struct vb2_buffer *vb)
+static int vim2m_buf_out_validate(struct vb2_buffer *vb)
 {
 	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
 	struct vim2m_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+
+	if (vbuf->field == V4L2_FIELD_ANY)
+		vbuf->field = V4L2_FIELD_NONE;
+	if (vbuf->field != V4L2_FIELD_NONE) {
+		dprintk(ctx->dev, "%s field isn't supported\n", __func__);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int vim2m_buf_prepare(struct vb2_buffer *vb)
+{
+	struct vim2m_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
 	struct vim2m_q_data *q_data;
 
 	dprintk(ctx->dev, "type: %d\n", vb->vb2_queue->type);
 
 	q_data = get_q_data(ctx, vb->vb2_queue->type);
-	if (V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) {
-		if (vbuf->field == V4L2_FIELD_ANY)
-			vbuf->field = V4L2_FIELD_NONE;
-		if (vbuf->field != V4L2_FIELD_NONE) {
-			dprintk(ctx->dev, "%s field isn't supported\n",
-					__func__);
-			return -EINVAL;
-		}
-	}
-
 	if (vb2_plane_size(vb, 0) < q_data->sizeimage) {
 		dprintk(ctx->dev, "%s data will not fit into plane (%lu < %lu)\n",
 				__func__, vb2_plane_size(vb, 0), (long)q_data->sizeimage);
@@ -822,6 +826,7 @@ static void vim2m_buf_request_complete(struct vb2_buffer *vb)
 
 static const struct vb2_ops vim2m_qops = {
 	.queue_setup	 = vim2m_queue_setup,
+	.buf_out_validate	 = vim2m_buf_out_validate,
 	.buf_prepare	 = vim2m_buf_prepare,
 	.buf_queue	 = vim2m_buf_queue,
 	.start_streaming = vim2m_start_streaming,
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCHv4 3/5] vivid: add buf_out_validate callback
  2019-01-16 12:01 [PATCHv4 0/5] vb2: add buf_out_validate callback hverkuil-cisco
  2019-01-16 12:01 ` [PATCHv4 1/5] " hverkuil-cisco
  2019-01-16 12:01 ` [PATCHv4 2/5] vim2m: " hverkuil-cisco
@ 2019-01-16 12:01 ` hverkuil-cisco
  2019-01-16 12:01 ` [PATCHv4 4/5] cedrus: " hverkuil-cisco
  2019-01-16 12:01 ` [PATCHv4 5/5] vb2: check that buf_out_validate is present hverkuil-cisco
  4 siblings, 0 replies; 7+ messages in thread
From: hverkuil-cisco @ 2019-01-16 12:01 UTC (permalink / raw)
  To: linux-media; +Cc: Sakari Ailus, Paul Kocialkowski, Hans Verkuil

From: Hans Verkuil <hverkuil-cisco@xs4all.nl>

Validate the field for an output buffer. This ensures that the
field is validated when the buffer is queued to a request, and
not when the request itself is queued, which is too late.

Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
---
 drivers/media/platform/vivid/vivid-vid-out.c | 23 ++++++++++++++------
 1 file changed, 16 insertions(+), 7 deletions(-)

diff --git a/drivers/media/platform/vivid/vivid-vid-out.c b/drivers/media/platform/vivid/vivid-vid-out.c
index ea250aee2b2e..e45753a1adde 100644
--- a/drivers/media/platform/vivid/vivid-vid-out.c
+++ b/drivers/media/platform/vivid/vivid-vid-out.c
@@ -81,10 +81,24 @@ static int vid_out_queue_setup(struct vb2_queue *vq,
 	return 0;
 }
 
-static int vid_out_buf_prepare(struct vb2_buffer *vb)
+static int vid_out_buf_out_validate(struct vb2_buffer *vb)
 {
 	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
 	struct vivid_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
+
+	dprintk(dev, 1, "%s\n", __func__);
+
+	if (dev->field_out != V4L2_FIELD_ALTERNATE)
+		vbuf->field = dev->field_out;
+	else if (vbuf->field != V4L2_FIELD_TOP &&
+		 vbuf->field != V4L2_FIELD_BOTTOM)
+		return -EINVAL;
+	return 0;
+}
+
+static int vid_out_buf_prepare(struct vb2_buffer *vb)
+{
+	struct vivid_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
 	unsigned long size;
 	unsigned planes;
 	unsigned p;
@@ -105,12 +119,6 @@ static int vid_out_buf_prepare(struct vb2_buffer *vb)
 		return -EINVAL;
 	}
 
-	if (dev->field_out != V4L2_FIELD_ALTERNATE)
-		vbuf->field = dev->field_out;
-	else if (vbuf->field != V4L2_FIELD_TOP &&
-		 vbuf->field != V4L2_FIELD_BOTTOM)
-		return -EINVAL;
-
 	for (p = 0; p < planes; p++) {
 		size = dev->bytesperline_out[p] * dev->fmt_out_rect.height +
 			vb->planes[p].data_offset;
@@ -188,6 +196,7 @@ static void vid_out_buf_request_complete(struct vb2_buffer *vb)
 
 const struct vb2_ops vivid_vid_out_qops = {
 	.queue_setup		= vid_out_queue_setup,
+	.buf_out_validate		= vid_out_buf_out_validate,
 	.buf_prepare		= vid_out_buf_prepare,
 	.buf_queue		= vid_out_buf_queue,
 	.start_streaming	= vid_out_start_streaming,
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCHv4 4/5] cedrus: add buf_out_validate callback
  2019-01-16 12:01 [PATCHv4 0/5] vb2: add buf_out_validate callback hverkuil-cisco
                   ` (2 preceding siblings ...)
  2019-01-16 12:01 ` [PATCHv4 3/5] vivid: " hverkuil-cisco
@ 2019-01-16 12:01 ` hverkuil-cisco
  2019-01-16 12:01 ` [PATCHv4 5/5] vb2: check that buf_out_validate is present hverkuil-cisco
  4 siblings, 0 replies; 7+ messages in thread
From: hverkuil-cisco @ 2019-01-16 12:01 UTC (permalink / raw)
  To: linux-media; +Cc: Sakari Ailus, Paul Kocialkowski, Hans Verkuil

From: Hans Verkuil <hverkuil-cisco@xs4all.nl>

Validate the field for an output buffer. This ensures that the
field is validated when the buffer is queued to a request, and
not when the request itself is queued, which is too late.

Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
---
 drivers/staging/media/sunxi/cedrus/cedrus_video.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_video.c b/drivers/staging/media/sunxi/cedrus/cedrus_video.c
index 8721b4a7d496..b5cc79389d67 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_video.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_video.c
@@ -416,6 +416,14 @@ static void cedrus_buf_cleanup(struct vb2_buffer *vb)
 		ctx->dst_bufs[vb->index] = NULL;
 }
 
+static int cedrus_buf_out_validate(struct vb2_buffer *vb)
+{
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+
+	vbuf->field = V4L2_FIELD_NONE;
+	return 0;
+}
+
 static int cedrus_buf_prepare(struct vb2_buffer *vb)
 {
 	struct vb2_queue *vq = vb->vb2_queue;
@@ -493,6 +501,7 @@ static struct vb2_ops cedrus_qops = {
 	.buf_init		= cedrus_buf_init,
 	.buf_cleanup		= cedrus_buf_cleanup,
 	.buf_queue		= cedrus_buf_queue,
+	.buf_out_validate	= cedrus_buf_out_validate,
 	.buf_request_complete	= cedrus_buf_request_complete,
 	.start_streaming	= cedrus_start_streaming,
 	.stop_streaming		= cedrus_stop_streaming,
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCHv4 5/5] vb2: check that buf_out_validate is present
  2019-01-16 12:01 [PATCHv4 0/5] vb2: add buf_out_validate callback hverkuil-cisco
                   ` (3 preceding siblings ...)
  2019-01-16 12:01 ` [PATCHv4 4/5] cedrus: " hverkuil-cisco
@ 2019-01-16 12:01 ` hverkuil-cisco
  2019-01-25 15:23   ` [PATCHv4.1 " Hans Verkuil
  4 siblings, 1 reply; 7+ messages in thread
From: hverkuil-cisco @ 2019-01-16 12:01 UTC (permalink / raw)
  To: linux-media; +Cc: Sakari Ailus, Paul Kocialkowski, Hans Verkuil

From: Hans Verkuil <hverkuil-cisco@xs4all.nl>

The buf_out_validate is required for output queues in combination
with requests. Check this.

Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
---
 drivers/media/common/videobuf2/videobuf2-v4l2.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/drivers/media/common/videobuf2/videobuf2-v4l2.c b/drivers/media/common/videobuf2/videobuf2-v4l2.c
index 75ea90e795d8..653869031b71 100644
--- a/drivers/media/common/videobuf2/videobuf2-v4l2.c
+++ b/drivers/media/common/videobuf2/videobuf2-v4l2.c
@@ -409,6 +409,13 @@ static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct media_device *md
 	 */
 	if (WARN_ON(!q->ops->buf_request_complete))
 		return -EINVAL;
+	/*
+	 * Make sure this op is implemented by the driver for the output queue.
+	 * It's easy to forget this callback, but is it important to correctly
+	 * validate the 'field' value at QBUF time.
+	 */
+	if (WARN_ON(q->is_output && !q->ops->buf_out_validate))
+		return -EINVAL;
 
 	if (vb->state != VB2_BUF_STATE_DEQUEUED) {
 		dprintk(1, "%s: buffer is not in dequeued state\n", opname);
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCHv4.1 5/5] vb2: check that buf_out_validate is present
  2019-01-16 12:01 ` [PATCHv4 5/5] vb2: check that buf_out_validate is present hverkuil-cisco
@ 2019-01-25 15:23   ` Hans Verkuil
  0 siblings, 0 replies; 7+ messages in thread
From: Hans Verkuil @ 2019-01-25 15:23 UTC (permalink / raw)
  To: linux-media; +Cc: Sakari Ailus, Paul Kocialkowski

The buf_out_validate is required for output queues in combination
with requests. Check this.

Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
---
Changes since v4:

- Check for VIDEO_OUTPUT types instead of q->is_output since this is not
  relevant for e.g. VBI outputs.
---
 drivers/media/common/videobuf2/videobuf2-v4l2.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/drivers/media/common/videobuf2/videobuf2-v4l2.c b/drivers/media/common/videobuf2/videobuf2-v4l2.c
index 2f3b3ca5bde6..3aeaea3af42a 100644
--- a/drivers/media/common/videobuf2/videobuf2-v4l2.c
+++ b/drivers/media/common/videobuf2/videobuf2-v4l2.c
@@ -409,6 +409,15 @@ static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct media_device *md
 	 */
 	if (WARN_ON(!q->ops->buf_request_complete))
 		return -EINVAL;
+	/*
+	 * Make sure this op is implemented by the driver for the output queue.
+	 * It's easy to forget this callback, but is it important to correctly
+	 * validate the 'field' value at QBUF time.
+	 */
+	if (WARN_ON((q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT ||
+		     q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) &&
+		    !q->ops->buf_out_validate))
+		return -EINVAL;

 	if (vb->state != VB2_BUF_STATE_DEQUEUED) {
 		dprintk(1, "%s: buffer is not in dequeued state\n", opname);
-- 
2.20.1

^ permalink raw reply related	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2019-01-25 15:23 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-01-16 12:01 [PATCHv4 0/5] vb2: add buf_out_validate callback hverkuil-cisco
2019-01-16 12:01 ` [PATCHv4 1/5] " hverkuil-cisco
2019-01-16 12:01 ` [PATCHv4 2/5] vim2m: " hverkuil-cisco
2019-01-16 12:01 ` [PATCHv4 3/5] vivid: " hverkuil-cisco
2019-01-16 12:01 ` [PATCHv4 4/5] cedrus: " hverkuil-cisco
2019-01-16 12:01 ` [PATCHv4 5/5] vb2: check that buf_out_validate is present hverkuil-cisco
2019-01-25 15:23   ` [PATCHv4.1 " Hans Verkuil

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.