Skip to content

Commit 822a2e4

Browse files
committed
Merge branch 'fixes'
* fixes: v4l1: fix 32-bit compat microcode loading translation De-pessimize rds_page_copy_user
2 parents 2b666ca + 3e645d6 commit 822a2e4

File tree

2 files changed

+28
-31
lines changed

2 files changed

+28
-31
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:

net/rds/page.c

Lines changed: 7 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -57,30 +57,17 @@ int rds_page_copy_user(struct page *page, unsigned long offset,
5757
unsigned long ret;
5858
void *addr;
5959

60-
if (to_user)
60+
addr = kmap(page);
61+
if (to_user) {
6162
rds_stats_add(s_copy_to_user, bytes);
62-
else
63+
ret = copy_to_user(ptr, addr + offset, bytes);
64+
} else {
6365
rds_stats_add(s_copy_from_user, bytes);
64-
65-
addr = kmap_atomic(page, KM_USER0);
66-
if (to_user)
67-
ret = __copy_to_user_inatomic(ptr, addr + offset, bytes);
68-
else
69-
ret = __copy_from_user_inatomic(addr + offset, ptr, bytes);
70-
kunmap_atomic(addr, KM_USER0);
71-
72-
if (ret) {
73-
addr = kmap(page);
74-
if (to_user)
75-
ret = copy_to_user(ptr, addr + offset, bytes);
76-
else
77-
ret = copy_from_user(addr + offset, ptr, bytes);
78-
kunmap(page);
79-
if (ret)
80-
return -EFAULT;
66+
ret = copy_from_user(addr + offset, ptr, bytes);
8167
}
68+
kunmap(page);
8269

83-
return 0;
70+
return ret ? -EFAULT : 0;
8471
}
8572
EXPORT_SYMBOL_GPL(rds_page_copy_user);
8673

0 commit comments

Comments
 (0)