Commit 3e645d6b authored by Linus Torvalds's avatar Linus Torvalds

v4l1: fix 32-bit compat microcode loading translation

The compat code for the VIDIOCSMICROCODE ioctl is totally buggered.
It's only used by the VIDEO_STRADIS driver, and that one is scheduled to
staging and eventually removed unless somebody steps up to maintain it
(at which point it should use request_firmware() rather than some magic
ioctl).  So we'll get rid of it eventually.

But in the meantime, the compatibility ioctl code is broken, and this
tries to get it to at least limp along (even if Mauro suggested just
deleting it entirely, which may be the right thing to do - I don't think
the compatibility translation code has ever worked unless you were very
lucky).
Reported-by: default avatarKees Cook <kees.cook@canonical.com>
Cc: Mauro Carvalho Chehab <mchehab@infradead.org>
Cc: stable@kernel.org
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 799c1055
...@@ -193,17 +193,24 @@ static int put_video_window32(struct video_window *kp, struct video_window32 __u ...@@ -193,17 +193,24 @@ static int put_video_window32(struct video_window *kp, struct video_window32 __u
struct video_code32 { struct video_code32 {
char loadwhat[16]; /* name or tag of file being passed */ char loadwhat[16]; /* name or tag of file being passed */
compat_int_t datasize; compat_int_t datasize;
unsigned char *data; compat_uptr_t data;
}; };
static int get_microcode32(struct video_code *kp, struct video_code32 __user *up) static struct video_code __user *get_microcode32(struct video_code32 *kp)
{ {
if (!access_ok(VERIFY_READ, up, sizeof(struct video_code32)) || struct video_code __user *up;
copy_from_user(kp->loadwhat, up->loadwhat, sizeof(up->loadwhat)) ||
get_user(kp->datasize, &up->datasize) || up = compat_alloc_user_space(sizeof(*up));
copy_from_user(kp->data, up->data, up->datasize))
return -EFAULT; /*
return 0; * NOTE! We don't actually care if these fail. If the
* user address is invalid, the native ioctl will do
* the error handling for us
*/
(void) copy_to_user(up->loadwhat, kp->loadwhat, sizeof(up->loadwhat));
(void) put_user(kp->datasize, &up->datasize);
(void) put_user(compat_ptr(kp->data), &up->data);
return up;
} }
#define VIDIOCGTUNER32 _IOWR('v', 4, struct video_tuner32) #define VIDIOCGTUNER32 _IOWR('v', 4, struct video_tuner32)
...@@ -739,7 +746,7 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar ...@@ -739,7 +746,7 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar
struct video_tuner vt; struct video_tuner vt;
struct video_buffer vb; struct video_buffer vb;
struct video_window vw; struct video_window vw;
struct video_code vc; struct video_code32 vc;
struct video_audio va; struct video_audio va;
#endif #endif
struct v4l2_format v2f; struct v4l2_format v2f;
...@@ -818,8 +825,11 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar ...@@ -818,8 +825,11 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar
break; break;
case VIDIOCSMICROCODE: case VIDIOCSMICROCODE:
err = get_microcode32(&karg.vc, up); /* Copy the 32-bit "video_code32" to kernel space */
compatible_arg = 0; if (copy_from_user(&karg.vc, up, sizeof(karg.vc)))
return -EFAULT;
/* Convert the 32-bit version to a 64-bit version in user space */
up = get_microcode32(&karg.vc);
break; break;
case VIDIOCSFREQ: case VIDIOCSFREQ:
......
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