summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBryan O'Donoghue <bryan.odonoghue@linaro.org>2020-09-20 18:01:58 +0100
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2020-10-07 08:00:04 +0200
commit69868141bcf701a7d5b4c1999dda13eb84e0ff56 (patch)
treef46e1ce911dff2392eaf4b77212a838d019cd585
parenta9ac777f96d955c9512498b10387a9d25e42de97 (diff)
downloadlinux-stable-69868141bcf701a7d5b4c1999dda13eb84e0ff56.tar.gz
linux-stable-69868141bcf701a7d5b4c1999dda13eb84e0ff56.tar.bz2
linux-stable-69868141bcf701a7d5b4c1999dda13eb84e0ff56.zip
USB: gadget: f_ncm: Fix NDP16 datagram validation
commit 2b405533c2560d7878199c57d95a39151351df72 upstream. commit 2b74b0a04d3e ("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: 2b74b0a04d3e ("USB: gadget: f_ncm: add bounds checks to ncm_unwrap_ntb()") Cc: Ilja Van Sprundel <ivansprundel@ioactive.com> Cc: Brooke Basile <brookebasile@gmail.com> Cc: stable <stable@kernel.org> Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Link: https://lore.kernel.org/r/20200920170158.1217068-1-bryan.odonoghue@linaro.org Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/usb/gadget/function/f_ncm.c30
1 files changed, 2 insertions, 28 deletions
diff --git a/drivers/usb/gadget/function/f_ncm.c b/drivers/usb/gadget/function/f_ncm.c
index 8d8c81d43069..e2eefdd8bf78 100644
--- a/drivers/usb/gadget/function/f_ncm.c
+++ b/drivers/usb/gadget/function/f_ncm.c
@@ -1192,7 +1192,6 @@ static int ncm_unwrap_ntb(struct gether *port,
const struct ndp_parser_opts *opts = ncm->parser_opts;
unsigned crc_len = ncm->is_crc ? sizeof(uint32_t) : 0;
int dgram_counter;
- bool ndp_after_header;
/* dwSignature */
if (get_unaligned_le32(tmp) != opts->nth_sign) {
@@ -1219,7 +1218,6 @@ static int ncm_unwrap_ntb(struct gether *port,
}
ndp_index = get_ncm(&tmp, opts->ndp_index);
- ndp_after_header = false;
/* Run through all the NDP's in the NTB */
do {
@@ -1235,8 +1233,6 @@ static int ncm_unwrap_ntb(struct gether *port,
ndp_index);
goto err;
}
- if (ndp_index == opts->nth_size)
- ndp_after_header = true;
/*
* walk through NDP
@@ -1315,37 +1311,13 @@ static int ncm_unwrap_ntb(struct gether *port,
index2 = get_ncm(&tmp, opts->dgram_item_len);
dg_len2 = get_ncm(&tmp, opts->dgram_item_len);
- if (index2 == 0 || dg_len2 == 0)
- break;
-
/* wDatagramIndex[1] */
- if (ndp_after_header) {
- if (index2 < opts->nth_size + opts->ndp_size) {
- INFO(port->func.config->cdev,
- "Bad index: %#X\n", index2);
- goto err;
- }
- } else {
- if (index2 < opts->nth_size + opts->dpe_size) {
- INFO(port->func.config->cdev,
- "Bad index: %#X\n", index2);
- goto err;
- }
- }
if (index2 > block_len - opts->dpe_size) {
INFO(port->func.config->cdev,
"Bad index: %#X\n", index2);
goto err;
}
- /* wDatagramLength[1] */
- if ((dg_len2 < 14 + crc_len) ||
- (dg_len2 > frame_max)) {
- INFO(port->func.config->cdev,
- "Bad dgram length: %#X\n", dg_len);
- goto err;
- }
-
/*
* Copy the data into a new skb.
* This ensures the truesize is correct
@@ -1362,6 +1334,8 @@ static int ncm_unwrap_ntb(struct gether *port,
ndp_len -= 2 * (opts->dgram_item_len * 2);
dgram_counter++;
+ if (index2 == 0 || dg_len2 == 0)
+ break;
} while (ndp_len > 2 * (opts->dgram_item_len * 2));
} while (ndp_index);