Skip to content

Commit 670b77d

Browse files
committed
Merge tag 'usb-7.1-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb
Pull USB and Thunderbolt fixes from Greg KH: "Here is a set of USB fixes and new device ids for 7.1-rc6. Nothing major in here, just lots of tiny fixes for reported issues found by users and some older patches found by some scanning tools. Included in here are: - typec fixes found by fuzzers that have decided to finally look at that device interaction path (i.e. before a driver is bound to a device) - typec fixes for issues found by users - thunderbolt driver fixes for reported problems - cdns3 driver fixes - dwc3 driver fixes - new device quirks added - usb serial driver fixes for broken devices - other small driver fixes All of these have been in linux-next for over a week with no reported issues" * tag 'usb-7.1-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (54 commits) USB: serial: cypress_m8: validate interrupt packet headers USB: serial: safe_serial: fix memory corruption with small endpoint USB: serial: omninet: fix memory corruption with small endpoint USB: serial: mxuport: fix memory corruption with small endpoint USB: serial: cypress_m8: fix memory corruption with small endpoint USB: cdc-acm: Fix bit overlap and move quirk definitions to header usb: dwc2: Fix use after free in debug code usb: chipidea: core: convert ci_role_switch to local variable usb: gadget: f_fs: serialize DMABUF cancel against request completion usb: gadget: f_fs: copy only received bytes on short ep0 read usb: gadget: dummy_hcd: Reject hub port requests for non-existent ports dt-bindings: usb: Fix EIC7700 USB reset's issue usbip: vudc: Fix use after free bug in vudc_remove due to race condition dt-bindings: usb: ti,omap4-musb: Drop duplicate 'usb-phy' property constraints usb: storage: Add quirks for PNY Elite Portable SSD USB: quirks: add NO_LPM for Lenovo ThinkPad USB-C Dock Gen2 hub controllers usb: usbtmc: reject interrupt endpoints with small wMaxPacketSize usb: usbtmc: check URB actual_length for interrupt-IN notifications xhci: tegra: Fix ghost USB device on dual-role port unplug usb: gadget: uvc: hold opts->lock across XU walks in uvc_function_bind ...
2 parents 495fb8d + 645d4ed commit 670b77d

43 files changed

Lines changed: 446 additions & 207 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Documentation/devicetree/bindings/usb/eswin,eic7700-usb.yaml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,13 @@ properties:
4141
- const: usb_en
4242

4343
resets:
44-
maxItems: 2
44+
maxItems: 3
4545

4646
reset-names:
4747
items:
4848
- const: vaux
4949
- const: usb_rst
50+
- const: usb_phy
5051

5152
eswin,hsp-sp-csr:
5253
description:
@@ -85,8 +86,8 @@ examples:
8586
interrupt-parent = <&plic>;
8687
interrupts = <85>;
8788
interrupt-names = "peripheral";
88-
resets = <&reset 84>, <&hspcrg 2>;
89-
reset-names = "vaux", "usb_rst";
89+
resets = <&reset 84>, <&hspcrg 2>, <&hspcrg 4>;
90+
reset-names = "vaux", "usb_rst", "usb_phy";
9091
dr_mode = "peripheral";
9192
maximum-speed = "high-speed";
9293
phy_type = "utmi";

Documentation/devicetree/bindings/usb/ti,omap4-musb.yaml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -81,9 +81,7 @@ properties:
8181
const: usb2-phy
8282

8383
usb-phy:
84-
$ref: /schemas/types.yaml#/definitions/phandle-array
85-
description: Phandle for the PHY device.
86-
deprecated: true
84+
maxItems: 1
8785

8886
ctrl-module:
8987
$ref: /schemas/types.yaml#/definitions/phandle
@@ -96,6 +94,9 @@ required:
9694
- interrupts
9795
- interrupt-names
9896

97+
allOf:
98+
- $ref: usb-hcd.yaml#
99+
99100
unevaluatedProperties: false
100101

101102
examples:

drivers/thunderbolt/property.c

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
*/
99

1010
#include <linux/err.h>
11+
#include <linux/overflow.h>
1112
#include <linux/slab.h>
1213
#include <linux/string.h>
1314
#include <linux/uuid.h>
@@ -34,10 +35,11 @@ struct tb_property_dir_entry {
3435
};
3536

3637
#define TB_PROPERTY_ROOTDIR_MAGIC 0x55584401
38+
#define TB_PROPERTY_MAX_DEPTH 8
3739

3840
static struct tb_property_dir *__tb_property_parse_dir(const u32 *block,
3941
size_t block_len, unsigned int dir_offset, size_t dir_len,
40-
bool is_root);
42+
bool is_root, unsigned int depth);
4143

4244
static inline void parse_dwdata(void *dst, const void *src, size_t dwords)
4345
{
@@ -52,13 +54,16 @@ static inline void format_dwdata(void *dst, const void *src, size_t dwords)
5254
static bool tb_property_entry_valid(const struct tb_property_entry *entry,
5355
size_t block_len)
5456
{
57+
u32 end;
58+
5559
switch (entry->type) {
5660
case TB_PROPERTY_TYPE_DIRECTORY:
5761
case TB_PROPERTY_TYPE_DATA:
5862
case TB_PROPERTY_TYPE_TEXT:
5963
if (entry->length > block_len)
6064
return false;
61-
if (entry->value + entry->length > block_len)
65+
if (check_add_overflow(entry->value, entry->length, &end) ||
66+
end > block_len)
6267
return false;
6368
break;
6469

@@ -93,7 +98,8 @@ tb_property_alloc(const char *key, enum tb_property_type type)
9398
}
9499

95100
static struct tb_property *tb_property_parse(const u32 *block, size_t block_len,
96-
const struct tb_property_entry *entry)
101+
const struct tb_property_entry *entry,
102+
unsigned int depth)
97103
{
98104
char key[TB_PROPERTY_KEY_SIZE + 1];
99105
struct tb_property *property;
@@ -114,7 +120,7 @@ static struct tb_property *tb_property_parse(const u32 *block, size_t block_len,
114120
switch (property->type) {
115121
case TB_PROPERTY_TYPE_DIRECTORY:
116122
dir = __tb_property_parse_dir(block, block_len, entry->value,
117-
entry->length, false);
123+
entry->length, false, depth + 1);
118124
if (!dir) {
119125
kfree(property);
120126
return NULL;
@@ -159,21 +165,31 @@ static struct tb_property *tb_property_parse(const u32 *block, size_t block_len,
159165
}
160166

161167
static struct tb_property_dir *__tb_property_parse_dir(const u32 *block,
162-
size_t block_len, unsigned int dir_offset, size_t dir_len, bool is_root)
168+
size_t block_len, unsigned int dir_offset, size_t dir_len, bool is_root,
169+
unsigned int depth)
163170
{
164171
const struct tb_property_entry *entries;
165172
size_t i, content_len, nentries;
166173
unsigned int content_offset;
167174
struct tb_property_dir *dir;
168175

176+
if (depth > TB_PROPERTY_MAX_DEPTH)
177+
return NULL;
178+
169179
dir = kzalloc_obj(*dir);
170180
if (!dir)
171181
return NULL;
172182

183+
INIT_LIST_HEAD(&dir->properties);
184+
173185
if (is_root) {
174186
content_offset = dir_offset + 2;
175187
content_len = dir_len;
176188
} else {
189+
if (dir_len < 4) {
190+
tb_property_free_dir(dir);
191+
return NULL;
192+
}
177193
dir->uuid = kmemdup(&block[dir_offset], sizeof(*dir->uuid),
178194
GFP_KERNEL);
179195
if (!dir->uuid) {
@@ -187,12 +203,10 @@ static struct tb_property_dir *__tb_property_parse_dir(const u32 *block,
187203
entries = (const struct tb_property_entry *)&block[content_offset];
188204
nentries = content_len / (sizeof(*entries) / 4);
189205

190-
INIT_LIST_HEAD(&dir->properties);
191-
192206
for (i = 0; i < nentries; i++) {
193207
struct tb_property *property;
194208

195-
property = tb_property_parse(block, block_len, &entries[i]);
209+
property = tb_property_parse(block, block_len, &entries[i], depth);
196210
if (!property) {
197211
tb_property_free_dir(dir);
198212
return NULL;
@@ -231,7 +245,7 @@ struct tb_property_dir *tb_property_parse_dir(const u32 *block,
231245
return NULL;
232246

233247
return __tb_property_parse_dir(block, block_len, 0, rootdir->length,
234-
true);
248+
true, 0);
235249
}
236250

237251
/**

drivers/usb/cdns3/cdns3-gadget.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2817,9 +2817,19 @@ int __cdns3_gadget_ep_clear_halt(struct cdns3_endpoint *priv_ep)
28172817
priv_ep->flags &= ~(EP_STALLED | EP_STALL_PENDING);
28182818

28192819
if (request) {
2820-
if (trb)
2820+
if (trb) {
28212821
*trb = trb_tmp;
28222822

2823+
/*
2824+
* Per datasheet, EPRST causes DMA to reposition to the next TD.
2825+
* Manually reset EP_TRADDR to the current TRB to prevent
2826+
* the hardware from skipping the interrupted request.
2827+
*/
2828+
writel(EP_TRADDR_TRADDR(priv_ep->trb_pool_dma +
2829+
priv_req->start_trb * TRB_SIZE),
2830+
&priv_dev->regs->ep_traddr);
2831+
}
2832+
28232833
cdns3_rearm_transfer(priv_ep, 1);
28242834
}
28252835

drivers/usb/cdns3/cdns3-plat.c

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -126,15 +126,15 @@ static int cdns3_plat_probe(struct platform_device *pdev)
126126
return dev_err_probe(dev, PTR_ERR(cdns->usb2_phy),
127127
"Failed to get cdn3,usb2-phy\n");
128128

129-
ret = phy_init(cdns->usb2_phy);
130-
if (ret)
131-
return ret;
132-
133129
cdns->usb3_phy = devm_phy_optional_get(dev, "cdns3,usb3-phy");
134130
if (IS_ERR(cdns->usb3_phy))
135131
return dev_err_probe(dev, PTR_ERR(cdns->usb3_phy),
136132
"Failed to get cdn3,usb3-phy\n");
137133

134+
ret = phy_init(cdns->usb2_phy);
135+
if (ret)
136+
return ret;
137+
138138
ret = phy_init(cdns->usb3_phy);
139139
if (ret)
140140
goto err_phy3_init;
@@ -186,6 +186,9 @@ static void cdns3_plat_remove(struct platform_device *pdev)
186186
struct device *dev = cdns->dev;
187187

188188
pm_runtime_get_sync(dev);
189+
if (!(cdns->pdata && (cdns->pdata->quirks & CDNS3_DEFAULT_PM_RUNTIME_ALLOW)))
190+
pm_runtime_allow(dev);
191+
189192
pm_runtime_disable(dev);
190193
pm_runtime_put_noidle(dev);
191194
cdns_remove(cdns);

drivers/usb/chipidea/core.c

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -655,12 +655,6 @@ static enum ci_role ci_get_role(struct ci_hdrc *ci)
655655
return role;
656656
}
657657

658-
static struct usb_role_switch_desc ci_role_switch = {
659-
.set = ci_usb_role_switch_set,
660-
.get = ci_usb_role_switch_get,
661-
.allow_userspace_control = true,
662-
};
663-
664658
static int ci_get_platdata(struct device *dev,
665659
struct ci_hdrc_platform_data *platdata)
666660
{
@@ -787,9 +781,6 @@ static int ci_get_platdata(struct device *dev,
787781
cable->connected = false;
788782
}
789783

790-
if (device_property_read_bool(dev, "usb-role-switch"))
791-
ci_role_switch.fwnode = dev->fwnode;
792-
793784
platdata->pctl = devm_pinctrl_get(dev);
794785
if (!IS_ERR(platdata->pctl)) {
795786
struct pinctrl_state *p;
@@ -1033,6 +1024,7 @@ ATTRIBUTE_GROUPS(ci);
10331024

10341025
static int ci_hdrc_probe(struct platform_device *pdev)
10351026
{
1027+
struct usb_role_switch_desc ci_role_switch = {};
10361028
struct device *dev = &pdev->dev;
10371029
struct ci_hdrc *ci;
10381030
struct resource *res;
@@ -1179,7 +1171,11 @@ static int ci_hdrc_probe(struct platform_device *pdev)
11791171
}
11801172
}
11811173

1182-
if (ci_role_switch.fwnode) {
1174+
if (device_property_read_bool(dev, "usb-role-switch")) {
1175+
ci_role_switch.set = ci_usb_role_switch_set;
1176+
ci_role_switch.get = ci_usb_role_switch_get;
1177+
ci_role_switch.allow_userspace_control = true;
1178+
ci_role_switch.fwnode = dev_fwnode(dev);
11831179
ci_role_switch.driver_data = ci;
11841180
ci->role_switch = usb_role_switch_register(dev,
11851181
&ci_role_switch);

drivers/usb/class/cdc-acm.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,8 +114,6 @@ static int acm_ctrl_msg(struct acm *acm, int request, int value,
114114
int retval;
115115

116116
retval = usb_autopm_get_interface(acm->control);
117-
#define VENDOR_CLASS_DATA_IFACE BIT(9) /* data interface uses vendor-specific class */
118-
#define ALWAYS_POLL_CTRL BIT(10) /* keep ctrl URB active even without an open TTY */
119117
if (retval)
120118
return retval;
121119

drivers/usb/class/cdc-acm.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,3 +115,5 @@ struct acm {
115115
#define DISABLE_ECHO BIT(7)
116116
#define MISSING_CAP_BRK BIT(8)
117117
#define NO_UNION_12 BIT(9)
118+
#define VENDOR_CLASS_DATA_IFACE BIT(10) /* data interface uses vendor-specific class */
119+
#define ALWAYS_POLL_CTRL BIT(11) /* keep ctrl URB active even without an open TTY */

drivers/usb/class/usbtmc.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2306,6 +2306,14 @@ static void usbtmc_interrupt(struct urb *urb)
23062306

23072307
switch (status) {
23082308
case 0: /* SUCCESS */
2309+
/* ensure at least two bytes of headers were transferred */
2310+
if (urb->actual_length < 2) {
2311+
dev_warn(dev,
2312+
"actual length %d not sufficient for interrupt headers\n",
2313+
urb->actual_length);
2314+
goto exit;
2315+
}
2316+
23092317
/* check for valid STB notification */
23102318
if (data->iin_buffer[0] > 0x81) {
23112319
data->bNotify1 = data->iin_buffer[0];
@@ -2432,6 +2440,12 @@ static int usbtmc_probe(struct usb_interface *intf,
24322440
data->iin_ep = int_in->bEndpointAddress;
24332441
data->iin_wMaxPacketSize = usb_endpoint_maxp(int_in);
24342442
data->iin_interval = int_in->bInterval;
2443+
/* wMaxPacketSize should be 0x02 or more as per USB488 Table 22 */
2444+
if (iface_desc->desc.bInterfaceProtocol == 1 &&
2445+
data->iin_wMaxPacketSize < 2) {
2446+
retcode = -EINVAL;
2447+
goto err_put;
2448+
}
24352449
dev_dbg(&intf->dev, "Found Int in endpoint at %u\n",
24362450
data->iin_ep);
24372451
}

drivers/usb/core/config.c

Lines changed: 19 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,7 @@ static void usb_parse_ssp_isoc_endpoint_companion(struct device *ddev,
5656
desc = (struct usb_ssp_isoc_ep_comp_descriptor *) buffer;
5757
if (size < USB_DT_SSP_ISOC_EP_COMP_SIZE ||
5858
desc->bDescriptorType != USB_DT_SSP_ISOC_ENDPOINT_COMP) {
59-
dev_notice(ddev, "Invalid SuperSpeedPlus isoc endpoint companion"
60-
"for config %d interface %d altsetting %d ep %d.\n",
59+
dev_notice(ddev, "Invalid SuperSpeedPlus isoc endpoint companion for config %d interface %d altsetting %d ep 0x%X.\n",
6160
cfgno, inum, asnum, ep->desc.bEndpointAddress);
6261
return;
6362
}
@@ -91,7 +90,7 @@ static void usb_parse_eusb2_isoc_endpoint_companion(struct device *ddev,
9190
size -= h->bLength;
9291
}
9392

94-
dev_notice(ddev, "No eUSB2 isoc ep %d companion for config %d interface %d altsetting %d\n",
93+
dev_notice(ddev, "No eUSB2 isoc ep 0x%X companion for config %d interface %d altsetting %d\n",
9594
ep->desc.bEndpointAddress, cfgno, inum, asnum);
9695
}
9796

@@ -115,9 +114,7 @@ static void usb_parse_ss_endpoint_companion(struct device *ddev, int cfgno,
115114
}
116115

117116
if (desc->bDescriptorType != USB_DT_SS_ENDPOINT_COMP) {
118-
dev_notice(ddev, "No SuperSpeed endpoint companion for config %d "
119-
" interface %d altsetting %d ep %d: "
120-
"using minimum values\n",
117+
dev_notice(ddev, "No SuperSpeed endpoint companion for config %d interface %d altsetting %d ep 0x%X: using minimum values\n",
121118
cfgno, inum, asnum, ep->desc.bEndpointAddress);
122119

123120
/* Fill in some default values.
@@ -141,42 +138,32 @@ static void usb_parse_ss_endpoint_companion(struct device *ddev, int cfgno,
141138

142139
/* Check the various values */
143140
if (usb_endpoint_xfer_control(&ep->desc) && desc->bMaxBurst != 0) {
144-
dev_notice(ddev, "Control endpoint with bMaxBurst = %d in "
145-
"config %d interface %d altsetting %d ep %d: "
146-
"setting to zero\n", desc->bMaxBurst,
147-
cfgno, inum, asnum, ep->desc.bEndpointAddress);
141+
dev_notice(ddev, "Control endpoint with bMaxBurst = %d in config %d interface %d altsetting %d ep 0x%X: setting to zero\n",
142+
desc->bMaxBurst, cfgno, inum, asnum, ep->desc.bEndpointAddress);
148143
ep->ss_ep_comp.bMaxBurst = 0;
149144
} else if (desc->bMaxBurst > 15) {
150-
dev_notice(ddev, "Endpoint with bMaxBurst = %d in "
151-
"config %d interface %d altsetting %d ep %d: "
152-
"setting to 15\n", desc->bMaxBurst,
153-
cfgno, inum, asnum, ep->desc.bEndpointAddress);
145+
dev_notice(ddev, "Endpoint with bMaxBurst = %d in config %d interface %d altsetting %d ep 0x%X: setting to 15\n",
146+
desc->bMaxBurst, cfgno, inum, asnum, ep->desc.bEndpointAddress);
154147
ep->ss_ep_comp.bMaxBurst = 15;
155148
}
156149

157150
if ((usb_endpoint_xfer_control(&ep->desc) ||
158151
usb_endpoint_xfer_int(&ep->desc)) &&
159152
desc->bmAttributes != 0) {
160-
dev_notice(ddev, "%s endpoint with bmAttributes = %d in "
161-
"config %d interface %d altsetting %d ep %d: "
162-
"setting to zero\n",
153+
dev_notice(ddev, "%s endpoint with bmAttributes = %d in config %d interface %d altsetting %d ep 0x%X: setting to zero\n",
163154
usb_endpoint_xfer_control(&ep->desc) ? "Control" : "Bulk",
164155
desc->bmAttributes,
165156
cfgno, inum, asnum, ep->desc.bEndpointAddress);
166157
ep->ss_ep_comp.bmAttributes = 0;
167158
} else if (usb_endpoint_xfer_bulk(&ep->desc) &&
168159
desc->bmAttributes > 16) {
169-
dev_notice(ddev, "Bulk endpoint with more than 65536 streams in "
170-
"config %d interface %d altsetting %d ep %d: "
171-
"setting to max\n",
160+
dev_notice(ddev, "Bulk endpoint with more than 65536 streams in config %d interface %d altsetting %d ep 0x%X: setting to max\n",
172161
cfgno, inum, asnum, ep->desc.bEndpointAddress);
173162
ep->ss_ep_comp.bmAttributes = 16;
174163
} else if (usb_endpoint_xfer_isoc(&ep->desc) &&
175164
!USB_SS_SSP_ISOC_COMP(desc->bmAttributes) &&
176165
USB_SS_MULT(desc->bmAttributes) > 3) {
177-
dev_notice(ddev, "Isoc endpoint has Mult of %d in "
178-
"config %d interface %d altsetting %d ep %d: "
179-
"setting to 3\n",
166+
dev_notice(ddev, "Isoc endpoint has Mult of %d in config %d interface %d altsetting %d ep 0x%X: setting to 3\n",
180167
USB_SS_MULT(desc->bmAttributes),
181168
cfgno, inum, asnum, ep->desc.bEndpointAddress);
182169
ep->ss_ep_comp.bmAttributes = 2;
@@ -191,10 +178,15 @@ static void usb_parse_ss_endpoint_companion(struct device *ddev, int cfgno,
191178
(desc->bMaxBurst + 1);
192179
else
193180
max_tx = 999999;
194-
if (le16_to_cpu(desc->wBytesPerInterval) > max_tx) {
195-
dev_notice(ddev, "%s endpoint with wBytesPerInterval of %d in "
196-
"config %d interface %d altsetting %d ep %d: "
197-
"setting to %d\n",
181+
/*
182+
* wBytesPerInterval > max_tx is bogus, but USB3 spec doesn't forbid the opposite.
183+
* Experience shows that wBytesPerInterval < wMaxPacketSize on common interrupt IN
184+
* endpoints is usually bogus too, and recent HCs enforce interrupt BW limits.
185+
*/
186+
if (le16_to_cpu(desc->wBytesPerInterval) > max_tx ||
187+
(le16_to_cpu(desc->wBytesPerInterval) < usb_endpoint_maxp(&ep->desc) &&
188+
usb_endpoint_is_int_in(&ep->desc))) {
189+
dev_notice(ddev, "%s endpoint with wBytesPerInterval of %d in config %d interface %d altsetting %d ep 0x%X: setting to %d\n",
198190
usb_endpoint_xfer_isoc(&ep->desc) ? "Isoc" : "Int",
199191
le16_to_cpu(desc->wBytesPerInterval),
200192
cfgno, inum, asnum, ep->desc.bEndpointAddress,

0 commit comments

Comments
 (0)