From: Greg Kroah-Hartman Date: Fri, 22 Jan 2021 11:54:13 +0000 (+0100) Subject: 4.9-stable patches X-Git-Tag: v4.4.253~13 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=7dd9c71dea6364c24b4445bd52bf816cd85089a3;p=thirdparty%2Fkernel%2Fstable-queue.git 4.9-stable patches added patches: net-cdc_ncm-correct-overhead-in-delayed_ndp_size.patch --- 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 index 00000000000..503e25f67fe --- /dev/null +++ b/queue-4.9/net-cdc_ncm-correct-overhead-in-delayed_ndp_size.patch @@ -0,0 +1,91 @@ +From 7a68d725e4ea384977445e0bcaed3d7de83ab5b3 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jouni=20K=2E=20Sepp=C3=A4nen?= +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 + +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: +> +> 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 +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 +Reviewed-by: Bjørn Mork +Signed-off-by: David S. Miller +[jks@iki.fi: backport to 4.4.y, 4.9.y] +Signed-off-by: Jouni K. Seppänen +Signed-off-by: Greg Kroah-Hartman + +--- + 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 */ diff --git a/queue-4.9/series b/queue-4.9/series index 10cb85d5d36..13a7abe66a4 100644 --- a/queue-4.9/series +++ b/queue-4.9/series @@ -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