Commit 3f65c6f6 authored by Arnd Bergmann's avatar Arnd Bergmann Committed by Mauro Carvalho Chehab

media: v4l2: allocate v4l2_clip objects early

The v4l2_format based ioctls can have an indirect pointer to an array
of v4l2_clip structures for overlay mode, depending on the 'type' member.
There are only five drivers that use the overlay mode and copy the
data through the __user pointer.

Change the five drivers to use memcpy() instead, and copy the data
in common code using the check_array_args() helpers. This allows
for a subsequent patch that use the same mechanism for compat
ioctl handlers.

Note that there is another pointer for a 'bitmap' that is only
used in the 'vivid' driver and nowhere else. There is no easy
way to use the same trick without adding complexity to the
common code, so this remains a __user pointer.

[hverkuil: fix: CHECK: spaces preferred around that '*' (ctx:VxV)]
[hverkuil: fix: CHECK: Alignment should match open parenthesis]
Signed-off-by: default avatarArnd Bergmann <arnd@arndb.de>
Signed-off-by: default avatarHans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab+huawei@kernel.org>
parent 00af58fd
...@@ -771,10 +771,8 @@ static int vidioc_s_fmt_vid_overlay(struct file *file, void *__fh, struct v4l2_f ...@@ -771,10 +771,8 @@ static int vidioc_s_fmt_vid_overlay(struct file *file, void *__fh, struct v4l2_f
vv->ov.nclips = f->fmt.win.clipcount; vv->ov.nclips = f->fmt.win.clipcount;
if (vv->ov.nclips > 16) if (vv->ov.nclips > 16)
vv->ov.nclips = 16; vv->ov.nclips = 16;
if (copy_from_user(vv->ov.clips, f->fmt.win.clips, memcpy(vv->ov.clips, f->fmt.win.clips,
sizeof(struct v4l2_clip) * vv->ov.nclips)) { sizeof(struct v4l2_clip) * vv->ov.nclips);
return -EFAULT;
}
/* vv->ov.fh is used to indicate that we have valid overlay information, too */ /* vv->ov.fh is used to indicate that we have valid overlay information, too */
vv->ov.fh = fh; vv->ov.fh = fh;
......
...@@ -2143,12 +2143,8 @@ static int setup_window_lock(struct bttv_fh *fh, struct bttv *btv, ...@@ -2143,12 +2143,8 @@ static int setup_window_lock(struct bttv_fh *fh, struct bttv *btv,
clips = kmalloc(size,GFP_KERNEL); clips = kmalloc(size,GFP_KERNEL);
if (NULL == clips) if (NULL == clips)
return -ENOMEM; return -ENOMEM;
if (n > 0) { if (n > 0)
if (copy_from_user(clips,win->clips,sizeof(struct v4l2_clip)*n)) { memcpy(clips, win->clips, sizeof(struct v4l2_clip) * n);
kfree(clips);
return -EFAULT;
}
}
/* clip against screen */ /* clip against screen */
if (NULL != btv->fbuf.base) if (NULL != btv->fbuf.base)
......
...@@ -1265,9 +1265,7 @@ static int saa7134_g_fmt_vid_overlay(struct file *file, void *priv, ...@@ -1265,9 +1265,7 @@ static int saa7134_g_fmt_vid_overlay(struct file *file, void *priv,
struct v4l2_format *f) struct v4l2_format *f)
{ {
struct saa7134_dev *dev = video_drvdata(file); struct saa7134_dev *dev = video_drvdata(file);
struct v4l2_clip __user *clips = f->fmt.win.clips;
u32 clipcount = f->fmt.win.clipcount; u32 clipcount = f->fmt.win.clipcount;
int err = 0;
int i; int i;
if (saa7134_no_overlay > 0) { if (saa7134_no_overlay > 0) {
...@@ -1275,20 +1273,18 @@ static int saa7134_g_fmt_vid_overlay(struct file *file, void *priv, ...@@ -1275,20 +1273,18 @@ static int saa7134_g_fmt_vid_overlay(struct file *file, void *priv,
return -EINVAL; return -EINVAL;
} }
f->fmt.win = dev->win; f->fmt.win = dev->win;
f->fmt.win.clips = clips; if (!f->fmt.win.clips)
if (clips == NULL)
clipcount = 0; clipcount = 0;
if (dev->nclips < clipcount) if (dev->nclips < clipcount)
clipcount = dev->nclips; clipcount = dev->nclips;
f->fmt.win.clipcount = clipcount; f->fmt.win.clipcount = clipcount;
for (i = 0; !err && i < clipcount; i++) { for (i = 0; i < clipcount; i++) {
if (copy_to_user(&f->fmt.win.clips[i].c, &dev->clips[i].c, memcpy(&f->fmt.win.clips[i].c, &dev->clips[i].c,
sizeof(struct v4l2_rect))) sizeof(struct v4l2_rect));
err = -EFAULT;
} }
return err; return 0;
} }
static int saa7134_try_fmt_vid_cap(struct file *file, void *priv, static int saa7134_try_fmt_vid_cap(struct file *file, void *priv,
...@@ -1396,9 +1392,8 @@ static int saa7134_s_fmt_vid_overlay(struct file *file, void *priv, ...@@ -1396,9 +1392,8 @@ static int saa7134_s_fmt_vid_overlay(struct file *file, void *priv,
dev->win = f->fmt.win; dev->win = f->fmt.win;
dev->nclips = f->fmt.win.clipcount; dev->nclips = f->fmt.win.clipcount;
if (copy_from_user(dev->clips, f->fmt.win.clips, memcpy(dev->clips, f->fmt.win.clips,
sizeof(struct v4l2_clip) * dev->nclips)) sizeof(struct v4l2_clip) * dev->nclips);
return -EFAULT;
if (priv == dev->overlay_owner) { if (priv == dev->overlay_owner) {
spin_lock_irqsave(&dev->slock, flags); spin_lock_irqsave(&dev->slock, flags);
......
...@@ -1107,11 +1107,9 @@ int vidioc_g_fmt_vid_overlay(struct file *file, void *priv, ...@@ -1107,11 +1107,9 @@ int vidioc_g_fmt_vid_overlay(struct file *file, void *priv,
((compose->width + 7) / 8) * compose->height)) ((compose->width + 7) / 8) * compose->height))
return -EFAULT; return -EFAULT;
} }
if (clipcount && win->clips) { if (clipcount && win->clips)
if (copy_to_user(win->clips, dev->clips_cap, memcpy(win->clips, dev->clips_cap,
clipcount * sizeof(dev->clips_cap[0]))) clipcount * sizeof(dev->clips_cap[0]));
return -EFAULT;
}
return 0; return 0;
} }
...@@ -1141,9 +1139,8 @@ int vidioc_try_fmt_vid_overlay(struct file *file, void *priv, ...@@ -1141,9 +1139,8 @@ int vidioc_try_fmt_vid_overlay(struct file *file, void *priv,
if (win->clipcount > MAX_CLIPS) if (win->clipcount > MAX_CLIPS)
win->clipcount = MAX_CLIPS; win->clipcount = MAX_CLIPS;
if (win->clipcount) { if (win->clipcount) {
if (copy_from_user(dev->try_clips_cap, win->clips, memcpy(dev->try_clips_cap, win->clips,
win->clipcount * sizeof(dev->clips_cap[0]))) win->clipcount * sizeof(dev->clips_cap[0]));
return -EFAULT;
for (i = 0; i < win->clipcount; i++) { for (i = 0; i < win->clipcount; i++) {
struct v4l2_rect *r = &dev->try_clips_cap[i].c; struct v4l2_rect *r = &dev->try_clips_cap[i].c;
...@@ -1166,9 +1163,8 @@ int vidioc_try_fmt_vid_overlay(struct file *file, void *priv, ...@@ -1166,9 +1163,8 @@ int vidioc_try_fmt_vid_overlay(struct file *file, void *priv,
return -EINVAL; return -EINVAL;
} }
} }
if (copy_to_user(win->clips, dev->try_clips_cap, memcpy(win->clips, dev->try_clips_cap,
win->clipcount * sizeof(dev->clips_cap[0]))) win->clipcount * sizeof(dev->clips_cap[0]));
return -EFAULT;
} }
return 0; return 0;
} }
......
...@@ -857,11 +857,9 @@ int vidioc_g_fmt_vid_out_overlay(struct file *file, void *priv, ...@@ -857,11 +857,9 @@ int vidioc_g_fmt_vid_out_overlay(struct file *file, void *priv,
((dev->compose_out.width + 7) / 8) * dev->compose_out.height)) ((dev->compose_out.width + 7) / 8) * dev->compose_out.height))
return -EFAULT; return -EFAULT;
} }
if (clipcount && win->clips) { if (clipcount && win->clips)
if (copy_to_user(win->clips, dev->clips_out, memcpy(win->clips, dev->clips_out,
clipcount * sizeof(dev->clips_out[0]))) clipcount * sizeof(dev->clips_out[0]));
return -EFAULT;
}
return 0; return 0;
} }
...@@ -891,9 +889,8 @@ int vidioc_try_fmt_vid_out_overlay(struct file *file, void *priv, ...@@ -891,9 +889,8 @@ int vidioc_try_fmt_vid_out_overlay(struct file *file, void *priv,
if (win->clipcount > MAX_CLIPS) if (win->clipcount > MAX_CLIPS)
win->clipcount = MAX_CLIPS; win->clipcount = MAX_CLIPS;
if (win->clipcount) { if (win->clipcount) {
if (copy_from_user(dev->try_clips_out, win->clips, memcpy(dev->try_clips_out, win->clips,
win->clipcount * sizeof(dev->clips_out[0]))) win->clipcount * sizeof(dev->clips_out[0]));
return -EFAULT;
for (i = 0; i < win->clipcount; i++) { for (i = 0; i < win->clipcount; i++) {
struct v4l2_rect *r = &dev->try_clips_out[i].c; struct v4l2_rect *r = &dev->try_clips_out[i].c;
...@@ -916,9 +913,8 @@ int vidioc_try_fmt_vid_out_overlay(struct file *file, void *priv, ...@@ -916,9 +913,8 @@ int vidioc_try_fmt_vid_out_overlay(struct file *file, void *priv,
return -EINVAL; return -EINVAL;
} }
} }
if (copy_to_user(win->clips, dev->try_clips_out, memcpy(win->clips, dev->try_clips_out,
win->clipcount * sizeof(dev->clips_out[0]))) win->clipcount * sizeof(dev->clips_out[0]));
return -EFAULT;
} }
return 0; return 0;
} }
......
...@@ -1582,7 +1582,7 @@ static int v4l_g_fmt(const struct v4l2_ioctl_ops *ops, ...@@ -1582,7 +1582,7 @@ static int v4l_g_fmt(const struct v4l2_ioctl_ops *ops,
switch (p->type) { switch (p->type) {
case V4L2_BUF_TYPE_VIDEO_OVERLAY: case V4L2_BUF_TYPE_VIDEO_OVERLAY:
case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: { case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: {
struct v4l2_clip __user *clips = p->fmt.win.clips; struct v4l2_clip *clips = p->fmt.win.clips;
u32 clipcount = p->fmt.win.clipcount; u32 clipcount = p->fmt.win.clipcount;
void __user *bitmap = p->fmt.win.bitmap; void __user *bitmap = p->fmt.win.bitmap;
...@@ -3084,6 +3084,27 @@ static int check_array_args(unsigned int cmd, void *parg, size_t *array_size, ...@@ -3084,6 +3084,27 @@ static int check_array_args(unsigned int cmd, void *parg, size_t *array_size,
} }
break; break;
} }
case VIDIOC_G_FMT:
case VIDIOC_S_FMT:
case VIDIOC_TRY_FMT: {
struct v4l2_format *fmt = parg;
if (fmt->type != V4L2_BUF_TYPE_VIDEO_OVERLAY &&
fmt->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY)
break;
if (fmt->fmt.win.clipcount > 2048)
return -EINVAL;
if (!fmt->fmt.win.clipcount)
break;
*user_ptr = (void __user *)fmt->fmt.win.clips;
*kernel_ptr = (void **)&fmt->fmt.win.clips;
*array_size = sizeof(struct v4l2_clip)
* fmt->fmt.win.clipcount;
ret = 1;
break;
}
} }
return ret; return ret;
......
...@@ -1185,7 +1185,7 @@ struct v4l2_window { ...@@ -1185,7 +1185,7 @@ struct v4l2_window {
struct v4l2_rect w; struct v4l2_rect w;
__u32 field; /* enum v4l2_field */ __u32 field; /* enum v4l2_field */
__u32 chromakey; __u32 chromakey;
struct v4l2_clip __user *clips; struct v4l2_clip *clips;
__u32 clipcount; __u32 clipcount;
void __user *bitmap; void __user *bitmap;
__u8 global_alpha; __u8 global_alpha;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment