V4L/DVB (11662): v4l2-ioctl: Clear buffer type specific trailing fields/padding
Some ioctls have structs that are a different size depending on what type of buffer is being used. If the buffer type leaves a field unused or has padding space at the end, this space should be zeroed out. The problems with S_FMT and REQBUFS were original identified and patched by Marton Nemeth <nm127@freemail.hu>. Signed-off-by: Trent Piepho <xyzzy@speakeasy.org> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
parent
1175d6131f
commit
7ecc0cf937
|
@ -42,6 +42,12 @@
|
|||
printk(KERN_DEBUG "%s: " fmt, vfd->name, ## arg);\
|
||||
} while (0)
|
||||
|
||||
/* Zero out the end of the struct pointed to by p. Everthing after, but
|
||||
* not including, the specified field is cleared. */
|
||||
#define CLEAR_AFTER_FIELD(p, field) \
|
||||
memset((u8 *)(p) + offsetof(typeof(*(p)), field) + sizeof((p)->field), \
|
||||
0, sizeof(*(p)) - offsetof(typeof(*(p)), field) - sizeof((p)->field))
|
||||
|
||||
struct std_descr {
|
||||
v4l2_std_id std;
|
||||
const char *descr;
|
||||
|
@ -782,44 +788,53 @@ static long __video_do_ioctl(struct file *file,
|
|||
|
||||
switch (f->type) {
|
||||
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
|
||||
CLEAR_AFTER_FIELD(f, fmt.pix);
|
||||
v4l_print_pix_fmt(vfd, &f->fmt.pix);
|
||||
if (ops->vidioc_s_fmt_vid_cap)
|
||||
ret = ops->vidioc_s_fmt_vid_cap(file, fh, f);
|
||||
break;
|
||||
case V4L2_BUF_TYPE_VIDEO_OVERLAY:
|
||||
CLEAR_AFTER_FIELD(f, fmt.win);
|
||||
if (ops->vidioc_s_fmt_vid_overlay)
|
||||
ret = ops->vidioc_s_fmt_vid_overlay(file,
|
||||
fh, f);
|
||||
break;
|
||||
case V4L2_BUF_TYPE_VIDEO_OUTPUT:
|
||||
CLEAR_AFTER_FIELD(f, fmt.pix);
|
||||
v4l_print_pix_fmt(vfd, &f->fmt.pix);
|
||||
if (ops->vidioc_s_fmt_vid_out)
|
||||
ret = ops->vidioc_s_fmt_vid_out(file, fh, f);
|
||||
break;
|
||||
case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
|
||||
CLEAR_AFTER_FIELD(f, fmt.win);
|
||||
if (ops->vidioc_s_fmt_vid_out_overlay)
|
||||
ret = ops->vidioc_s_fmt_vid_out_overlay(file,
|
||||
fh, f);
|
||||
break;
|
||||
case V4L2_BUF_TYPE_VBI_CAPTURE:
|
||||
CLEAR_AFTER_FIELD(f, fmt.vbi);
|
||||
if (ops->vidioc_s_fmt_vbi_cap)
|
||||
ret = ops->vidioc_s_fmt_vbi_cap(file, fh, f);
|
||||
break;
|
||||
case V4L2_BUF_TYPE_VBI_OUTPUT:
|
||||
CLEAR_AFTER_FIELD(f, fmt.vbi);
|
||||
if (ops->vidioc_s_fmt_vbi_out)
|
||||
ret = ops->vidioc_s_fmt_vbi_out(file, fh, f);
|
||||
break;
|
||||
case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
|
||||
CLEAR_AFTER_FIELD(f, fmt.sliced);
|
||||
if (ops->vidioc_s_fmt_sliced_vbi_cap)
|
||||
ret = ops->vidioc_s_fmt_sliced_vbi_cap(file,
|
||||
fh, f);
|
||||
break;
|
||||
case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
|
||||
CLEAR_AFTER_FIELD(f, fmt.sliced);
|
||||
if (ops->vidioc_s_fmt_sliced_vbi_out)
|
||||
ret = ops->vidioc_s_fmt_sliced_vbi_out(file,
|
||||
fh, f);
|
||||
break;
|
||||
case V4L2_BUF_TYPE_PRIVATE:
|
||||
/* CLEAR_AFTER_FIELD(f, fmt.raw_data); <- does nothing */
|
||||
if (ops->vidioc_s_fmt_type_private)
|
||||
ret = ops->vidioc_s_fmt_type_private(file,
|
||||
fh, f);
|
||||
|
@ -836,46 +851,55 @@ static long __video_do_ioctl(struct file *file,
|
|||
v4l2_type_names));
|
||||
switch (f->type) {
|
||||
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
|
||||
CLEAR_AFTER_FIELD(f, fmt.pix);
|
||||
if (ops->vidioc_try_fmt_vid_cap)
|
||||
ret = ops->vidioc_try_fmt_vid_cap(file, fh, f);
|
||||
if (!ret)
|
||||
v4l_print_pix_fmt(vfd, &f->fmt.pix);
|
||||
break;
|
||||
case V4L2_BUF_TYPE_VIDEO_OVERLAY:
|
||||
CLEAR_AFTER_FIELD(f, fmt.win);
|
||||
if (ops->vidioc_try_fmt_vid_overlay)
|
||||
ret = ops->vidioc_try_fmt_vid_overlay(file,
|
||||
fh, f);
|
||||
break;
|
||||
case V4L2_BUF_TYPE_VIDEO_OUTPUT:
|
||||
CLEAR_AFTER_FIELD(f, fmt.pix);
|
||||
if (ops->vidioc_try_fmt_vid_out)
|
||||
ret = ops->vidioc_try_fmt_vid_out(file, fh, f);
|
||||
if (!ret)
|
||||
v4l_print_pix_fmt(vfd, &f->fmt.pix);
|
||||
break;
|
||||
case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
|
||||
CLEAR_AFTER_FIELD(f, fmt.win);
|
||||
if (ops->vidioc_try_fmt_vid_out_overlay)
|
||||
ret = ops->vidioc_try_fmt_vid_out_overlay(file,
|
||||
fh, f);
|
||||
break;
|
||||
case V4L2_BUF_TYPE_VBI_CAPTURE:
|
||||
CLEAR_AFTER_FIELD(f, fmt.vbi);
|
||||
if (ops->vidioc_try_fmt_vbi_cap)
|
||||
ret = ops->vidioc_try_fmt_vbi_cap(file, fh, f);
|
||||
break;
|
||||
case V4L2_BUF_TYPE_VBI_OUTPUT:
|
||||
CLEAR_AFTER_FIELD(f, fmt.vbi);
|
||||
if (ops->vidioc_try_fmt_vbi_out)
|
||||
ret = ops->vidioc_try_fmt_vbi_out(file, fh, f);
|
||||
break;
|
||||
case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
|
||||
CLEAR_AFTER_FIELD(f, fmt.sliced);
|
||||
if (ops->vidioc_try_fmt_sliced_vbi_cap)
|
||||
ret = ops->vidioc_try_fmt_sliced_vbi_cap(file,
|
||||
fh, f);
|
||||
break;
|
||||
case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
|
||||
CLEAR_AFTER_FIELD(f, fmt.sliced);
|
||||
if (ops->vidioc_try_fmt_sliced_vbi_out)
|
||||
ret = ops->vidioc_try_fmt_sliced_vbi_out(file,
|
||||
fh, f);
|
||||
break;
|
||||
case V4L2_BUF_TYPE_PRIVATE:
|
||||
/* CLEAR_AFTER_FIELD(f, fmt.raw_data); <- does nothing */
|
||||
if (ops->vidioc_try_fmt_type_private)
|
||||
ret = ops->vidioc_try_fmt_type_private(file,
|
||||
fh, f);
|
||||
|
@ -898,6 +922,9 @@ static long __video_do_ioctl(struct file *file,
|
|||
if (ret)
|
||||
break;
|
||||
|
||||
if (p->type < V4L2_BUF_TYPE_PRIVATE)
|
||||
CLEAR_AFTER_FIELD(p, memory);
|
||||
|
||||
ret = ops->vidioc_reqbufs(file, fh, p);
|
||||
dbgarg(cmd, "count=%d, type=%s, memory=%s\n",
|
||||
p->count,
|
||||
|
|
Loading…
Reference in a new issue