Skip to content

Commit 17c653d

Browse files
Krishna Kurapatigregkh
authored andcommitted
usb: gadget: ncm: Handle decoding of multiple NTB's in unwrap call
commit 427694c upstream. When NCM is used with hosts like Windows PC, it is observed that there are multiple NTB's contained in one usb request giveback. Since the driver unwraps the obtained request data assuming only one NTB is present, we loose the subsequent NTB's present resulting in data loss. Fix this by checking the parsed block length with the obtained data length in usb request and continue parsing after the last byte of current NTB. Cc: [email protected] Fixes: 9f6ce42 ("usb: gadget: f_ncm.c added") Signed-off-by: Krishna Kurapati <[email protected]> Reviewed-by: Maciej Żenczykowski <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent a906f2e commit 17c653d

File tree

1 file changed

+19
-7
lines changed

1 file changed

+19
-7
lines changed

drivers/usb/gadget/function/f_ncm.c

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1180,7 +1180,8 @@ static int ncm_unwrap_ntb(struct gether *port,
11801180
struct sk_buff_head *list)
11811181
{
11821182
struct f_ncm *ncm = func_to_ncm(&port->func);
1183-
__le16 *tmp = (void *) skb->data;
1183+
unsigned char *ntb_ptr = skb->data;
1184+
__le16 *tmp;
11841185
unsigned index, index2;
11851186
int ndp_index;
11861187
unsigned dg_len, dg_len2;
@@ -1193,6 +1194,10 @@ static int ncm_unwrap_ntb(struct gether *port,
11931194
const struct ndp_parser_opts *opts = ncm->parser_opts;
11941195
unsigned crc_len = ncm->is_crc ? sizeof(uint32_t) : 0;
11951196
int dgram_counter;
1197+
int to_process = skb->len;
1198+
1199+
parse_ntb:
1200+
tmp = (__le16 *)ntb_ptr;
11961201

11971202
/* dwSignature */
11981203
if (get_unaligned_le32(tmp) != opts->nth_sign) {
@@ -1239,7 +1244,7 @@ static int ncm_unwrap_ntb(struct gether *port,
12391244
* walk through NDP
12401245
* dwSignature
12411246
*/
1242-
tmp = (void *)(skb->data + ndp_index);
1247+
tmp = (__le16 *)(ntb_ptr + ndp_index);
12431248
if (get_unaligned_le32(tmp) != ncm->ndp_sign) {
12441249
INFO(port->func.config->cdev, "Wrong NDP SIGN\n");
12451250
goto err;
@@ -1296,11 +1301,11 @@ static int ncm_unwrap_ntb(struct gether *port,
12961301
if (ncm->is_crc) {
12971302
uint32_t crc, crc2;
12981303

1299-
crc = get_unaligned_le32(skb->data +
1304+
crc = get_unaligned_le32(ntb_ptr +
13001305
index + dg_len -
13011306
crc_len);
13021307
crc2 = ~crc32_le(~0,
1303-
skb->data + index,
1308+
ntb_ptr + index,
13041309
dg_len - crc_len);
13051310
if (crc != crc2) {
13061311
INFO(port->func.config->cdev,
@@ -1327,7 +1332,7 @@ static int ncm_unwrap_ntb(struct gether *port,
13271332
dg_len - crc_len);
13281333
if (skb2 == NULL)
13291334
goto err;
1330-
skb_put_data(skb2, skb->data + index,
1335+
skb_put_data(skb2, ntb_ptr + index,
13311336
dg_len - crc_len);
13321337

13331338
skb_queue_tail(list, skb2);
@@ -1340,10 +1345,17 @@ static int ncm_unwrap_ntb(struct gether *port,
13401345
} while (ndp_len > 2 * (opts->dgram_item_len * 2));
13411346
} while (ndp_index);
13421347

1343-
dev_consume_skb_any(skb);
1344-
13451348
VDBG(port->func.config->cdev,
13461349
"Parsed NTB with %d frames\n", dgram_counter);
1350+
1351+
to_process -= block_len;
1352+
if (to_process != 0) {
1353+
ntb_ptr = (unsigned char *)(ntb_ptr + block_len);
1354+
goto parse_ntb;
1355+
}
1356+
1357+
dev_consume_skb_any(skb);
1358+
13471359
return 0;
13481360
err:
13491361
skb_queue_purge(list);

0 commit comments

Comments
 (0)