89 lines
3.2 KiB
Diff
89 lines
3.2 KiB
Diff
From 3e645d6b485446c54c6745c5e2cf5c528fe4deec Mon Sep 17 00:00:00 2001
|
|
From: Linus Torvalds <torvalds@linux-foundation.org>
|
|
Date: Fri, 15 Oct 2010 11:12:38 -0700
|
|
Subject: v4l1: fix 32-bit compat microcode loading translation
|
|
|
|
From: Linus Torvalds <torvalds@linux-foundation.org>
|
|
|
|
commit 3e645d6b485446c54c6745c5e2cf5c528fe4deec upstream.
|
|
|
|
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: Kees Cook <kees.cook@canonical.com>
|
|
Cc: Mauro Carvalho Chehab <mchehab@infradead.org>
|
|
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
|
|
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
|
|
|
|
---
|
|
drivers/media/video/v4l2-compat-ioctl32.c | 32 +++++++++++++++++++-----------
|
|
1 file changed, 21 insertions(+), 11 deletions(-)
|
|
|
|
--- a/drivers/media/video/v4l2-compat-ioctl32.c
|
|
+++ b/drivers/media/video/v4l2-compat-ioctl32.c
|
|
@@ -193,17 +193,24 @@ static int put_video_window32(struct vid
|
|
struct video_code32 {
|
|
char loadwhat[16]; /* name or tag of file being passed */
|
|
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)) ||
|
|
- copy_from_user(kp->loadwhat, up->loadwhat, sizeof(up->loadwhat)) ||
|
|
- get_user(kp->datasize, &up->datasize) ||
|
|
- copy_from_user(kp->data, up->data, up->datasize))
|
|
- return -EFAULT;
|
|
- return 0;
|
|
+ struct video_code __user *up;
|
|
+
|
|
+ up = compat_alloc_user_space(sizeof(*up));
|
|
+
|
|
+ /*
|
|
+ * 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)
|
|
@@ -744,7 +751,7 @@ static long do_video_ioctl(struct file *
|
|
struct video_tuner vt;
|
|
struct video_buffer vb;
|
|
struct video_window vw;
|
|
- struct video_code vc;
|
|
+ struct video_code32 vc;
|
|
struct video_audio va;
|
|
#endif
|
|
struct v4l2_format v2f;
|
|
@@ -823,8 +830,11 @@ static long do_video_ioctl(struct file *
|
|
break;
|
|
|
|
case VIDIOCSMICROCODE:
|
|
- err = get_microcode32(&karg.vc, up);
|
|
- compatible_arg = 0;
|
|
+ /* Copy the 32-bit "video_code32" to kernel space */
|
|
+ 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;
|
|
|
|
case VIDIOCSFREQ:
|