]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/commitdiff
usb: gadget: f_fs: Assorted buffer overflow checks.
authorVincent Pelletier <plr.vincent@gmail.com>
Wed, 18 Jan 2017 00:57:44 +0000 (00:57 +0000)
committerThadeu Lima de Souza Cascardo <cascardo@canonical.com>
Wed, 8 Mar 2017 13:35:41 +0000 (10:35 -0300)
BugLink: http://bugs.launchpad.net/bugs/1663657
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>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Tim Gardner <tim.gardner@canonical.com>
Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@canonical.com>
drivers/usb/gadget/function/f_fs.c

index 803c503a2e3d262b8a6ee858fab929596c84de43..cfda1a1c0ab63055d303ef180c71a4df7cb93023 100644 (file)
@@ -2079,6 +2079,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) {
@@ -2087,6 +2089,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",
@@ -2171,6 +2178,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;
@@ -2243,7 +2253,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);