mirror of https://gitee.com/openkylin/linux.git
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);\
|
printk(KERN_DEBUG "%s: " fmt, vfd->name, ## arg);\
|
||||||
} while (0)
|
} 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 {
|
struct std_descr {
|
||||||
v4l2_std_id std;
|
v4l2_std_id std;
|
||||||
const char *descr;
|
const char *descr;
|
||||||
|
@ -782,44 +788,53 @@ static long __video_do_ioctl(struct file *file,
|
||||||
|
|
||||||
switch (f->type) {
|
switch (f->type) {
|
||||||
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
|
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
|
||||||
|
CLEAR_AFTER_FIELD(f, fmt.pix);
|
||||||
v4l_print_pix_fmt(vfd, &f->fmt.pix);
|
v4l_print_pix_fmt(vfd, &f->fmt.pix);
|
||||||
if (ops->vidioc_s_fmt_vid_cap)
|
if (ops->vidioc_s_fmt_vid_cap)
|
||||||
ret = ops->vidioc_s_fmt_vid_cap(file, fh, f);
|
ret = ops->vidioc_s_fmt_vid_cap(file, fh, f);
|
||||||
break;
|
break;
|
||||||
case V4L2_BUF_TYPE_VIDEO_OVERLAY:
|
case V4L2_BUF_TYPE_VIDEO_OVERLAY:
|
||||||
|
CLEAR_AFTER_FIELD(f, fmt.win);
|
||||||
if (ops->vidioc_s_fmt_vid_overlay)
|
if (ops->vidioc_s_fmt_vid_overlay)
|
||||||
ret = ops->vidioc_s_fmt_vid_overlay(file,
|
ret = ops->vidioc_s_fmt_vid_overlay(file,
|
||||||
fh, f);
|
fh, f);
|
||||||
break;
|
break;
|
||||||
case V4L2_BUF_TYPE_VIDEO_OUTPUT:
|
case V4L2_BUF_TYPE_VIDEO_OUTPUT:
|
||||||
|
CLEAR_AFTER_FIELD(f, fmt.pix);
|
||||||
v4l_print_pix_fmt(vfd, &f->fmt.pix);
|
v4l_print_pix_fmt(vfd, &f->fmt.pix);
|
||||||
if (ops->vidioc_s_fmt_vid_out)
|
if (ops->vidioc_s_fmt_vid_out)
|
||||||
ret = ops->vidioc_s_fmt_vid_out(file, fh, f);
|
ret = ops->vidioc_s_fmt_vid_out(file, fh, f);
|
||||||
break;
|
break;
|
||||||
case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
|
case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
|
||||||
|
CLEAR_AFTER_FIELD(f, fmt.win);
|
||||||
if (ops->vidioc_s_fmt_vid_out_overlay)
|
if (ops->vidioc_s_fmt_vid_out_overlay)
|
||||||
ret = ops->vidioc_s_fmt_vid_out_overlay(file,
|
ret = ops->vidioc_s_fmt_vid_out_overlay(file,
|
||||||
fh, f);
|
fh, f);
|
||||||
break;
|
break;
|
||||||
case V4L2_BUF_TYPE_VBI_CAPTURE:
|
case V4L2_BUF_TYPE_VBI_CAPTURE:
|
||||||
|
CLEAR_AFTER_FIELD(f, fmt.vbi);
|
||||||
if (ops->vidioc_s_fmt_vbi_cap)
|
if (ops->vidioc_s_fmt_vbi_cap)
|
||||||
ret = ops->vidioc_s_fmt_vbi_cap(file, fh, f);
|
ret = ops->vidioc_s_fmt_vbi_cap(file, fh, f);
|
||||||
break;
|
break;
|
||||||
case V4L2_BUF_TYPE_VBI_OUTPUT:
|
case V4L2_BUF_TYPE_VBI_OUTPUT:
|
||||||
|
CLEAR_AFTER_FIELD(f, fmt.vbi);
|
||||||
if (ops->vidioc_s_fmt_vbi_out)
|
if (ops->vidioc_s_fmt_vbi_out)
|
||||||
ret = ops->vidioc_s_fmt_vbi_out(file, fh, f);
|
ret = ops->vidioc_s_fmt_vbi_out(file, fh, f);
|
||||||
break;
|
break;
|
||||||
case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
|
case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
|
||||||
|
CLEAR_AFTER_FIELD(f, fmt.sliced);
|
||||||
if (ops->vidioc_s_fmt_sliced_vbi_cap)
|
if (ops->vidioc_s_fmt_sliced_vbi_cap)
|
||||||
ret = ops->vidioc_s_fmt_sliced_vbi_cap(file,
|
ret = ops->vidioc_s_fmt_sliced_vbi_cap(file,
|
||||||
fh, f);
|
fh, f);
|
||||||
break;
|
break;
|
||||||
case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
|
case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
|
||||||
|
CLEAR_AFTER_FIELD(f, fmt.sliced);
|
||||||
if (ops->vidioc_s_fmt_sliced_vbi_out)
|
if (ops->vidioc_s_fmt_sliced_vbi_out)
|
||||||
ret = ops->vidioc_s_fmt_sliced_vbi_out(file,
|
ret = ops->vidioc_s_fmt_sliced_vbi_out(file,
|
||||||
fh, f);
|
fh, f);
|
||||||
break;
|
break;
|
||||||
case V4L2_BUF_TYPE_PRIVATE:
|
case V4L2_BUF_TYPE_PRIVATE:
|
||||||
|
/* CLEAR_AFTER_FIELD(f, fmt.raw_data); <- does nothing */
|
||||||
if (ops->vidioc_s_fmt_type_private)
|
if (ops->vidioc_s_fmt_type_private)
|
||||||
ret = ops->vidioc_s_fmt_type_private(file,
|
ret = ops->vidioc_s_fmt_type_private(file,
|
||||||
fh, f);
|
fh, f);
|
||||||
|
@ -836,46 +851,55 @@ static long __video_do_ioctl(struct file *file,
|
||||||
v4l2_type_names));
|
v4l2_type_names));
|
||||||
switch (f->type) {
|
switch (f->type) {
|
||||||
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
|
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
|
||||||
|
CLEAR_AFTER_FIELD(f, fmt.pix);
|
||||||
if (ops->vidioc_try_fmt_vid_cap)
|
if (ops->vidioc_try_fmt_vid_cap)
|
||||||
ret = ops->vidioc_try_fmt_vid_cap(file, fh, f);
|
ret = ops->vidioc_try_fmt_vid_cap(file, fh, f);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
v4l_print_pix_fmt(vfd, &f->fmt.pix);
|
v4l_print_pix_fmt(vfd, &f->fmt.pix);
|
||||||
break;
|
break;
|
||||||
case V4L2_BUF_TYPE_VIDEO_OVERLAY:
|
case V4L2_BUF_TYPE_VIDEO_OVERLAY:
|
||||||
|
CLEAR_AFTER_FIELD(f, fmt.win);
|
||||||
if (ops->vidioc_try_fmt_vid_overlay)
|
if (ops->vidioc_try_fmt_vid_overlay)
|
||||||
ret = ops->vidioc_try_fmt_vid_overlay(file,
|
ret = ops->vidioc_try_fmt_vid_overlay(file,
|
||||||
fh, f);
|
fh, f);
|
||||||
break;
|
break;
|
||||||
case V4L2_BUF_TYPE_VIDEO_OUTPUT:
|
case V4L2_BUF_TYPE_VIDEO_OUTPUT:
|
||||||
|
CLEAR_AFTER_FIELD(f, fmt.pix);
|
||||||
if (ops->vidioc_try_fmt_vid_out)
|
if (ops->vidioc_try_fmt_vid_out)
|
||||||
ret = ops->vidioc_try_fmt_vid_out(file, fh, f);
|
ret = ops->vidioc_try_fmt_vid_out(file, fh, f);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
v4l_print_pix_fmt(vfd, &f->fmt.pix);
|
v4l_print_pix_fmt(vfd, &f->fmt.pix);
|
||||||
break;
|
break;
|
||||||
case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
|
case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
|
||||||
|
CLEAR_AFTER_FIELD(f, fmt.win);
|
||||||
if (ops->vidioc_try_fmt_vid_out_overlay)
|
if (ops->vidioc_try_fmt_vid_out_overlay)
|
||||||
ret = ops->vidioc_try_fmt_vid_out_overlay(file,
|
ret = ops->vidioc_try_fmt_vid_out_overlay(file,
|
||||||
fh, f);
|
fh, f);
|
||||||
break;
|
break;
|
||||||
case V4L2_BUF_TYPE_VBI_CAPTURE:
|
case V4L2_BUF_TYPE_VBI_CAPTURE:
|
||||||
|
CLEAR_AFTER_FIELD(f, fmt.vbi);
|
||||||
if (ops->vidioc_try_fmt_vbi_cap)
|
if (ops->vidioc_try_fmt_vbi_cap)
|
||||||
ret = ops->vidioc_try_fmt_vbi_cap(file, fh, f);
|
ret = ops->vidioc_try_fmt_vbi_cap(file, fh, f);
|
||||||
break;
|
break;
|
||||||
case V4L2_BUF_TYPE_VBI_OUTPUT:
|
case V4L2_BUF_TYPE_VBI_OUTPUT:
|
||||||
|
CLEAR_AFTER_FIELD(f, fmt.vbi);
|
||||||
if (ops->vidioc_try_fmt_vbi_out)
|
if (ops->vidioc_try_fmt_vbi_out)
|
||||||
ret = ops->vidioc_try_fmt_vbi_out(file, fh, f);
|
ret = ops->vidioc_try_fmt_vbi_out(file, fh, f);
|
||||||
break;
|
break;
|
||||||
case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
|
case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
|
||||||
|
CLEAR_AFTER_FIELD(f, fmt.sliced);
|
||||||
if (ops->vidioc_try_fmt_sliced_vbi_cap)
|
if (ops->vidioc_try_fmt_sliced_vbi_cap)
|
||||||
ret = ops->vidioc_try_fmt_sliced_vbi_cap(file,
|
ret = ops->vidioc_try_fmt_sliced_vbi_cap(file,
|
||||||
fh, f);
|
fh, f);
|
||||||
break;
|
break;
|
||||||
case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
|
case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
|
||||||
|
CLEAR_AFTER_FIELD(f, fmt.sliced);
|
||||||
if (ops->vidioc_try_fmt_sliced_vbi_out)
|
if (ops->vidioc_try_fmt_sliced_vbi_out)
|
||||||
ret = ops->vidioc_try_fmt_sliced_vbi_out(file,
|
ret = ops->vidioc_try_fmt_sliced_vbi_out(file,
|
||||||
fh, f);
|
fh, f);
|
||||||
break;
|
break;
|
||||||
case V4L2_BUF_TYPE_PRIVATE:
|
case V4L2_BUF_TYPE_PRIVATE:
|
||||||
|
/* CLEAR_AFTER_FIELD(f, fmt.raw_data); <- does nothing */
|
||||||
if (ops->vidioc_try_fmt_type_private)
|
if (ops->vidioc_try_fmt_type_private)
|
||||||
ret = ops->vidioc_try_fmt_type_private(file,
|
ret = ops->vidioc_try_fmt_type_private(file,
|
||||||
fh, f);
|
fh, f);
|
||||||
|
@ -898,6 +922,9 @@ static long __video_do_ioctl(struct file *file,
|
||||||
if (ret)
|
if (ret)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
if (p->type < V4L2_BUF_TYPE_PRIVATE)
|
||||||
|
CLEAR_AFTER_FIELD(p, memory);
|
||||||
|
|
||||||
ret = ops->vidioc_reqbufs(file, fh, p);
|
ret = ops->vidioc_reqbufs(file, fh, p);
|
||||||
dbgarg(cmd, "count=%d, type=%s, memory=%s\n",
|
dbgarg(cmd, "count=%d, type=%s, memory=%s\n",
|
||||||
p->count,
|
p->count,
|
||||||
|
|
Loading…
Reference in New Issue