Skip to content

Commit 427694c

Browse files
Krishna Kurapatigregkh
authored andcommitted
usb: gadget: ncm: Handle decoding of multiple NTB's in unwrap call
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: stable@vger.kernel.org Fixes: 9f6ce42 ("usb: gadget: f_ncm.c added") Signed-off-by: Krishna Kurapati <quic_kriskura@quicinc.com> Reviewed-by: Maciej Żenczykowski <maze@google.com> Link: https://lore.kernel.org/r/20230927105858.12950-1-quic_kriskura@quicinc.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 33d7e37 commit 427694c

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
@@ -1156,7 +1156,8 @@ static int ncm_unwrap_ntb(struct gether *port,
11561156
struct sk_buff_head *list)
11571157
{
11581158
struct f_ncm *ncm = func_to_ncm(&port->func);
1159-
__le16 *tmp = (void *) skb->data;
1159+
unsigned char *ntb_ptr = skb->data;
1160+
__le16 *tmp;
11601161
unsigned index, index2;
11611162
int ndp_index;
11621163
unsigned dg_len, dg_len2;
@@ -1169,6 +1170,10 @@ static int ncm_unwrap_ntb(struct gether *port,
11691170
const struct ndp_parser_opts *opts = ncm->parser_opts;
11701171
unsigned crc_len = ncm->is_crc ? sizeof(uint32_t) : 0;
11711172
int dgram_counter;
1173+
int to_process = skb->len;
1174+
1175+
parse_ntb:
1176+
tmp = (__le16 *)ntb_ptr;
11721177

11731178
/* dwSignature */
11741179
if (get_unaligned_le32(tmp) != opts->nth_sign) {
@@ -1215,7 +1220,7 @@ static int ncm_unwrap_ntb(struct gether *port,
12151220
* walk through NDP
12161221
* dwSignature
12171222
*/
1218-
tmp = (void *)(skb->data + ndp_index);
1223+
tmp = (__le16 *)(ntb_ptr + ndp_index);
12191224
if (get_unaligned_le32(tmp) != ncm->ndp_sign) {
12201225
INFO(port->func.config->cdev, "Wrong NDP SIGN\n");
12211226
goto err;
@@ -1272,11 +1277,11 @@ static int ncm_unwrap_ntb(struct gether *port,
12721277
if (ncm->is_crc) {
12731278
uint32_t crc, crc2;
12741279

1275-
crc = get_unaligned_le32(skb->data +
1280+
crc = get_unaligned_le32(ntb_ptr +
12761281
index + dg_len -
12771282
crc_len);
12781283
crc2 = ~crc32_le(~0,
1279-
skb->data + index,
1284+
ntb_ptr + index,
12801285
dg_len - crc_len);
12811286
if (crc != crc2) {
12821287
INFO(port->func.config->cdev,
@@ -1303,7 +1308,7 @@ static int ncm_unwrap_ntb(struct gether *port,
13031308
dg_len - crc_len);
13041309
if (skb2 == NULL)
13051310
goto err;
1306-
skb_put_data(skb2, skb->data + index,
1311+
skb_put_data(skb2, ntb_ptr + index,
13071312
dg_len - crc_len);
13081313

13091314
skb_queue_tail(list, skb2);
@@ -1316,10 +1321,17 @@ static int ncm_unwrap_ntb(struct gether *port,
13161321
} while (ndp_len > 2 * (opts->dgram_item_len * 2));
13171322
} while (ndp_index);
13181323

1319-
dev_consume_skb_any(skb);
1320-
13211324
VDBG(port->func.config->cdev,
13221325
"Parsed NTB with %d frames\n", dgram_counter);
1326+
1327+
to_process -= block_len;
1328+
if (to_process != 0) {
1329+
ntb_ptr = (unsigned char *)(ntb_ptr + block_len);
1330+
goto parse_ntb;
1331+
}
1332+
1333+
dev_consume_skb_any(skb);
1334+
13231335
return 0;
13241336
err:
13251337
skb_queue_purge(list);

0 commit comments

Comments
 (0)