ChangeSet 1.1673.8.18, 2004/03/25 17:06:47-08:00, stern@rowland.harvard.edu [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. drivers/usb/core/devio.c | 19 +++++++++++++++---- 1 files changed, 15 insertions(+), 4 deletions(-) diff -Nru a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c --- a/drivers/usb/core/devio.c Wed Apr 14 14:38:52 2004 +++ b/drivers/usb/core/devio.c Wed Apr 14 14:38:52 2004 @@ -124,14 +124,25 @@ unsigned int length = le16_to_cpu(config->wTotalLength); 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); if (len > nbytes) len = nbytes; - if (copy_to_user(buf, - ps->dev->rawdescriptors[i] + (*ppos - pos), len)) { - ret = -EFAULT; - goto err; + /* Simply don't write (skip over) unallocated parts */ + if (alloclen > (*ppos - pos)) { + alloclen -= (*ppos - pos); + if (copy_to_user(buf, + ps->dev->rawdescriptors[i] + (*ppos - pos), + min(len, alloclen))) { + ret = -EFAULT; + goto err; + } } *ppos += len;