Skip to content

Commit 2b40553

Browse files
0xB0Dgregkh
authored andcommitted
USB: gadget: f_ncm: Fix NDP16 datagram validation
commit 2b74b0a ("USB: gadget: f_ncm: add bounds checks to ncm_unwrap_ntb()") adds important bounds checking however it unfortunately also introduces a bug with respect to section 3.3.1 of the NCM specification. wDatagramIndex[1] : "Byte index, in little endian, of the second datagram described by this NDP16. If zero, then this marks the end of the sequence of datagrams in this NDP16." wDatagramLength[1]: "Byte length, in little endian, of the second datagram described by this NDP16. If zero, then this marks the end of the sequence of datagrams in this NDP16." wDatagramIndex[1] and wDatagramLength[1] respectively then may be zero but that does not mean we should throw away the data referenced by wDatagramIndex[0] and wDatagramLength[0] as is currently the case. Breaking the loop on (index2 == 0 || dg_len2 == 0) should come at the end as was previously the case and checks for index2 and dg_len2 should be removed since zero is valid. I'm not sure how much testing the above patch received but for me right now after enumeration ping doesn't work. Reverting the commit restores ping, scp, etc. The extra validation associated with wDatagramIndex[0] and wDatagramLength[0] appears to be valid so, this change removes the incorrect restriction on wDatagramIndex[1] and wDatagramLength[1] restoring data processing between host and device. Fixes: 2b74b0a ("USB: gadget: f_ncm: add bounds checks to ncm_unwrap_ntb()") Cc: Ilja Van Sprundel <[email protected]> Cc: Brooke Basile <[email protected]> Cc: stable <[email protected]> Signed-off-by: Bryan O'Donoghue <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent a311283 commit 2b40553

File tree

1 file changed

+2
-28
lines changed

1 file changed

+2
-28
lines changed

drivers/usb/gadget/function/f_ncm.c

Lines changed: 2 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1189,7 +1189,6 @@ static int ncm_unwrap_ntb(struct gether *port,
11891189
const struct ndp_parser_opts *opts = ncm->parser_opts;
11901190
unsigned crc_len = ncm->is_crc ? sizeof(uint32_t) : 0;
11911191
int dgram_counter;
1192-
bool ndp_after_header;
11931192

11941193
/* dwSignature */
11951194
if (get_unaligned_le32(tmp) != opts->nth_sign) {
@@ -1216,7 +1215,6 @@ static int ncm_unwrap_ntb(struct gether *port,
12161215
}
12171216

12181217
ndp_index = get_ncm(&tmp, opts->ndp_index);
1219-
ndp_after_header = false;
12201218

12211219
/* Run through all the NDP's in the NTB */
12221220
do {
@@ -1232,8 +1230,6 @@ static int ncm_unwrap_ntb(struct gether *port,
12321230
ndp_index);
12331231
goto err;
12341232
}
1235-
if (ndp_index == opts->nth_size)
1236-
ndp_after_header = true;
12371233

12381234
/*
12391235
* walk through NDP
@@ -1312,37 +1308,13 @@ static int ncm_unwrap_ntb(struct gether *port,
13121308
index2 = get_ncm(&tmp, opts->dgram_item_len);
13131309
dg_len2 = get_ncm(&tmp, opts->dgram_item_len);
13141310

1315-
if (index2 == 0 || dg_len2 == 0)
1316-
break;
1317-
13181311
/* wDatagramIndex[1] */
1319-
if (ndp_after_header) {
1320-
if (index2 < opts->nth_size + opts->ndp_size) {
1321-
INFO(port->func.config->cdev,
1322-
"Bad index: %#X\n", index2);
1323-
goto err;
1324-
}
1325-
} else {
1326-
if (index2 < opts->nth_size + opts->dpe_size) {
1327-
INFO(port->func.config->cdev,
1328-
"Bad index: %#X\n", index2);
1329-
goto err;
1330-
}
1331-
}
13321312
if (index2 > block_len - opts->dpe_size) {
13331313
INFO(port->func.config->cdev,
13341314
"Bad index: %#X\n", index2);
13351315
goto err;
13361316
}
13371317

1338-
/* wDatagramLength[1] */
1339-
if ((dg_len2 < 14 + crc_len) ||
1340-
(dg_len2 > frame_max)) {
1341-
INFO(port->func.config->cdev,
1342-
"Bad dgram length: %#X\n", dg_len);
1343-
goto err;
1344-
}
1345-
13461318
/*
13471319
* Copy the data into a new skb.
13481320
* This ensures the truesize is correct
@@ -1359,6 +1331,8 @@ static int ncm_unwrap_ntb(struct gether *port,
13591331
ndp_len -= 2 * (opts->dgram_item_len * 2);
13601332

13611333
dgram_counter++;
1334+
if (index2 == 0 || dg_len2 == 0)
1335+
break;
13621336
} while (ndp_len > 2 * (opts->dgram_item_len * 2));
13631337
} while (ndp_index);
13641338

0 commit comments

Comments
 (0)