Commit c17536d0 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Greg Kroah-Hartman

usb: usbfs: stop using compat_alloc_user_space

Just switch the low-level routines to take kernel structures, and do the
conversion from the compat to the native structure on that.
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Link: https://lore.kernel.org/r/20200722073655.220011-1-hch@lst.deSigned-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 6c9a9a8d
...@@ -1102,22 +1102,20 @@ static int usbdev_release(struct inode *inode, struct file *file) ...@@ -1102,22 +1102,20 @@ static int usbdev_release(struct inode *inode, struct file *file)
return 0; return 0;
} }
static int proc_control(struct usb_dev_state *ps, void __user *arg) static int do_proc_control(struct usb_dev_state *ps,
struct usbdevfs_ctrltransfer *ctrl)
{ {
struct usb_device *dev = ps->dev; struct usb_device *dev = ps->dev;
struct usbdevfs_ctrltransfer ctrl;
unsigned int tmo; unsigned int tmo;
unsigned char *tbuf; unsigned char *tbuf;
unsigned wLength; unsigned wLength;
int i, pipe, ret; int i, pipe, ret;
if (copy_from_user(&ctrl, arg, sizeof(ctrl))) ret = check_ctrlrecip(ps, ctrl->bRequestType, ctrl->bRequest,
return -EFAULT; ctrl->wIndex);
ret = check_ctrlrecip(ps, ctrl.bRequestType, ctrl.bRequest,
ctrl.wIndex);
if (ret) if (ret)
return ret; return ret;
wLength = ctrl.wLength; /* To suppress 64k PAGE_SIZE warning */ wLength = ctrl->wLength; /* To suppress 64k PAGE_SIZE warning */
if (wLength > PAGE_SIZE) if (wLength > PAGE_SIZE)
return -EINVAL; return -EINVAL;
ret = usbfs_increase_memory_usage(PAGE_SIZE + sizeof(struct urb) + ret = usbfs_increase_memory_usage(PAGE_SIZE + sizeof(struct urb) +
...@@ -1129,52 +1127,52 @@ static int proc_control(struct usb_dev_state *ps, void __user *arg) ...@@ -1129,52 +1127,52 @@ static int proc_control(struct usb_dev_state *ps, void __user *arg)
ret = -ENOMEM; ret = -ENOMEM;
goto done; goto done;
} }
tmo = ctrl.timeout; tmo = ctrl->timeout;
snoop(&dev->dev, "control urb: bRequestType=%02x " snoop(&dev->dev, "control urb: bRequestType=%02x "
"bRequest=%02x wValue=%04x " "bRequest=%02x wValue=%04x "
"wIndex=%04x wLength=%04x\n", "wIndex=%04x wLength=%04x\n",
ctrl.bRequestType, ctrl.bRequest, ctrl.wValue, ctrl->bRequestType, ctrl->bRequest, ctrl->wValue,
ctrl.wIndex, ctrl.wLength); ctrl->wIndex, ctrl->wLength);
if (ctrl.bRequestType & 0x80) { if (ctrl->bRequestType & 0x80) {
pipe = usb_rcvctrlpipe(dev, 0); pipe = usb_rcvctrlpipe(dev, 0);
snoop_urb(dev, NULL, pipe, ctrl.wLength, tmo, SUBMIT, NULL, 0); snoop_urb(dev, NULL, pipe, ctrl->wLength, tmo, SUBMIT, NULL, 0);
usb_unlock_device(dev); usb_unlock_device(dev);
i = usb_control_msg(dev, pipe, ctrl.bRequest, i = usb_control_msg(dev, pipe, ctrl->bRequest,
ctrl.bRequestType, ctrl.wValue, ctrl.wIndex, ctrl->bRequestType, ctrl->wValue, ctrl->wIndex,
tbuf, ctrl.wLength, tmo); tbuf, ctrl->wLength, tmo);
usb_lock_device(dev); usb_lock_device(dev);
snoop_urb(dev, NULL, pipe, max(i, 0), min(i, 0), COMPLETE, snoop_urb(dev, NULL, pipe, max(i, 0), min(i, 0), COMPLETE,
tbuf, max(i, 0)); tbuf, max(i, 0));
if ((i > 0) && ctrl.wLength) { if ((i > 0) && ctrl->wLength) {
if (copy_to_user(ctrl.data, tbuf, i)) { if (copy_to_user(ctrl->data, tbuf, i)) {
ret = -EFAULT; ret = -EFAULT;
goto done; goto done;
} }
} }
} else { } else {
if (ctrl.wLength) { if (ctrl->wLength) {
if (copy_from_user(tbuf, ctrl.data, ctrl.wLength)) { if (copy_from_user(tbuf, ctrl->data, ctrl->wLength)) {
ret = -EFAULT; ret = -EFAULT;
goto done; goto done;
} }
} }
pipe = usb_sndctrlpipe(dev, 0); pipe = usb_sndctrlpipe(dev, 0);
snoop_urb(dev, NULL, pipe, ctrl.wLength, tmo, SUBMIT, snoop_urb(dev, NULL, pipe, ctrl->wLength, tmo, SUBMIT,
tbuf, ctrl.wLength); tbuf, ctrl->wLength);
usb_unlock_device(dev); usb_unlock_device(dev);
i = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), ctrl.bRequest, i = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), ctrl->bRequest,
ctrl.bRequestType, ctrl.wValue, ctrl.wIndex, ctrl->bRequestType, ctrl->wValue, ctrl->wIndex,
tbuf, ctrl.wLength, tmo); tbuf, ctrl->wLength, tmo);
usb_lock_device(dev); usb_lock_device(dev);
snoop_urb(dev, NULL, pipe, max(i, 0), min(i, 0), COMPLETE, NULL, 0); snoop_urb(dev, NULL, pipe, max(i, 0), min(i, 0), COMPLETE, NULL, 0);
} }
if (i < 0 && i != -EPIPE) { if (i < 0 && i != -EPIPE) {
dev_printk(KERN_DEBUG, &dev->dev, "usbfs: USBDEVFS_CONTROL " dev_printk(KERN_DEBUG, &dev->dev, "usbfs: USBDEVFS_CONTROL "
"failed cmd %s rqt %u rq %u len %u ret %d\n", "failed cmd %s rqt %u rq %u len %u ret %d\n",
current->comm, ctrl.bRequestType, ctrl.bRequest, current->comm, ctrl->bRequestType, ctrl->bRequest,
ctrl.wLength, i); ctrl->wLength, i);
} }
ret = i; ret = i;
done: done:
...@@ -1184,30 +1182,37 @@ static int proc_control(struct usb_dev_state *ps, void __user *arg) ...@@ -1184,30 +1182,37 @@ static int proc_control(struct usb_dev_state *ps, void __user *arg)
return ret; return ret;
} }
static int proc_bulk(struct usb_dev_state *ps, void __user *arg) static int proc_control(struct usb_dev_state *ps, void __user *arg)
{
struct usbdevfs_ctrltransfer ctrl;
if (copy_from_user(&ctrl, arg, sizeof(ctrl)))
return -EFAULT;
return do_proc_control(ps, &ctrl);
}
static int do_proc_bulk(struct usb_dev_state *ps,
struct usbdevfs_bulktransfer *bulk)
{ {
struct usb_device *dev = ps->dev; struct usb_device *dev = ps->dev;
struct usbdevfs_bulktransfer bulk;
unsigned int tmo, len1, pipe; unsigned int tmo, len1, pipe;
int len2; int len2;
unsigned char *tbuf; unsigned char *tbuf;
int i, ret; int i, ret;
if (copy_from_user(&bulk, arg, sizeof(bulk))) ret = findintfep(ps->dev, bulk->ep);
return -EFAULT;
ret = findintfep(ps->dev, bulk.ep);
if (ret < 0) if (ret < 0)
return ret; return ret;
ret = checkintf(ps, ret); ret = checkintf(ps, ret);
if (ret) if (ret)
return ret; return ret;
if (bulk.ep & USB_DIR_IN) if (bulk->ep & USB_DIR_IN)
pipe = usb_rcvbulkpipe(dev, bulk.ep & 0x7f); pipe = usb_rcvbulkpipe(dev, bulk->ep & 0x7f);
else else
pipe = usb_sndbulkpipe(dev, bulk.ep & 0x7f); pipe = usb_sndbulkpipe(dev, bulk->ep & 0x7f);
if (!usb_maxpacket(dev, pipe, !(bulk.ep & USB_DIR_IN))) if (!usb_maxpacket(dev, pipe, !(bulk->ep & USB_DIR_IN)))
return -EINVAL; return -EINVAL;
len1 = bulk.len; len1 = bulk->len;
if (len1 >= (INT_MAX - sizeof(struct urb))) if (len1 >= (INT_MAX - sizeof(struct urb)))
return -EINVAL; return -EINVAL;
ret = usbfs_increase_memory_usage(len1 + sizeof(struct urb)); ret = usbfs_increase_memory_usage(len1 + sizeof(struct urb));
...@@ -1218,8 +1223,8 @@ static int proc_bulk(struct usb_dev_state *ps, void __user *arg) ...@@ -1218,8 +1223,8 @@ static int proc_bulk(struct usb_dev_state *ps, void __user *arg)
ret = -ENOMEM; ret = -ENOMEM;
goto done; goto done;
} }
tmo = bulk.timeout; tmo = bulk->timeout;
if (bulk.ep & 0x80) { if (bulk->ep & 0x80) {
snoop_urb(dev, NULL, pipe, len1, tmo, SUBMIT, NULL, 0); snoop_urb(dev, NULL, pipe, len1, tmo, SUBMIT, NULL, 0);
usb_unlock_device(dev); usb_unlock_device(dev);
...@@ -1228,14 +1233,14 @@ static int proc_bulk(struct usb_dev_state *ps, void __user *arg) ...@@ -1228,14 +1233,14 @@ static int proc_bulk(struct usb_dev_state *ps, void __user *arg)
snoop_urb(dev, NULL, pipe, len2, i, COMPLETE, tbuf, len2); snoop_urb(dev, NULL, pipe, len2, i, COMPLETE, tbuf, len2);
if (!i && len2) { if (!i && len2) {
if (copy_to_user(bulk.data, tbuf, len2)) { if (copy_to_user(bulk->data, tbuf, len2)) {
ret = -EFAULT; ret = -EFAULT;
goto done; goto done;
} }
} }
} else { } else {
if (len1) { if (len1) {
if (copy_from_user(tbuf, bulk.data, len1)) { if (copy_from_user(tbuf, bulk->data, len1)) {
ret = -EFAULT; ret = -EFAULT;
goto done; goto done;
} }
...@@ -1254,6 +1259,15 @@ static int proc_bulk(struct usb_dev_state *ps, void __user *arg) ...@@ -1254,6 +1259,15 @@ static int proc_bulk(struct usb_dev_state *ps, void __user *arg)
return ret; return ret;
} }
static int proc_bulk(struct usb_dev_state *ps, void __user *arg)
{
struct usbdevfs_bulktransfer bulk;
if (copy_from_user(&bulk, arg, sizeof(bulk)))
return -EFAULT;
return do_proc_bulk(ps, &bulk);
}
static void check_reset_of_active_ep(struct usb_device *udev, static void check_reset_of_active_ep(struct usb_device *udev,
unsigned int epnum, char *ioctl_name) unsigned int epnum, char *ioctl_name)
{ {
...@@ -2013,33 +2027,31 @@ static int proc_reapurbnonblock(struct usb_dev_state *ps, void __user *arg) ...@@ -2013,33 +2027,31 @@ static int proc_reapurbnonblock(struct usb_dev_state *ps, void __user *arg)
static int proc_control_compat(struct usb_dev_state *ps, static int proc_control_compat(struct usb_dev_state *ps,
struct usbdevfs_ctrltransfer32 __user *p32) struct usbdevfs_ctrltransfer32 __user *p32)
{ {
struct usbdevfs_ctrltransfer __user *p; struct usbdevfs_ctrltransfer ctrl;
__u32 udata; u32 udata;
p = compat_alloc_user_space(sizeof(*p));
if (copy_in_user(p, p32, (sizeof(*p32) - sizeof(compat_caddr_t))) || if (copy_from_user(&ctrl, p32, sizeof(*p32) - sizeof(compat_caddr_t)) ||
get_user(udata, &p32->data) || get_user(udata, &p32->data))
put_user(compat_ptr(udata), &p->data))
return -EFAULT; return -EFAULT;
return proc_control(ps, p); ctrl.data = compat_ptr(udata);
return do_proc_control(ps, &ctrl);
} }
static int proc_bulk_compat(struct usb_dev_state *ps, static int proc_bulk_compat(struct usb_dev_state *ps,
struct usbdevfs_bulktransfer32 __user *p32) struct usbdevfs_bulktransfer32 __user *p32)
{ {
struct usbdevfs_bulktransfer __user *p; struct usbdevfs_bulktransfer bulk;
compat_uint_t n;
compat_caddr_t addr; compat_caddr_t addr;
p = compat_alloc_user_space(sizeof(*p)); if (get_user(bulk.ep, &p32->ep) ||
get_user(bulk.len, &p32->len) ||
if (get_user(n, &p32->ep) || put_user(n, &p->ep) || get_user(bulk.timeout, &p32->timeout) ||
get_user(n, &p32->len) || put_user(n, &p->len) || get_user(addr, &p32->data))
get_user(n, &p32->timeout) || put_user(n, &p->timeout) ||
get_user(addr, &p32->data) || put_user(compat_ptr(addr), &p->data))
return -EFAULT; return -EFAULT;
bulk.data = compat_ptr(addr);
return proc_bulk(ps, p); return do_proc_bulk(ps, &bulk);
} }
static int proc_disconnectsignal_compat(struct usb_dev_state *ps, void __user *arg) static int proc_disconnectsignal_compat(struct usb_dev_state *ps, void __user *arg)
{ {
struct usbdevfs_disconnectsignal32 ds; struct usbdevfs_disconnectsignal32 ds;
......
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