Commit 5ffdb755 authored by Alexander Viro's avatar Alexander Viro Committed by Linus Torvalds

[PATCH] sparse: usb ioctl cleanups

	usb ioctls in compat_ioctl.c switched to compat_alloc_user_space()
and cleaned up; ioctl structures annotated.
parent 3851523a
...@@ -2517,54 +2517,15 @@ struct usbdevfs_ctrltransfer32 { ...@@ -2517,54 +2517,15 @@ struct usbdevfs_ctrltransfer32 {
static int do_usbdevfs_control(unsigned int fd, unsigned int cmd, unsigned long arg) static int do_usbdevfs_control(unsigned int fd, unsigned int cmd, unsigned long arg)
{ {
struct usbdevfs_ctrltransfer kctrl; struct usbdevfs_ctrltransfer32 __user *p32 = compat_ptr(arg);
struct usbdevfs_ctrltransfer32 __user *uctrl; struct usbdevfs_ctrltransfer __user *p;
mm_segment_t old_fs;
__u32 udata; __u32 udata;
void __user *uptr; p = compat_alloc_user_space(sizeof(*p));
void *kptr; if (copy_in_user(p, p32, (sizeof(*p32) - sizeof(compat_caddr_t))) ||
int err; get_user(udata, &p32->data) ||
put_user(compat_ptr(udata), &p->data))
uctrl = compat_ptr(arg);
if (copy_from_user(&kctrl, uctrl,
(sizeof(struct usbdevfs_ctrltransfer32) -
sizeof(compat_caddr_t))))
return -EFAULT;
if (get_user(udata, &uctrl->data))
return -EFAULT; return -EFAULT;
uptr = compat_ptr(udata); return sys_ioctl(fd, USBDEVFS_CONTROL, (unsigned long)p);
/* In usbdevice_fs, it limits the control buffer to a page,
* for simplicity so do we.
*/
if (!uptr || kctrl.wLength > PAGE_SIZE)
return -EINVAL;
kptr = (void *)__get_free_page(GFP_KERNEL);
if ((kctrl.bRequestType & USB_DIR_IN) == 0) {
err = -EFAULT;
if (copy_from_user(kptr, uptr, kctrl.wLength))
goto out;
}
kctrl.data = kptr;
old_fs = get_fs();
set_fs(KERNEL_DS);
err = sys_ioctl(fd, USBDEVFS_CONTROL, (unsigned long)&kctrl);
set_fs(old_fs);
if (err >= 0 &&
((kctrl.bRequestType & USB_DIR_IN) != 0)) {
if (copy_to_user(uptr, kptr, kctrl.wLength))
err = -EFAULT;
}
out:
free_page((unsigned long) kptr);
return err;
} }
...@@ -2579,54 +2540,20 @@ struct usbdevfs_bulktransfer32 { ...@@ -2579,54 +2540,20 @@ struct usbdevfs_bulktransfer32 {
static int do_usbdevfs_bulk(unsigned int fd, unsigned int cmd, unsigned long arg) static int do_usbdevfs_bulk(unsigned int fd, unsigned int cmd, unsigned long arg)
{ {
struct usbdevfs_bulktransfer kbulk; struct usbdevfs_bulktransfer32 __user *p32 = compat_ptr(arg);
struct usbdevfs_bulktransfer32 __user *ubulk; struct usbdevfs_bulktransfer __user *p;
mm_segment_t old_fs; compat_uint_t n;
__u32 udata; compat_caddr_t addr;
void __user *uptr;
void *kptr;
int err;
ubulk = compat_ptr(arg); p = compat_alloc_user_space(sizeof(*p));
if (get_user(kbulk.ep, &ubulk->ep) || if (get_user(n, &p32->ep) || put_user(n, &p->ep) ||
get_user(kbulk.len, &ubulk->len) || get_user(n, &p32->len) || put_user(n, &p->len) ||
get_user(kbulk.timeout, &ubulk->timeout) || get_user(n, &p32->timeout) || put_user(n, &p->timeout) ||
get_user(udata, &ubulk->data)) get_user(addr, &p32->data) || put_user(compat_ptr(addr), &p->data))
return -EFAULT; return -EFAULT;
uptr = compat_ptr(udata); return sys_ioctl(fd, USBDEVFS_BULK, (unsigned long)p);
/* In usbdevice_fs, it limits the control buffer to a page,
* for simplicity so do we.
*/
if (!uptr || kbulk.len > PAGE_SIZE)
return -EINVAL;
kptr = (void *) __get_free_page(GFP_KERNEL);
if ((kbulk.ep & 0x80) == 0) {
err = -EFAULT;
if (copy_from_user(kptr, uptr, kbulk.len))
goto out;
}
kbulk.data = kptr;
old_fs = get_fs();
set_fs(KERNEL_DS);
err = sys_ioctl(fd, USBDEVFS_BULK, (unsigned long) &kbulk);
set_fs(old_fs);
if (err >= 0 &&
((kbulk.ep & 0x80) != 0)) {
if (copy_to_user(uptr, kptr, kbulk.len))
err = -EFAULT;
}
out:
free_page((unsigned long) kptr);
return err;
} }
/* This needs more work before we can enable it. Unfortunately /* This needs more work before we can enable it. Unfortunately
......
...@@ -63,7 +63,7 @@ struct usbdevfs_setinterface { ...@@ -63,7 +63,7 @@ struct usbdevfs_setinterface {
struct usbdevfs_disconnectsignal { struct usbdevfs_disconnectsignal {
unsigned int signr; unsigned int signr;
void *context; void __user *context;
}; };
#define USBDEVFS_MAXDRIVERNAME 255 #define USBDEVFS_MAXDRIVERNAME 255
...@@ -162,7 +162,7 @@ struct dev_state { ...@@ -162,7 +162,7 @@ struct dev_state {
wait_queue_head_t wait; /* wake up if a request completed */ wait_queue_head_t wait; /* wake up if a request completed */
unsigned int discsignr; unsigned int discsignr;
struct task_struct *disctask; struct task_struct *disctask;
void *disccontext; void __user *disccontext;
unsigned long ifclaimed; unsigned long ifclaimed;
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment