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

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.de


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 6c9a9a8d
Loading
Loading
Loading
Loading
+69 −57
Original line number Diff line number Diff line
@@ -1102,22 +1102,20 @@ static int usbdev_release(struct inode *inode, struct file *file)
	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 usbdevfs_ctrltransfer ctrl;
	unsigned int tmo;
	unsigned char *tbuf;
	unsigned wLength;
	int i, pipe, ret;

	if (copy_from_user(&ctrl, arg, sizeof(ctrl)))
		return -EFAULT;
	ret = check_ctrlrecip(ps, ctrl.bRequestType, ctrl.bRequest,
			      ctrl.wIndex);
	ret = check_ctrlrecip(ps, ctrl->bRequestType, ctrl->bRequest,
			      ctrl->wIndex);
	if (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)
		return -EINVAL;
	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)
		ret = -ENOMEM;
		goto done;
	}
	tmo = ctrl.timeout;
	tmo = ctrl->timeout;
	snoop(&dev->dev, "control urb: bRequestType=%02x "
		"bRequest=%02x wValue=%04x "
		"wIndex=%04x wLength=%04x\n",
		ctrl.bRequestType, ctrl.bRequest, ctrl.wValue,
		ctrl.wIndex, ctrl.wLength);
	if (ctrl.bRequestType & 0x80) {
		ctrl->bRequestType, ctrl->bRequest, ctrl->wValue,
		ctrl->wIndex, ctrl->wLength);
	if (ctrl->bRequestType & 0x80) {
		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);
		i = usb_control_msg(dev, pipe, ctrl.bRequest,
				    ctrl.bRequestType, ctrl.wValue, ctrl.wIndex,
				    tbuf, ctrl.wLength, tmo);
		i = usb_control_msg(dev, pipe, ctrl->bRequest,
				    ctrl->bRequestType, ctrl->wValue, ctrl->wIndex,
				    tbuf, ctrl->wLength, tmo);
		usb_lock_device(dev);
		snoop_urb(dev, NULL, pipe, max(i, 0), min(i, 0), COMPLETE,
			  tbuf, max(i, 0));
		if ((i > 0) && ctrl.wLength) {
			if (copy_to_user(ctrl.data, tbuf, i)) {
		if ((i > 0) && ctrl->wLength) {
			if (copy_to_user(ctrl->data, tbuf, i)) {
				ret = -EFAULT;
				goto done;
			}
		}
	} else {
		if (ctrl.wLength) {
			if (copy_from_user(tbuf, ctrl.data, ctrl.wLength)) {
		if (ctrl->wLength) {
			if (copy_from_user(tbuf, ctrl->data, ctrl->wLength)) {
				ret = -EFAULT;
				goto done;
			}
		}
		pipe = usb_sndctrlpipe(dev, 0);
		snoop_urb(dev, NULL, pipe, ctrl.wLength, tmo, SUBMIT,
			tbuf, ctrl.wLength);
		snoop_urb(dev, NULL, pipe, ctrl->wLength, tmo, SUBMIT,
			tbuf, ctrl->wLength);

		usb_unlock_device(dev);
		i = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), ctrl.bRequest,
				    ctrl.bRequestType, ctrl.wValue, ctrl.wIndex,
				    tbuf, ctrl.wLength, tmo);
		i = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), ctrl->bRequest,
				    ctrl->bRequestType, ctrl->wValue, ctrl->wIndex,
				    tbuf, ctrl->wLength, tmo);
		usb_lock_device(dev);
		snoop_urb(dev, NULL, pipe, max(i, 0), min(i, 0), COMPLETE, NULL, 0);
	}
	if (i < 0 && i != -EPIPE) {
		dev_printk(KERN_DEBUG, &dev->dev, "usbfs: USBDEVFS_CONTROL "
			   "failed cmd %s rqt %u rq %u len %u ret %d\n",
			   current->comm, ctrl.bRequestType, ctrl.bRequest,
			   ctrl.wLength, i);
			   current->comm, ctrl->bRequestType, ctrl->bRequest,
			   ctrl->wLength, i);
	}
	ret = i;
 done:
@@ -1184,30 +1182,37 @@ static int proc_control(struct usb_dev_state *ps, void __user *arg)
	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 usbdevfs_bulktransfer bulk;
	unsigned int tmo, len1, pipe;
	int len2;
	unsigned char *tbuf;
	int i, ret;

	if (copy_from_user(&bulk, arg, sizeof(bulk)))
		return -EFAULT;
	ret = findintfep(ps->dev, bulk.ep);
	ret = findintfep(ps->dev, bulk->ep);
	if (ret < 0)
		return ret;
	ret = checkintf(ps, ret);
	if (ret)
		return ret;
	if (bulk.ep & USB_DIR_IN)
		pipe = usb_rcvbulkpipe(dev, bulk.ep & 0x7f);
	if (bulk->ep & USB_DIR_IN)
		pipe = usb_rcvbulkpipe(dev, bulk->ep & 0x7f);
	else
		pipe = usb_sndbulkpipe(dev, bulk.ep & 0x7f);
	if (!usb_maxpacket(dev, pipe, !(bulk.ep & USB_DIR_IN)))
		pipe = usb_sndbulkpipe(dev, bulk->ep & 0x7f);
	if (!usb_maxpacket(dev, pipe, !(bulk->ep & USB_DIR_IN)))
		return -EINVAL;
	len1 = bulk.len;
	len1 = bulk->len;
	if (len1 >= (INT_MAX - sizeof(struct urb)))
		return -EINVAL;
	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)
		ret = -ENOMEM;
		goto done;
	}
	tmo = bulk.timeout;
	if (bulk.ep & 0x80) {
	tmo = bulk->timeout;
	if (bulk->ep & 0x80) {
		snoop_urb(dev, NULL, pipe, len1, tmo, SUBMIT, NULL, 0);

		usb_unlock_device(dev);
@@ -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);

		if (!i && len2) {
			if (copy_to_user(bulk.data, tbuf, len2)) {
			if (copy_to_user(bulk->data, tbuf, len2)) {
				ret = -EFAULT;
				goto done;
			}
		}
	} else {
		if (len1) {
			if (copy_from_user(tbuf, bulk.data, len1)) {
			if (copy_from_user(tbuf, bulk->data, len1)) {
				ret = -EFAULT;
				goto done;
			}
@@ -1254,6 +1259,15 @@ static int proc_bulk(struct usb_dev_state *ps, void __user *arg)
	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,
		unsigned int epnum, char *ioctl_name)
{
@@ -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,
				struct usbdevfs_ctrltransfer32 __user *p32)
{
	struct usbdevfs_ctrltransfer __user *p;
	__u32 udata;
	p = compat_alloc_user_space(sizeof(*p));
	if (copy_in_user(p, p32, (sizeof(*p32) - sizeof(compat_caddr_t))) ||
	    get_user(udata, &p32->data) ||
	    put_user(compat_ptr(udata), &p->data))
	struct usbdevfs_ctrltransfer ctrl;
	u32 udata;

	if (copy_from_user(&ctrl, p32, sizeof(*p32) - sizeof(compat_caddr_t)) ||
	    get_user(udata, &p32->data))
		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,
			struct usbdevfs_bulktransfer32 __user *p32)
{
	struct usbdevfs_bulktransfer __user *p;
	compat_uint_t n;
	struct usbdevfs_bulktransfer bulk;
	compat_caddr_t addr;

	p = compat_alloc_user_space(sizeof(*p));

	if (get_user(n, &p32->ep) || put_user(n, &p->ep) ||
	    get_user(n, &p32->len) || put_user(n, &p->len) ||
	    get_user(n, &p32->timeout) || put_user(n, &p->timeout) ||
	    get_user(addr, &p32->data) || put_user(compat_ptr(addr), &p->data))
	if (get_user(bulk.ep, &p32->ep) ||
	    get_user(bulk.len, &p32->len) ||
	    get_user(bulk.timeout, &p32->timeout) ||
	    get_user(addr, &p32->data))
		return -EFAULT;

	return proc_bulk(ps, p);
	bulk.data = compat_ptr(addr);
	return do_proc_bulk(ps, &bulk);
}

static int proc_disconnectsignal_compat(struct usb_dev_state *ps, void __user *arg)
{
	struct usbdevfs_disconnectsignal32 ds;