aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/gadget/function/f_fs.c')
-rw-r--r--drivers/usb/gadget/function/f_fs.c36
1 files changed, 31 insertions, 5 deletions
diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c
index 803c503a2e3d..732e6ed5d7b4 100644
--- a/drivers/usb/gadget/function/f_fs.c
+++ b/drivers/usb/gadget/function/f_fs.c
@@ -1643,11 +1643,14 @@ static int ffs_func_eps_enable(struct ffs_function *func)
1643 spin_lock_irqsave(&func->ffs->eps_lock, flags); 1643 spin_lock_irqsave(&func->ffs->eps_lock, flags);
1644 do { 1644 do {
1645 struct usb_endpoint_descriptor *ds; 1645 struct usb_endpoint_descriptor *ds;
1646 struct usb_ss_ep_comp_descriptor *comp_desc = NULL;
1647 int needs_comp_desc = false;
1646 int desc_idx; 1648 int desc_idx;
1647 1649
1648 if (ffs->gadget->speed == USB_SPEED_SUPER) 1650 if (ffs->gadget->speed == USB_SPEED_SUPER) {
1649 desc_idx = 2; 1651 desc_idx = 2;
1650 else if (ffs->gadget->speed == USB_SPEED_HIGH) 1652 needs_comp_desc = true;
1653 } else if (ffs->gadget->speed == USB_SPEED_HIGH)
1651 desc_idx = 1; 1654 desc_idx = 1;
1652 else 1655 else
1653 desc_idx = 0; 1656 desc_idx = 0;
@@ -1664,6 +1667,14 @@ static int ffs_func_eps_enable(struct ffs_function *func)
1664 1667
1665 ep->ep->driver_data = ep; 1668 ep->ep->driver_data = ep;
1666 ep->ep->desc = ds; 1669 ep->ep->desc = ds;
1670
1671 if (needs_comp_desc) {
1672 comp_desc = (struct usb_ss_ep_comp_descriptor *)(ds +
1673 USB_DT_ENDPOINT_SIZE);
1674 ep->ep->maxburst = comp_desc->bMaxBurst + 1;
1675 ep->ep->comp_desc = comp_desc;
1676 }
1677
1667 ret = usb_ep_enable(ep->ep); 1678 ret = usb_ep_enable(ep->ep);
1668 if (likely(!ret)) { 1679 if (likely(!ret)) {
1669 epfile->ep = ep; 1680 epfile->ep = ep;
@@ -2079,6 +2090,8 @@ static int __ffs_data_do_os_desc(enum ffs_os_desc_type type,
2079 if (len < sizeof(*d) || h->interface >= ffs->interfaces_count) 2090 if (len < sizeof(*d) || h->interface >= ffs->interfaces_count)
2080 return -EINVAL; 2091 return -EINVAL;
2081 length = le32_to_cpu(d->dwSize); 2092 length = le32_to_cpu(d->dwSize);
2093 if (len < length)
2094 return -EINVAL;
2082 type = le32_to_cpu(d->dwPropertyDataType); 2095 type = le32_to_cpu(d->dwPropertyDataType);
2083 if (type < USB_EXT_PROP_UNICODE || 2096 if (type < USB_EXT_PROP_UNICODE ||
2084 type > USB_EXT_PROP_UNICODE_MULTI) { 2097 type > USB_EXT_PROP_UNICODE_MULTI) {
@@ -2087,6 +2100,11 @@ static int __ffs_data_do_os_desc(enum ffs_os_desc_type type,
2087 return -EINVAL; 2100 return -EINVAL;
2088 } 2101 }
2089 pnl = le16_to_cpu(d->wPropertyNameLength); 2102 pnl = le16_to_cpu(d->wPropertyNameLength);
2103 if (length < 14 + pnl) {
2104 pr_vdebug("invalid os descriptor length: %d pnl:%d (descriptor %d)\n",
2105 length, pnl, type);
2106 return -EINVAL;
2107 }
2090 pdl = le32_to_cpu(*(u32 *)((u8 *)data + 10 + pnl)); 2108 pdl = le32_to_cpu(*(u32 *)((u8 *)data + 10 + pnl));
2091 if (length != 14 + pnl + pdl) { 2109 if (length != 14 + pnl + pdl) {
2092 pr_vdebug("invalid os descriptor length: %d pnl:%d pdl:%d (descriptor %d)\n", 2110 pr_vdebug("invalid os descriptor length: %d pnl:%d pdl:%d (descriptor %d)\n",
@@ -2171,6 +2189,9 @@ static int __ffs_data_got_descs(struct ffs_data *ffs,
2171 } 2189 }
2172 } 2190 }
2173 if (flags & (1 << i)) { 2191 if (flags & (1 << i)) {
2192 if (len < 4) {
2193 goto error;
2194 }
2174 os_descs_count = get_unaligned_le32(data); 2195 os_descs_count = get_unaligned_le32(data);
2175 data += 4; 2196 data += 4;
2176 len -= 4; 2197 len -= 4;
@@ -2243,7 +2264,8 @@ static int __ffs_data_got_strings(struct ffs_data *ffs,
2243 2264
2244 ENTER(); 2265 ENTER();
2245 2266
2246 if (unlikely(get_unaligned_le32(data) != FUNCTIONFS_STRINGS_MAGIC || 2267 if (unlikely(len < 16 ||
2268 get_unaligned_le32(data) != FUNCTIONFS_STRINGS_MAGIC ||
2247 get_unaligned_le32(data + 4) != len)) 2269 get_unaligned_le32(data + 4) != len))
2248 goto error; 2270 goto error;
2249 str_count = get_unaligned_le32(data + 8); 2271 str_count = get_unaligned_le32(data + 8);
@@ -3441,6 +3463,7 @@ static void ffs_closed(struct ffs_data *ffs)
3441{ 3463{
3442 struct ffs_dev *ffs_obj; 3464 struct ffs_dev *ffs_obj;
3443 struct f_fs_opts *opts; 3465 struct f_fs_opts *opts;
3466 struct config_item *ci;
3444 3467
3445 ENTER(); 3468 ENTER();
3446 ffs_dev_lock(); 3469 ffs_dev_lock();
@@ -3464,8 +3487,11 @@ static void ffs_closed(struct ffs_data *ffs)
3464 || !atomic_read(&opts->func_inst.group.cg_item.ci_kref.refcount)) 3487 || !atomic_read(&opts->func_inst.group.cg_item.ci_kref.refcount))
3465 goto done; 3488 goto done;
3466 3489
3467 unregister_gadget_item(ffs_obj->opts-> 3490 ci = opts->func_inst.group.cg_item.ci_parent->ci_parent;
3468 func_inst.group.cg_item.ci_parent->ci_parent); 3491 ffs_dev_unlock();
3492
3493 unregister_gadget_item(ci);
3494 return;
3469done: 3495done:
3470 ffs_dev_unlock(); 3496 ffs_dev_unlock();
3471} 3497}