Skip to content

Commit 3e645d6

Browse files
committed
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>
1 parent 799c105 commit 3e645d6

File tree

1 file changed

+21
-11
lines changed

1 file changed

+21
-11
lines changed

drivers/media/video/v4l2-compat-ioctl32.c

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -193,17 +193,24 @@ static int put_video_window32(struct video_window *kp, struct video_window32 __u
193193
struct video_code32 {
194194
char loadwhat[16]; /* name or tag of file being passed */
195195
compat_int_t datasize;
196-
unsigned char *data;
196+
compat_uptr_t data;
197197
};
198198

199-
static int get_microcode32(struct video_code *kp, struct video_code32 __user *up)
199+
static struct video_code __user *get_microcode32(struct video_code32 *kp)
200200
{
201-
if (!access_ok(VERIFY_READ, up, sizeof(struct video_code32)) ||
202-
copy_from_user(kp->loadwhat, up->loadwhat, sizeof(up->loadwhat)) ||
203-
get_user(kp->datasize, &up->datasize) ||
204-
copy_from_user(kp->data, up->data, up->datasize))
205-
return -EFAULT;
206-
return 0;
201+
struct video_code __user *up;
202+
203+
up = compat_alloc_user_space(sizeof(*up));
204+
205+
/*
206+
* NOTE! We don't actually care if these fail. If the
207+
* user address is invalid, the native ioctl will do
208+
* the error handling for us
209+
*/
210+
(void) copy_to_user(up->loadwhat, kp->loadwhat, sizeof(up->loadwhat));
211+
(void) put_user(kp->datasize, &up->datasize);
212+
(void) put_user(compat_ptr(kp->data), &up->data);
213+
return up;
207214
}
208215

209216
#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
739746
struct video_tuner vt;
740747
struct video_buffer vb;
741748
struct video_window vw;
742-
struct video_code vc;
749+
struct video_code32 vc;
743750
struct video_audio va;
744751
#endif
745752
struct v4l2_format v2f;
@@ -818,8 +825,11 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar
818825
break;
819826

820827
case VIDIOCSMICROCODE:
821-
err = get_microcode32(&karg.vc, up);
822-
compatible_arg = 0;
828+
/* Copy the 32-bit "video_code32" to kernel space */
829+
if (copy_from_user(&karg.vc, up, sizeof(karg.vc)))
830+
return -EFAULT;
831+
/* Convert the 32-bit version to a 64-bit version in user space */
832+
up = get_microcode32(&karg.vc);
823833
break;
824834

825835
case VIDIOCSFREQ:

0 commit comments

Comments
 (0)