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: