Re: [PATCH 1/1] Increase USB transfer limit

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Fri, 9 Dec 2016, Mateusz Berezecki wrote:

> On 9 Dec 2016, at 13:50, Alan Stern wrote:
> 
> > On Fri, 9 Dec 2016, Mateusz Berezecki wrote:
> >
> >>  /* Limit on the total amount of memory we can allocate for transfers 
> >> */
> >> -static unsigned usbfs_memory_mb = 16;
> >> +static u32 usbfs_memory_mb = 16;
> >>  module_param(usbfs_memory_mb, uint, 0644);
> >>  MODULE_PARM_DESC(usbfs_memory_mb,
> >>  		"maximum MB allowed for usbfs buffers (0 = no limit)");
> >>
> >> -/* Hard limit, necessary to avoid arithmetic overflow */
> >> -#define USBFS_XFER_MAX		(UINT_MAX / 2 - 1000000)
> >> +/* Hard limit */
> >> +#define USBFS_XFER_MAX		(1ull << 52)
> >
> > I should have realized this before -- my fault.  Since usbfs_memory_mb
> > is a u32 value, it can never be >= 2^32 MB.  Consequently, the total
> > memory limit can never be >= 2^52 bytes, so there's no need for
> > USBFS_XFER_MAX at all!
> >
> > The only reason it's there now is, like the comment says, with 32-bit
> > values the user could cause an arithmetic overflow.  With 64-bit 
> > values
> > that isn't possible.
> >
> > So you might as well just get rid of it entirely.
> 
> That’s what I thought initially as well, but in the proc_bulk() 
> function, there is this piece :
> 
> static int proc_bulk(struct usb_dev_state *ps, void __user *arg)
> {
> 	[...]
> 	struct usbdevfs_bulktransfer bulk;
> 	unsigned int tmo, len1, pipe;
> 
> 	[...]
> 
> 	if (copy_from_user(&bulk, arg, sizeof(bulk)))
> 		return -EFAULT;
> 
> 	[...]
> 
> 	if (!usb_maxpacket(dev, pipe, !(bulk.ep & USB_DIR_IN)))
> 		return -EINVAL;
> 	len1 = bulk.len;
> 	if (len1 >= USBFS_XFER_MAX)
> 		return -EINVAL;
> 	ret = usbfs_increase_memory_usage(len1 + sizeof(struct urb));
> 	if (ret)
> 		return ret;
> 	tbuf = kmalloc(len1, GFP_KERNEL);
> 
> Does this potentially open up some sort of resource-exhaustion 
> vulnerability?

No.  Although we should be careful, because len1 + sizeof(struct urb)
could overflow an unsigned int.

> Specifically, the part where bulk is copied in from userspace,
> and the len1 = bulk.len . Next without checking for some bounds,
> we’d just add up that value to the memory counter.

If the memory counter is a 32-bit value then you're right; the addition
could overflow the counter.  That's why the check is there now.

But if you change the counter to a 64-bit value then there's no 
possibility of overflow, because len1 and bulk.len are both 32-bit 
quantities.  The sum of two values, where one is limited to 2^52 and 
the other is limited to 2^32, cannot overflow a 64-bit word.

> Should the limit stay, perhaps?

Not in the form it is now.  Really, the only need is to make sure that 
len1 + sizeof(struct urb) won't overflow a 32-bit word.

Alan Stern

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux