Commit 59941877 authored by Alan Stern's avatar Alan Stern Committed by Greg Kroah-Hartman

[PATCH] USB: Don't trust raw descriptor length in devioc.

This is a very minor point, unlikely ever to come up.  But just in case...

It's conceivable that a device might transmit different values for a
configuration descriptor's wTotalLength the first time we ask for it (in
order to get the length) and the second time (to get the entire
descriptor).  Should that improbable event occur, the rawdescriptor buffer
could be allocated using a size that's smaller than the length recorded in
the rawdescriptor itself.  This patch protects devio.c against such a
problem.

If you feel this sequence of events is too unlikely to worry about, then
don't bother to apply the patch.
parent af6f5064
...@@ -124,14 +124,25 @@ static ssize_t usbdev_read(struct file *file, char __user *buf, size_t nbytes, l ...@@ -124,14 +124,25 @@ static ssize_t usbdev_read(struct file *file, char __user *buf, size_t nbytes, l
unsigned int length = le16_to_cpu(config->wTotalLength); unsigned int length = le16_to_cpu(config->wTotalLength);
if (*ppos < pos + length) { if (*ppos < pos + length) {
/* The descriptor may claim to be longer than it
* really is. Here is the actual allocated length. */
unsigned alloclen =
ps->dev->config[i].desc.wTotalLength;
len = length - (*ppos - pos); len = length - (*ppos - pos);
if (len > nbytes) if (len > nbytes)
len = nbytes; len = nbytes;
if (copy_to_user(buf, /* Simply don't write (skip over) unallocated parts */
ps->dev->rawdescriptors[i] + (*ppos - pos), len)) { if (alloclen > (*ppos - pos)) {
ret = -EFAULT; alloclen -= (*ppos - pos);
goto err; if (copy_to_user(buf,
ps->dev->rawdescriptors[i] + (*ppos - pos),
min(len, alloclen))) {
ret = -EFAULT;
goto err;
}
} }
*ppos += len; *ppos += len;
......
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