* fixes:
  v4l1: fix 32-bit compat microcode loading translation
  De-pessimize rds_page_copy_user
This commit is contained in:
Linus Torvalds 2010-10-18 13:04:33 -07:00
Родитель 2b666ca4a6 3e645d6b48
Коммит 822a2e4524
2 изменённых файлов: 28 добавлений и 31 удалений

Просмотреть файл

@ -193,17 +193,24 @@ static int put_video_window32(struct video_window *kp, struct video_window32 __u
struct video_code32 { struct video_code32 {
char loadwhat[16]; /* name or tag of file being passed */ char loadwhat[16]; /* name or tag of file being passed */
compat_int_t datasize; 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)) || struct video_code __user *up;
copy_from_user(kp->loadwhat, up->loadwhat, sizeof(up->loadwhat)) ||
get_user(kp->datasize, &up->datasize) || up = compat_alloc_user_space(sizeof(*up));
copy_from_user(kp->data, up->data, up->datasize))
return -EFAULT; /*
return 0; * 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) #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_tuner vt;
struct video_buffer vb; struct video_buffer vb;
struct video_window vw; struct video_window vw;
struct video_code vc; struct video_code32 vc;
struct video_audio va; struct video_audio va;
#endif #endif
struct v4l2_format v2f; struct v4l2_format v2f;
@ -818,8 +825,11 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar
break; break;
case VIDIOCSMICROCODE: case VIDIOCSMICROCODE:
err = get_microcode32(&karg.vc, up); /* Copy the 32-bit "video_code32" to kernel space */
compatible_arg = 0; 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; break;
case VIDIOCSFREQ: case VIDIOCSFREQ:

Просмотреть файл

@ -57,30 +57,17 @@ int rds_page_copy_user(struct page *page, unsigned long offset,
unsigned long ret; unsigned long ret;
void *addr; void *addr;
if (to_user) addr = kmap(page);
if (to_user) {
rds_stats_add(s_copy_to_user, bytes); rds_stats_add(s_copy_to_user, bytes);
else ret = copy_to_user(ptr, addr + offset, bytes);
} else {
rds_stats_add(s_copy_from_user, bytes); rds_stats_add(s_copy_from_user, bytes);
ret = copy_from_user(addr + offset, ptr, bytes);
addr = kmap_atomic(page, KM_USER0);
if (to_user)
ret = __copy_to_user_inatomic(ptr, addr + offset, bytes);
else
ret = __copy_from_user_inatomic(addr + offset, ptr, bytes);
kunmap_atomic(addr, KM_USER0);
if (ret) {
addr = kmap(page);
if (to_user)
ret = copy_to_user(ptr, addr + offset, bytes);
else
ret = copy_from_user(addr + offset, ptr, bytes);
kunmap(page);
if (ret)
return -EFAULT;
} }
kunmap(page);
return 0; return ret ? -EFAULT : 0;
} }
EXPORT_SYMBOL_GPL(rds_page_copy_user); EXPORT_SYMBOL_GPL(rds_page_copy_user);