media: v4l2-mem2mem: Apply DST_QUEUE_OFF_BASE on MMAP buffers across ioctls

ANBZ: #3101

commit 8310ca9407 upstream.

DST_QUEUE_OFF_BASE is applied to offset/mem_offset on MMAP capture buffers
only for the VIDIOC_QUERYBUF ioctl, while the userspace fields (including
offset/mem_offset) are filled in for VIDIOC_{QUERY,PREPARE,Q,DQ}BUF
ioctls. This leads to differences in the values presented to userspace.
If userspace attempts to mmap the capture buffer directly using values
from DQBUF, it will fail.

Move the code that applies the magic offset into a helper, and call
that helper from all four ioctl entry points.

[hverkuil: drop unnecessary '= 0' in v4l2_m2m_querybuf() for ret]

Fixes: 7f98639def ("V4L/DVB: add memory-to-memory device helper framework for videobuf")
Fixes: 908a0d7c58 ("[media] v4l: mem2mem: port to videobuf2")
Signed-off-by: Chen-Yu Tsai <wenst@chromium.org>
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>
[OP: adjusted return logic for 4.19]
Signed-off-by: Ovidiu Panait <ovidiu.panait@windriver.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

Fixes: CVE-2022-20369
Signed-off-by: Shile Zhang <shile.zhang@linux.alibaba.com>
Signed-off-by: Xiaolong <xiaolong@openanolis.org>
Reviewed-by: Xunlei Pang <xlpang@linux.alibaba.com>
Link: https://gitee.com/anolis/cloud-kernel/pulls/876
This commit is contained in:
Chen-Yu Tsai 2021-12-10 00:38:03 +08:00 committed by 小龙
parent b8a17b12b3
commit d3988a0276
1 changed files with 45 additions and 17 deletions

View File

@ -445,19 +445,14 @@ int v4l2_m2m_reqbufs(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
}
EXPORT_SYMBOL_GPL(v4l2_m2m_reqbufs);
int v4l2_m2m_querybuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
struct v4l2_buffer *buf)
static void v4l2_m2m_adjust_mem_offset(struct vb2_queue *vq,
struct v4l2_buffer *buf)
{
struct vb2_queue *vq;
int ret = 0;
unsigned int i;
vq = v4l2_m2m_get_vq(m2m_ctx, buf->type);
ret = vb2_querybuf(vq, buf);
/* Adjust MMAP memory offsets for the CAPTURE queue */
if (buf->memory == V4L2_MEMORY_MMAP && !V4L2_TYPE_IS_OUTPUT(vq->type)) {
if (V4L2_TYPE_IS_MULTIPLANAR(vq->type)) {
unsigned int i;
for (i = 0; i < buf->length; ++i)
buf->m.planes[i].m.mem_offset
+= DST_QUEUE_OFF_BASE;
@ -465,8 +460,23 @@ int v4l2_m2m_querybuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
buf->m.offset += DST_QUEUE_OFF_BASE;
}
}
}
return ret;
int v4l2_m2m_querybuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
struct v4l2_buffer *buf)
{
struct vb2_queue *vq;
int ret;
vq = v4l2_m2m_get_vq(m2m_ctx, buf->type);
ret = vb2_querybuf(vq, buf);
if (ret)
return ret;
/* Adjust MMAP memory offsets for the CAPTURE queue */
v4l2_m2m_adjust_mem_offset(vq, buf);
return 0;
}
EXPORT_SYMBOL_GPL(v4l2_m2m_querybuf);
@ -478,10 +488,15 @@ int v4l2_m2m_qbuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
vq = v4l2_m2m_get_vq(m2m_ctx, buf->type);
ret = vb2_qbuf(vq, buf);
if (!ret)
v4l2_m2m_try_schedule(m2m_ctx);
if (ret)
return ret;
return ret;
/* Adjust MMAP memory offsets for the CAPTURE queue */
v4l2_m2m_adjust_mem_offset(vq, buf);
v4l2_m2m_try_schedule(m2m_ctx);
return 0;
}
EXPORT_SYMBOL_GPL(v4l2_m2m_qbuf);
@ -489,9 +504,17 @@ int v4l2_m2m_dqbuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
struct v4l2_buffer *buf)
{
struct vb2_queue *vq;
int ret;
vq = v4l2_m2m_get_vq(m2m_ctx, buf->type);
return vb2_dqbuf(vq, buf, file->f_flags & O_NONBLOCK);
ret = vb2_dqbuf(vq, buf, file->f_flags & O_NONBLOCK);
if (ret)
return ret;
/* Adjust MMAP memory offsets for the CAPTURE queue */
v4l2_m2m_adjust_mem_offset(vq, buf);
return 0;
}
EXPORT_SYMBOL_GPL(v4l2_m2m_dqbuf);
@ -503,10 +526,15 @@ int v4l2_m2m_prepare_buf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
vq = v4l2_m2m_get_vq(m2m_ctx, buf->type);
ret = vb2_prepare_buf(vq, buf);
if (!ret)
v4l2_m2m_try_schedule(m2m_ctx);
if (ret)
return ret;
return ret;
/* Adjust MMAP memory offsets for the CAPTURE queue */
v4l2_m2m_adjust_mem_offset(vq, buf);
v4l2_m2m_try_schedule(m2m_ctx);
return 0;
}
EXPORT_SYMBOL_GPL(v4l2_m2m_prepare_buf);