| From 83e526f2a2fa4b2e82b6bd3ddbb26b70acfa8947 Mon Sep 17 00:00:00 2001 |
| From: Vincent Pelletier <plr.vincent@gmail.com> |
| Date: Wed, 18 Jan 2017 00:57:44 +0000 |
| Subject: [PATCH] usb: gadget: f_fs: Assorted buffer overflow checks. |
| |
| commit 83e526f2a2fa4b2e82b6bd3ddbb26b70acfa8947 upstream. |
| |
| 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> |
| |
| 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, |
| if (len < sizeof(*d) || h->interface >= ffs->interfaces_count) |
| return -EINVAL; |
| length = le32_to_cpu(d->dwSize); |
| + if (len < length) |
| + return -EINVAL; |
| type = le32_to_cpu(d->dwPropertyDataType); |
| if (type < USB_EXT_PROP_UNICODE || |
| type > USB_EXT_PROP_UNICODE_MULTI) { |
| @@ -2277,6 +2279,11 @@ static int __ffs_data_do_os_desc(enum ffs_os_desc_type type, |
| return -EINVAL; |
| } |
| pnl = le16_to_cpu(d->wPropertyNameLength); |
| + if (length < 14 + pnl) { |
| + pr_vdebug("invalid os descriptor length: %d pnl:%d (descriptor %d)\n", |
| + length, pnl, type); |
| + return -EINVAL; |
| + } |
| pdl = le32_to_cpu(*(u32 *)((u8 *)data + 10 + pnl)); |
| if (length != 14 + pnl + pdl) { |
| 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, |
| } |
| } |
| if (flags & (1 << i)) { |
| + if (len < 4) { |
| + goto error; |
| + } |
| os_descs_count = get_unaligned_le32(data); |
| data += 4; |
| len -= 4; |
| @@ -2435,7 +2445,8 @@ static int __ffs_data_got_strings(struct ffs_data *ffs, |
| |
| ENTER(); |
| |
| - if (unlikely(get_unaligned_le32(data) != FUNCTIONFS_STRINGS_MAGIC || |
| + if (unlikely(len < 16 || |
| + get_unaligned_le32(data) != FUNCTIONFS_STRINGS_MAGIC || |
| get_unaligned_le32(data + 4) != len)) |
| goto error; |
| str_count = get_unaligned_le32(data + 8); |
| -- |
| 2.12.0 |
| |