aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVincent Pelletier <plr.vincent@gmail.com>2017-01-17 19:57:44 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-01-25 06:03:52 -0500
commit83e526f2a2fa4b2e82b6bd3ddbb26b70acfa8947 (patch)
tree3067a6dfefc8299039bc89f9eca8dc36a77e1ab4
parentd9b2997e4a0a874e452df7cdd7de5a54502bd0aa (diff)
usb: gadget: f_fs: Assorted buffer overflow checks.
OS descriptor head, when flagged as provided, is accessed without checking if it fits in provided buffer. Verify length before access. Also, there are other places where buffer length it checked after accessing offsets which are potentially past the end. Check buffer length before as well to fail cleanly. Signed-off-by: Vincent Pelletier <plr.vincent@gmail.com> Acked-by: Felipe Balbi <felipe.balbi@linux.intel.com> Cc: stable <stable@vger.kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/usb/gadget/function/f_fs.c13
1 files changed, 12 insertions, 1 deletions
diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c
index 5490fc51638e..fd80c1b9c823 100644
--- a/drivers/usb/gadget/function/f_fs.c
+++ b/drivers/usb/gadget/function/f_fs.c
@@ -2269,6 +2269,8 @@ static int __ffs_data_do_os_desc(enum ffs_os_desc_type type,
2269 if (len < sizeof(*d) || h->interface >= ffs->interfaces_count) 2269 if (len < sizeof(*d) || h->interface >= ffs->interfaces_count)
2270 return -EINVAL; 2270 return -EINVAL;
2271 length = le32_to_cpu(d->dwSize); 2271 length = le32_to_cpu(d->dwSize);
2272 if (len < length)
2273 return -EINVAL;
2272 type = le32_to_cpu(d->dwPropertyDataType); 2274 type = le32_to_cpu(d->dwPropertyDataType);
2273 if (type < USB_EXT_PROP_UNICODE || 2275 if (type < USB_EXT_PROP_UNICODE ||
2274 type > USB_EXT_PROP_UNICODE_MULTI) { 2276 type > USB_EXT_PROP_UNICODE_MULTI) {
@@ -2277,6 +2279,11 @@ static int __ffs_data_do_os_desc(enum ffs_os_desc_type type,
2277 return -EINVAL; 2279 return -EINVAL;
2278 } 2280 }
2279 pnl = le16_to_cpu(d->wPropertyNameLength); 2281 pnl = le16_to_cpu(d->wPropertyNameLength);
2282 if (length < 14 + pnl) {
2283 pr_vdebug("invalid os descriptor length: %d pnl:%d (descriptor %d)\n",
2284 length, pnl, type);
2285 return -EINVAL;
2286 }
2280 pdl = le32_to_cpu(*(u32 *)((u8 *)data + 10 + pnl)); 2287 pdl = le32_to_cpu(*(u32 *)((u8 *)data + 10 + pnl));
2281 if (length != 14 + pnl + pdl) { 2288 if (length != 14 + pnl + pdl) {
2282 pr_vdebug("invalid os descriptor length: %d pnl:%d pdl:%d (descriptor %d)\n", 2289 pr_vdebug("invalid os descriptor length: %d pnl:%d pdl:%d (descriptor %d)\n",
@@ -2363,6 +2370,9 @@ static int __ffs_data_got_descs(struct ffs_data *ffs,
2363 } 2370 }
2364 } 2371 }
2365 if (flags & (1 << i)) { 2372 if (flags & (1 << i)) {
2373 if (len < 4) {
2374 goto error;
2375 }
2366 os_descs_count = get_unaligned_le32(data); 2376 os_descs_count = get_unaligned_le32(data);
2367 data += 4; 2377 data += 4;
2368 len -= 4; 2378 len -= 4;
@@ -2435,7 +2445,8 @@ static int __ffs_data_got_strings(struct ffs_data *ffs,
2435 2445
2436 ENTER(); 2446 ENTER();
2437 2447
2438 if (unlikely(get_unaligned_le32(data) != FUNCTIONFS_STRINGS_MAGIC || 2448 if (unlikely(len < 16 ||
2449 get_unaligned_le32(data) != FUNCTIONFS_STRINGS_MAGIC ||
2439 get_unaligned_le32(data + 4) != len)) 2450 get_unaligned_le32(data + 4) != len))
2440 goto error; 2451 goto error;
2441 str_count = get_unaligned_le32(data + 8); 2452 str_count = get_unaligned_le32(data + 8);