]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.9-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 22 Jan 2021 11:54:13 +0000 (12:54 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 22 Jan 2021 11:54:13 +0000 (12:54 +0100)
added patches:
net-cdc_ncm-correct-overhead-in-delayed_ndp_size.patch

queue-4.9/net-cdc_ncm-correct-overhead-in-delayed_ndp_size.patch [new file with mode: 0644]
queue-4.9/series

diff --git a/queue-4.9/net-cdc_ncm-correct-overhead-in-delayed_ndp_size.patch b/queue-4.9/net-cdc_ncm-correct-overhead-in-delayed_ndp_size.patch
new file mode 100644 (file)
index 0000000..503e25f
--- /dev/null
@@ -0,0 +1,91 @@
+From 7a68d725e4ea384977445e0bcaed3d7de83ab5b3 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Jouni=20K=2E=20Sepp=C3=A4nen?= <jks@iki.fi>
+Date: Tue, 5 Jan 2021 06:52:49 +0200
+Subject: net: cdc_ncm: correct overhead in delayed_ndp_size
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Jouni K. Seppänen <jks@iki.fi>
+
+commit 7a68d725e4ea384977445e0bcaed3d7de83ab5b3 upstream.
+
+Aligning to tx_ndp_modulus is not sufficient because the next align
+call can be cdc_ncm_align_tail, which can add up to ctx->tx_modulus +
+ctx->tx_remainder - 1 bytes. This used to lead to occasional crashes
+on a Huawei 909s-120 LTE module as follows:
+
+- the condition marked /* if there is a remaining skb [...] */ is true
+  so the swaps happen
+- skb_out is set from ctx->tx_curr_skb
+- skb_out->len is exactly 0x3f52
+- ctx->tx_curr_size is 0x4000 and delayed_ndp_size is 0xac
+  (note that the sum of skb_out->len and delayed_ndp_size is 0x3ffe)
+- the for loop over n is executed once
+- the cdc_ncm_align_tail call marked /* align beginning of next frame */
+  increases skb_out->len to 0x3f56 (the sum is now 0x4002)
+- the condition marked /* check if we had enough room left [...] */ is
+  false so we break out of the loop
+- the condition marked /* If requested, put NDP at end of frame. */ is
+  true so the NDP is written into skb_out
+- now skb_out->len is 0x4002, so padding_count is minus two interpreted
+  as an unsigned number, which is used as the length argument to memset,
+  leading to a crash with various symptoms but usually including
+
+> Call Trace:
+>  <IRQ>
+>  cdc_ncm_fill_tx_frame+0x83a/0x970 [cdc_ncm]
+>  cdc_mbim_tx_fixup+0x1d9/0x240 [cdc_mbim]
+>  usbnet_start_xmit+0x5d/0x720 [usbnet]
+
+The cdc_ncm_align_tail call first aligns on a ctx->tx_modulus
+boundary (adding at most ctx->tx_modulus-1 bytes), then adds
+ctx->tx_remainder bytes. Alternatively, the next alignment call can
+occur in cdc_ncm_ndp16 or cdc_ncm_ndp32, in which case at most
+ctx->tx_ndp_modulus-1 bytes are added.
+
+A similar problem has occurred before, and the code is nontrivial to
+reason about, so add a guard before the crashing call. By that time it
+is too late to prevent any memory corruption (we'll have written past
+the end of the buffer already) but we can at least try to get a warning
+written into an on-disk log by avoiding the hard crash caused by padding
+past the buffer with a huge number of zeros.
+
+Signed-off-by: Jouni K. Seppänen <jks@iki.fi>
+Fixes: 4a0e3e989d66 ("cdc_ncm: Add support for moving NDP to end of NCM frame")
+Link: https://bugzilla.kernel.org/show_bug.cgi?id=209407
+Reported-by: kernel test robot <lkp@intel.com>
+Reviewed-by: Bjørn Mork <bjorn@mork.no>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+[jks@iki.fi: backport to 4.4.y, 4.9.y]
+Signed-off-by: Jouni K. Seppänen <jks@iki.fi>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/usb/cdc_ncm.c |    8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/usb/cdc_ncm.c
++++ b/drivers/net/usb/cdc_ncm.c
+@@ -1128,7 +1128,10 @@ cdc_ncm_fill_tx_frame(struct usbnet *dev
+        * accordingly. Otherwise, we should check here.
+        */
+       if (ctx->drvflags & CDC_NCM_FLAG_NDP_TO_END)
+-              delayed_ndp_size = ALIGN(ctx->max_ndp_size, ctx->tx_ndp_modulus);
++              delayed_ndp_size = ctx->max_ndp_size +
++                      max_t(u32,
++                            ctx->tx_ndp_modulus,
++                            ctx->tx_modulus + ctx->tx_remainder) - 1;
+       else
+               delayed_ndp_size = 0;
+@@ -1281,7 +1284,8 @@ cdc_ncm_fill_tx_frame(struct usbnet *dev
+       if (!(dev->driver_info->flags & FLAG_SEND_ZLP) &&
+           skb_out->len > ctx->min_tx_pkt) {
+               padding_count = ctx->tx_max - skb_out->len;
+-              memset(skb_put(skb_out, padding_count), 0, padding_count);
++              if (!WARN_ON(padding_count > ctx->tx_max))
++                      memset(skb_put(skb_out, padding_count), 0, padding_count);
+       } else if (skb_out->len < ctx->tx_max &&
+                  (skb_out->len % dev->maxpacket) == 0) {
+               *skb_put(skb_out, 1) = 0;       /* force short packet */
index 10cb85d5d361dedd6de8d1852f5131e47c40ce9f..13a7abe66a420cc45fd5d0dd1c67cb37bc2b2717 100644 (file)
@@ -23,3 +23,4 @@ netfilter-conntrack-fix-reading-nf_conntrack_buckets.patch
 usb-ohci-make-distrust_firmware-param-default-to-false.patch
 compiler.h-raise-minimum-version-of-gcc-to-5.1-for-arm64.patch
 nfsd4-readdirplus-shouldn-t-return-parent-of-export.patch
+net-cdc_ncm-correct-overhead-in-delayed_ndp_size.patch