87 lines
3.3 KiB
Diff
87 lines
3.3 KiB
Diff
From: Linus Torvalds <torvalds@linux-foundation.org>
|
|
Date: Fri, 15 Oct 2010 18:12:38 +0000 (-0700)
|
|
Subject: v4l1: fix 32-bit compat microcode loading translation
|
|
X-Git-Tag: v2.6.36~11^2
|
|
X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=3e645d6b485446c54c6745c5e2cf5c528fe4deec
|
|
|
|
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: Kees Cook <kees.cook@canonical.com>
|
|
Cc: Mauro Carvalho Chehab <mchehab@infradead.org>
|
|
Cc: stable@kernel.org
|
|
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
|
|
---
|
|
|
|
diff --git a/drivers/media/video/v4l2-compat-ioctl32.c b/drivers/media/video/v4l2-compat-ioctl32.c
|
|
index 073f013..86294ed3 100644
|
|
--- 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 video_window *kp, struct video_window32 __u
|
|
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)
|
|
@@ -739,7 +746,7 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar
|
|
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;
|
|
@@ -818,8 +825,11 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar
|
|
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:
|