|
Chuck Ebbert |
643d353 |
From 3e645d6b485446c54c6745c5e2cf5c528fe4deec Mon Sep 17 00:00:00 2001
|
|
Chuck Ebbert |
643d353 |
From: Linus Torvalds <torvalds@linux-foundation.org>
|
|
Chuck Ebbert |
643d353 |
Date: Fri, 15 Oct 2010 11:12:38 -0700
|
|
Chuck Ebbert |
643d353 |
Subject: v4l1: fix 32-bit compat microcode loading translation
|
|
Chuck Ebbert |
643d353 |
|
|
Chuck Ebbert |
643d353 |
From: Linus Torvalds <torvalds@linux-foundation.org>
|
|
Chuck Ebbert |
643d353 |
|
|
Chuck Ebbert |
643d353 |
commit 3e645d6b485446c54c6745c5e2cf5c528fe4deec upstream.
|
|
Chuck Ebbert |
643d353 |
|
|
Chuck Ebbert |
643d353 |
The compat code for the VIDIOCSMICROCODE ioctl is totally buggered.
|
|
Chuck Ebbert |
643d353 |
It's only used by the VIDEO_STRADIS driver, and that one is scheduled to
|
|
Chuck Ebbert |
643d353 |
staging and eventually removed unless somebody steps up to maintain it
|
|
Chuck Ebbert |
643d353 |
(at which point it should use request_firmware() rather than some magic
|
|
Chuck Ebbert |
643d353 |
ioctl). So we'll get rid of it eventually.
|
|
Chuck Ebbert |
643d353 |
|
|
Chuck Ebbert |
643d353 |
But in the meantime, the compatibility ioctl code is broken, and this
|
|
Chuck Ebbert |
643d353 |
tries to get it to at least limp along (even if Mauro suggested just
|
|
Chuck Ebbert |
643d353 |
deleting it entirely, which may be the right thing to do - I don't think
|
|
Chuck Ebbert |
643d353 |
the compatibility translation code has ever worked unless you were very
|
|
Chuck Ebbert |
643d353 |
lucky).
|
|
Chuck Ebbert |
643d353 |
|
|
Chuck Ebbert |
643d353 |
Reported-by: Kees Cook <kees.cook@canonical.com>
|
|
Chuck Ebbert |
643d353 |
Cc: Mauro Carvalho Chehab <mchehab@infradead.org>
|
|
Chuck Ebbert |
643d353 |
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
|
|
Chuck Ebbert |
643d353 |
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
|
|
Chuck Ebbert |
643d353 |
|
|
Chuck Ebbert |
643d353 |
---
|
|
Chuck Ebbert |
643d353 |
drivers/media/video/v4l2-compat-ioctl32.c | 32 +++++++++++++++++++-----------
|
|
Chuck Ebbert |
643d353 |
1 file changed, 21 insertions(+), 11 deletions(-)
|
|
Chuck Ebbert |
643d353 |
|
|
Chuck Ebbert |
643d353 |
--- a/drivers/media/video/v4l2-compat-ioctl32.c
|
|
Chuck Ebbert |
643d353 |
+++ b/drivers/media/video/v4l2-compat-ioctl32.c
|
|
Chuck Ebbert |
643d353 |
@@ -193,17 +193,24 @@ static int put_video_window32(struct vid
|
|
Chuck Ebbert |
643d353 |
struct video_code32 {
|
|
Chuck Ebbert |
643d353 |
char loadwhat[16]; /* name or tag of file being passed */
|
|
Chuck Ebbert |
643d353 |
compat_int_t datasize;
|
|
Chuck Ebbert |
643d353 |
- unsigned char *data;
|
|
Chuck Ebbert |
643d353 |
+ compat_uptr_t data;
|
|
Chuck Ebbert |
643d353 |
};
|
|
Chuck Ebbert |
643d353 |
|
|
Chuck Ebbert |
643d353 |
-static int get_microcode32(struct video_code *kp, struct video_code32 __user *up)
|
|
Chuck Ebbert |
643d353 |
+static struct video_code __user *get_microcode32(struct video_code32 *kp)
|
|
Chuck Ebbert |
643d353 |
{
|
|
Chuck Ebbert |
643d353 |
- if (!access_ok(VERIFY_READ, up, sizeof(struct video_code32)) ||
|
|
Chuck Ebbert |
643d353 |
- copy_from_user(kp->loadwhat, up->loadwhat, sizeof(up->loadwhat)) ||
|
|
Chuck Ebbert |
643d353 |
- get_user(kp->datasize, &up->datasize) ||
|
|
Chuck Ebbert |
643d353 |
- copy_from_user(kp->data, up->data, up->datasize))
|
|
Chuck Ebbert |
643d353 |
- return -EFAULT;
|
|
Chuck Ebbert |
643d353 |
- return 0;
|
|
Chuck Ebbert |
643d353 |
+ struct video_code __user *up;
|
|
Chuck Ebbert |
643d353 |
+
|
|
Chuck Ebbert |
643d353 |
+ up = compat_alloc_user_space(sizeof(*up));
|
|
Chuck Ebbert |
643d353 |
+
|
|
Chuck Ebbert |
643d353 |
+ /*
|
|
Chuck Ebbert |
643d353 |
+ * NOTE! We don't actually care if these fail. If the
|
|
Chuck Ebbert |
643d353 |
+ * user address is invalid, the native ioctl will do
|
|
Chuck Ebbert |
643d353 |
+ * the error handling for us
|
|
Chuck Ebbert |
643d353 |
+ */
|
|
Chuck Ebbert |
643d353 |
+ (void) copy_to_user(up->loadwhat, kp->loadwhat, sizeof(up->loadwhat));
|
|
Chuck Ebbert |
643d353 |
+ (void) put_user(kp->datasize, &up->datasize);
|
|
Chuck Ebbert |
643d353 |
+ (void) put_user(compat_ptr(kp->data), &up->data);
|
|
Chuck Ebbert |
643d353 |
+ return up;
|
|
Chuck Ebbert |
643d353 |
}
|
|
Chuck Ebbert |
643d353 |
|
|
Chuck Ebbert |
643d353 |
#define VIDIOCGTUNER32 _IOWR('v', 4, struct video_tuner32)
|
|
Chuck Ebbert |
643d353 |
@@ -744,7 +751,7 @@ static long do_video_ioctl(struct file *
|
|
Chuck Ebbert |
643d353 |
struct video_tuner vt;
|
|
Chuck Ebbert |
643d353 |
struct video_buffer vb;
|
|
Chuck Ebbert |
643d353 |
struct video_window vw;
|
|
Chuck Ebbert |
643d353 |
- struct video_code vc;
|
|
Chuck Ebbert |
643d353 |
+ struct video_code32 vc;
|
|
Chuck Ebbert |
643d353 |
struct video_audio va;
|
|
Chuck Ebbert |
643d353 |
#endif
|
|
Chuck Ebbert |
643d353 |
struct v4l2_format v2f;
|
|
Chuck Ebbert |
643d353 |
@@ -823,8 +830,11 @@ static long do_video_ioctl(struct file *
|
|
Chuck Ebbert |
643d353 |
break;
|
|
Chuck Ebbert |
643d353 |
|
|
Chuck Ebbert |
643d353 |
case VIDIOCSMICROCODE:
|
|
Chuck Ebbert |
643d353 |
- err = get_microcode32(&karg.vc, up);
|
|
Chuck Ebbert |
643d353 |
- compatible_arg = 0;
|
|
Chuck Ebbert |
643d353 |
+ /* Copy the 32-bit "video_code32" to kernel space */
|
|
Chuck Ebbert |
643d353 |
+ if (copy_from_user(&karg.vc, up, sizeof(karg.vc)))
|
|
Chuck Ebbert |
643d353 |
+ return -EFAULT;
|
|
Chuck Ebbert |
643d353 |
+ /* Convert the 32-bit version to a 64-bit version in user space */
|
|
Chuck Ebbert |
643d353 |
+ up = get_microcode32(&karg.vc);
|
|
Chuck Ebbert |
643d353 |
break;
|
|
Chuck Ebbert |
643d353 |
|
|
Chuck Ebbert |
643d353 |
case VIDIOCSFREQ:
|