From: Greg Kroah-Hartman Date: Sat, 9 Sep 2023 12:45:14 +0000 (+0100) Subject: 5.4-stable patches X-Git-Tag: v6.1.53~96 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=1f4fd6fd6219d328cb582c5edf559aea91818522;p=thirdparty%2Fkernel%2Fstable-queue.git 5.4-stable patches added patches: alsa-pcm-fix-missing-fixup-call-in-compat-hw_refine-ioctl.patch arm-omap2-fix-warray-bounds-warning-in-_pwrdm_state_switch.patch igb-set-max-size-rx-buffer-when-store-bad-packet-is-enabled.patch ipmi_si-fix-a-memleak-in-try_smi_init.patch netfilter-xt_sctp-validate-the-flag_info-count.patch netfilter-xt_u32-validate-user-space-input.patch pm-devfreq-fix-leak-in-devfreq_dev_release.patch skbuff-skb_segment-call-zero-copy-functions-before-using-skbuff-frags.patch --- diff --git a/queue-5.4/alsa-pcm-fix-missing-fixup-call-in-compat-hw_refine-ioctl.patch b/queue-5.4/alsa-pcm-fix-missing-fixup-call-in-compat-hw_refine-ioctl.patch new file mode 100644 index 00000000000..a15c3a673e4 --- /dev/null +++ b/queue-5.4/alsa-pcm-fix-missing-fixup-call-in-compat-hw_refine-ioctl.patch @@ -0,0 +1,49 @@ +From 358040e3807754944dbddf948a23c6d914297ed7 Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Tue, 29 Aug 2023 15:43:44 +0200 +Subject: ALSA: pcm: Fix missing fixup call in compat hw_refine ioctl + +From: Takashi Iwai + +commit 358040e3807754944dbddf948a23c6d914297ed7 upstream. + +The update of rate_num/den and msbits were factored out to +fixup_unreferenced_params() function to be called explicitly after the +hw_refine or hw_params procedure. It's called from +snd_pcm_hw_refine_user(), but it's forgotten in the PCM compat ioctl. +This ended up with the incomplete rate_num/den and msbits parameters +when 32bit compat ioctl is used. + +This patch adds the missing call in snd_pcm_ioctl_hw_params_compat(). + +Reported-by: Meng_Cai@novatek.com.cn +Fixes: f9a076bff053 ("ALSA: pcm: calculate non-mask/non-interval parameters always when possible") +Reviewed-by: Takashi Sakamoto +Reviewed-by: Jaroslav Kysela +Cc: +Link: https://lore.kernel.org/r/20230829134344.31588-1-tiwai@suse.de +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman +--- + sound/core/pcm_compat.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +--- a/sound/core/pcm_compat.c ++++ b/sound/core/pcm_compat.c +@@ -315,10 +315,14 @@ static int snd_pcm_ioctl_hw_params_compa + goto error; + } + +- if (refine) ++ if (refine) { + err = snd_pcm_hw_refine(substream, data); +- else ++ if (err < 0) ++ goto error; ++ err = fixup_unreferenced_params(substream, data); ++ } else { + err = snd_pcm_hw_params(substream, data); ++ } + if (err < 0) + goto error; + if (copy_to_user(data32, data, sizeof(*data32)) || diff --git a/queue-5.4/arm-omap2-fix-warray-bounds-warning-in-_pwrdm_state_switch.patch b/queue-5.4/arm-omap2-fix-warray-bounds-warning-in-_pwrdm_state_switch.patch new file mode 100644 index 00000000000..367243285b5 --- /dev/null +++ b/queue-5.4/arm-omap2-fix-warray-bounds-warning-in-_pwrdm_state_switch.patch @@ -0,0 +1,45 @@ +From 847fb80cc01a54bc827b02547bb8743bdb59ddab Mon Sep 17 00:00:00 2001 +From: "Gustavo A. R. Silva" +Date: Wed, 7 Jun 2023 22:12:11 -0600 +Subject: ARM: OMAP2+: Fix -Warray-bounds warning in _pwrdm_state_switch() + +From: Gustavo A. R. Silva + +commit 847fb80cc01a54bc827b02547bb8743bdb59ddab upstream. + +If function pwrdm_read_prev_pwrst() returns -EINVAL, we will end +up accessing array pwrdm->state_counter through negative index +-22. This is wrong and the compiler is legitimately warning us +about this potential problem. + +Fix this by sanity checking the value stored in variable _prev_ +before accessing array pwrdm->state_counter. + +Address the following -Warray-bounds warning: +arch/arm/mach-omap2/powerdomain.c:178:45: warning: array subscript -22 is below array bounds of 'unsigned int[4]' [-Warray-bounds] + +Link: https://github.com/KSPP/linux/issues/307 +Fixes: ba20bb126940 ("OMAP: PM counter infrastructure.") +Cc: stable@vger.kernel.org +Reported-by: kernel test robot +Link: https://lore.kernel.org/lkml/20230607050639.LzbPn%25lkp@intel.com/ +Signed-off-by: Gustavo A. R. Silva +Message-ID: +Acked-by: Ard Biesheuvel +Signed-off-by: Tony Lindgren +Signed-off-by: Greg Kroah-Hartman +--- + arch/arm/mach-omap2/powerdomain.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/arm/mach-omap2/powerdomain.c ++++ b/arch/arm/mach-omap2/powerdomain.c +@@ -174,7 +174,7 @@ static int _pwrdm_state_switch(struct po + break; + case PWRDM_STATE_PREV: + prev = pwrdm_read_prev_pwrst(pwrdm); +- if (pwrdm->state != prev) ++ if (prev >= 0 && pwrdm->state != prev) + pwrdm->state_counter[prev]++; + if (prev == PWRDM_POWER_RET) + _update_logic_membank_counters(pwrdm); diff --git a/queue-5.4/igb-set-max-size-rx-buffer-when-store-bad-packet-is-enabled.patch b/queue-5.4/igb-set-max-size-rx-buffer-when-store-bad-packet-is-enabled.patch new file mode 100644 index 00000000000..4964ee8b3fb --- /dev/null +++ b/queue-5.4/igb-set-max-size-rx-buffer-when-store-bad-packet-is-enabled.patch @@ -0,0 +1,52 @@ +From bb5ed01cd2428cd25b1c88a3a9cba87055eb289f Mon Sep 17 00:00:00 2001 +From: Radoslaw Tyl +Date: Thu, 24 Aug 2023 13:46:19 -0700 +Subject: igb: set max size RX buffer when store bad packet is enabled + +From: Radoslaw Tyl + +commit bb5ed01cd2428cd25b1c88a3a9cba87055eb289f upstream. + +Increase the RX buffer size to 3K when the SBP bit is on. The size of +the RX buffer determines the number of pages allocated which may not +be sufficient for receive frames larger than the set MTU size. + +Cc: stable@vger.kernel.org +Fixes: 89eaefb61dc9 ("igb: Support RX-ALL feature flag.") +Reported-by: Manfred Rudigier +Signed-off-by: Radoslaw Tyl +Tested-by: Arpana Arland (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/intel/igb/igb_main.c | 11 +++++++---- + 1 file changed, 7 insertions(+), 4 deletions(-) + +--- a/drivers/net/ethernet/intel/igb/igb_main.c ++++ b/drivers/net/ethernet/intel/igb/igb_main.c +@@ -4552,6 +4552,10 @@ void igb_configure_rx_ring(struct igb_ad + static void igb_set_rx_buffer_len(struct igb_adapter *adapter, + struct igb_ring *rx_ring) + { ++#if (PAGE_SIZE < 8192) ++ struct e1000_hw *hw = &adapter->hw; ++#endif ++ + /* set build_skb and buffer size flags */ + clear_ring_build_skb_enabled(rx_ring); + clear_ring_uses_large_buffer(rx_ring); +@@ -4562,10 +4566,9 @@ static void igb_set_rx_buffer_len(struct + set_ring_build_skb_enabled(rx_ring); + + #if (PAGE_SIZE < 8192) +- if (adapter->max_frame_size <= IGB_MAX_FRAME_BUILD_SKB) +- return; +- +- set_ring_uses_large_buffer(rx_ring); ++ if (adapter->max_frame_size > IGB_MAX_FRAME_BUILD_SKB || ++ rd32(E1000_RCTL) & E1000_RCTL_SBP) ++ set_ring_uses_large_buffer(rx_ring); + #endif + } + diff --git a/queue-5.4/ipmi_si-fix-a-memleak-in-try_smi_init.patch b/queue-5.4/ipmi_si-fix-a-memleak-in-try_smi_init.patch new file mode 100644 index 00000000000..f37ec133f8e --- /dev/null +++ b/queue-5.4/ipmi_si-fix-a-memleak-in-try_smi_init.patch @@ -0,0 +1,60 @@ +From 6cf1a126de2992b4efe1c3c4d398f8de4aed6e3f Mon Sep 17 00:00:00 2001 +From: Yi Yang +Date: Thu, 29 Jun 2023 20:33:28 +0800 +Subject: ipmi_si: fix a memleak in try_smi_init() + +From: Yi Yang + +commit 6cf1a126de2992b4efe1c3c4d398f8de4aed6e3f upstream. + +Kmemleak reported the following leak info in try_smi_init(): + +unreferenced object 0xffff00018ecf9400 (size 1024): + comm "modprobe", pid 2707763, jiffies 4300851415 (age 773.308s) + backtrace: + [<000000004ca5b312>] __kmalloc+0x4b8/0x7b0 + [<00000000953b1072>] try_smi_init+0x148/0x5dc [ipmi_si] + [<000000006460d325>] 0xffff800081b10148 + [<0000000039206ea5>] do_one_initcall+0x64/0x2a4 + [<00000000601399ce>] do_init_module+0x50/0x300 + [<000000003c12ba3c>] load_module+0x7a8/0x9e0 + [<00000000c246fffe>] __se_sys_init_module+0x104/0x180 + [<00000000eea99093>] __arm64_sys_init_module+0x24/0x30 + [<0000000021b1ef87>] el0_svc_common.constprop.0+0x94/0x250 + [<0000000070f4f8b7>] do_el0_svc+0x48/0xe0 + [<000000005a05337f>] el0_svc+0x24/0x3c + [<000000005eb248d6>] el0_sync_handler+0x160/0x164 + [<0000000030a59039>] el0_sync+0x160/0x180 + +The problem was that when an error occurred before handlers registration +and after allocating `new_smi->si_sm`, the variable wouldn't be freed in +the error handling afterwards since `shutdown_smi()` hadn't been +registered yet. Fix it by adding a `kfree()` in the error handling path +in `try_smi_init()`. + +Cc: stable@vger.kernel.org # 4.19+ +Fixes: 7960f18a5647 ("ipmi_si: Convert over to a shutdown handler") +Signed-off-by: Yi Yang +Co-developed-by: GONG, Ruiqi +Signed-off-by: GONG, Ruiqi +Message-Id: <20230629123328.2402075-1-gongruiqi@huaweicloud.com> +Signed-off-by: Corey Minyard +Signed-off-by: Greg Kroah-Hartman +--- + drivers/char/ipmi/ipmi_si_intf.c | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/drivers/char/ipmi/ipmi_si_intf.c ++++ b/drivers/char/ipmi/ipmi_si_intf.c +@@ -2086,6 +2086,11 @@ static int try_smi_init(struct smi_info + new_smi->io.io_cleanup = NULL; + } + ++ if (rv && new_smi->si_sm) { ++ kfree(new_smi->si_sm); ++ new_smi->si_sm = NULL; ++ } ++ + return rv; + } + diff --git a/queue-5.4/netfilter-xt_sctp-validate-the-flag_info-count.patch b/queue-5.4/netfilter-xt_sctp-validate-the-flag_info-count.patch new file mode 100644 index 00000000000..0c16583671a --- /dev/null +++ b/queue-5.4/netfilter-xt_sctp-validate-the-flag_info-count.patch @@ -0,0 +1,36 @@ +From e99476497687ef9e850748fe6d232264f30bc8f9 Mon Sep 17 00:00:00 2001 +From: Wander Lairson Costa +Date: Mon, 28 Aug 2023 19:12:55 -0300 +Subject: netfilter: xt_sctp: validate the flag_info count + +From: Wander Lairson Costa + +commit e99476497687ef9e850748fe6d232264f30bc8f9 upstream. + +sctp_mt_check doesn't validate the flag_count field. An attacker can +take advantage of that to trigger a OOB read and leak memory +information. + +Add the field validation in the checkentry function. + +Fixes: 2e4e6a17af35 ("[NETFILTER] x_tables: Abstraction layer for {ip,ip6,arp}_tables") +Cc: stable@vger.kernel.org +Reported-by: Lucas Leong +Signed-off-by: Wander Lairson Costa +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Greg Kroah-Hartman +--- + net/netfilter/xt_sctp.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/net/netfilter/xt_sctp.c ++++ b/net/netfilter/xt_sctp.c +@@ -150,6 +150,8 @@ static int sctp_mt_check(const struct xt + { + const struct xt_sctp_info *info = par->matchinfo; + ++ if (info->flag_count > ARRAY_SIZE(info->flag_info)) ++ return -EINVAL; + if (info->flags & ~XT_SCTP_VALID_FLAGS) + return -EINVAL; + if (info->invflags & ~XT_SCTP_VALID_FLAGS) diff --git a/queue-5.4/netfilter-xt_u32-validate-user-space-input.patch b/queue-5.4/netfilter-xt_u32-validate-user-space-input.patch new file mode 100644 index 00000000000..e8a50eb0a2e --- /dev/null +++ b/queue-5.4/netfilter-xt_u32-validate-user-space-input.patch @@ -0,0 +1,61 @@ +From 69c5d284f67089b4750d28ff6ac6f52ec224b330 Mon Sep 17 00:00:00 2001 +From: Wander Lairson Costa +Date: Mon, 28 Aug 2023 10:21:07 -0300 +Subject: netfilter: xt_u32: validate user space input + +From: Wander Lairson Costa + +commit 69c5d284f67089b4750d28ff6ac6f52ec224b330 upstream. + +The xt_u32 module doesn't validate the fields in the xt_u32 structure. +An attacker may take advantage of this to trigger an OOB read by setting +the size fields with a value beyond the arrays boundaries. + +Add a checkentry function to validate the structure. + +This was originally reported by the ZDI project (ZDI-CAN-18408). + +Fixes: 1b50b8a371e9 ("[NETFILTER]: Add u32 match") +Cc: stable@vger.kernel.org +Signed-off-by: Wander Lairson Costa +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Greg Kroah-Hartman +--- + net/netfilter/xt_u32.c | 21 +++++++++++++++++++++ + 1 file changed, 21 insertions(+) + +--- a/net/netfilter/xt_u32.c ++++ b/net/netfilter/xt_u32.c +@@ -96,11 +96,32 @@ static bool u32_mt(const struct sk_buff + return ret ^ data->invert; + } + ++static int u32_mt_checkentry(const struct xt_mtchk_param *par) ++{ ++ const struct xt_u32 *data = par->matchinfo; ++ const struct xt_u32_test *ct; ++ unsigned int i; ++ ++ if (data->ntests > ARRAY_SIZE(data->tests)) ++ return -EINVAL; ++ ++ for (i = 0; i < data->ntests; ++i) { ++ ct = &data->tests[i]; ++ ++ if (ct->nnums > ARRAY_SIZE(ct->location) || ++ ct->nvalues > ARRAY_SIZE(ct->value)) ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ + static struct xt_match xt_u32_mt_reg __read_mostly = { + .name = "u32", + .revision = 0, + .family = NFPROTO_UNSPEC, + .match = u32_mt, ++ .checkentry = u32_mt_checkentry, + .matchsize = sizeof(struct xt_u32), + .me = THIS_MODULE, + }; diff --git a/queue-5.4/pm-devfreq-fix-leak-in-devfreq_dev_release.patch b/queue-5.4/pm-devfreq-fix-leak-in-devfreq_dev_release.patch new file mode 100644 index 00000000000..55dd5200ca8 --- /dev/null +++ b/queue-5.4/pm-devfreq-fix-leak-in-devfreq_dev_release.patch @@ -0,0 +1,34 @@ +From 5693d077595de721f9ddbf9d37f40e5409707dfe Mon Sep 17 00:00:00 2001 +From: Boris Brezillon +Date: Wed, 9 Aug 2023 13:31:08 +0200 +Subject: PM / devfreq: Fix leak in devfreq_dev_release() + +From: Boris Brezillon + +commit 5693d077595de721f9ddbf9d37f40e5409707dfe upstream. + +srcu_init_notifier_head() allocates resources that need to be released +with a srcu_cleanup_notifier_head() call. + +Reported by kmemleak. + +Fixes: 0fe3a66410a3 ("PM / devfreq: Add new DEVFREQ_TRANSITION_NOTIFIER notifier") +Cc: +Signed-off-by: Boris Brezillon +Reviewed-by: Dhruva Gole +Signed-off-by: Chanwoo Choi +Signed-off-by: Greg Kroah-Hartman +--- + drivers/devfreq/devfreq.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/devfreq/devfreq.c ++++ b/drivers/devfreq/devfreq.c +@@ -595,6 +595,7 @@ static void devfreq_dev_release(struct d + devfreq->profile->exit(devfreq->dev.parent); + + mutex_destroy(&devfreq->lock); ++ srcu_cleanup_notifier_head(&devfreq->transition_notifier_list); + kfree(devfreq); + } + diff --git a/queue-5.4/series b/queue-5.4/series index 49e010706d2..6cce693703c 100644 --- a/queue-5.4/series +++ b/queue-5.4/series @@ -205,3 +205,11 @@ cpufreq-fix-the-race-condition-while-updating-the-tr.patch virtio_ring-fix-avail_wrap_counter-in-virtqueue_add_.patch igmp-limit-igmpv3_newpack-packet-size-to-ip_max_mtu.patch netfilter-ipset-add-the-missing-ip_set_hash_with_net0-macro-for-ip_set_hash_netportnet.c.patch +netfilter-xt_u32-validate-user-space-input.patch +netfilter-xt_sctp-validate-the-flag_info-count.patch +skbuff-skb_segment-call-zero-copy-functions-before-using-skbuff-frags.patch +igb-set-max-size-rx-buffer-when-store-bad-packet-is-enabled.patch +pm-devfreq-fix-leak-in-devfreq_dev_release.patch +alsa-pcm-fix-missing-fixup-call-in-compat-hw_refine-ioctl.patch +ipmi_si-fix-a-memleak-in-try_smi_init.patch +arm-omap2-fix-warray-bounds-warning-in-_pwrdm_state_switch.patch diff --git a/queue-5.4/skbuff-skb_segment-call-zero-copy-functions-before-using-skbuff-frags.patch b/queue-5.4/skbuff-skb_segment-call-zero-copy-functions-before-using-skbuff-frags.patch new file mode 100644 index 00000000000..0cdd87e37a0 --- /dev/null +++ b/queue-5.4/skbuff-skb_segment-call-zero-copy-functions-before-using-skbuff-frags.patch @@ -0,0 +1,156 @@ +From 2ea35288c83b3d501a88bc17f2df8f176b5cc96f Mon Sep 17 00:00:00 2001 +From: Mohamed Khalfella +Date: Thu, 31 Aug 2023 02:17:02 -0600 +Subject: skbuff: skb_segment, Call zero copy functions before using skbuff frags + +From: Mohamed Khalfella + +commit 2ea35288c83b3d501a88bc17f2df8f176b5cc96f upstream. + +Commit bf5c25d60861 ("skbuff: in skb_segment, call zerocopy functions +once per nskb") added the call to zero copy functions in skb_segment(). +The change introduced a bug in skb_segment() because skb_orphan_frags() +may possibly change the number of fragments or allocate new fragments +altogether leaving nrfrags and frag to point to the old values. This can +cause a panic with stacktrace like the one below. + +[ 193.894380] BUG: kernel NULL pointer dereference, address: 00000000000000bc +[ 193.895273] CPU: 13 PID: 18164 Comm: vh-net-17428 Kdump: loaded Tainted: G O 5.15.123+ #26 +[ 193.903919] RIP: 0010:skb_segment+0xb0e/0x12f0 +[ 194.021892] Call Trace: +[ 194.027422] +[ 194.072861] tcp_gso_segment+0x107/0x540 +[ 194.082031] inet_gso_segment+0x15c/0x3d0 +[ 194.090783] skb_mac_gso_segment+0x9f/0x110 +[ 194.095016] __skb_gso_segment+0xc1/0x190 +[ 194.103131] netem_enqueue+0x290/0xb10 [sch_netem] +[ 194.107071] dev_qdisc_enqueue+0x16/0x70 +[ 194.110884] __dev_queue_xmit+0x63b/0xb30 +[ 194.121670] bond_start_xmit+0x159/0x380 [bonding] +[ 194.128506] dev_hard_start_xmit+0xc3/0x1e0 +[ 194.131787] __dev_queue_xmit+0x8a0/0xb30 +[ 194.138225] macvlan_start_xmit+0x4f/0x100 [macvlan] +[ 194.141477] dev_hard_start_xmit+0xc3/0x1e0 +[ 194.144622] sch_direct_xmit+0xe3/0x280 +[ 194.147748] __dev_queue_xmit+0x54a/0xb30 +[ 194.154131] tap_get_user+0x2a8/0x9c0 [tap] +[ 194.157358] tap_sendmsg+0x52/0x8e0 [tap] +[ 194.167049] handle_tx_zerocopy+0x14e/0x4c0 [vhost_net] +[ 194.173631] handle_tx+0xcd/0xe0 [vhost_net] +[ 194.176959] vhost_worker+0x76/0xb0 [vhost] +[ 194.183667] kthread+0x118/0x140 +[ 194.190358] ret_from_fork+0x1f/0x30 +[ 194.193670] + +In this case calling skb_orphan_frags() updated nr_frags leaving nrfrags +local variable in skb_segment() stale. This resulted in the code hitting +i >= nrfrags prematurely and trying to move to next frag_skb using +list_skb pointer, which was NULL, and caused kernel panic. Move the call +to zero copy functions before using frags and nr_frags. + +Fixes: bf5c25d60861 ("skbuff: in skb_segment, call zerocopy functions once per nskb") +Signed-off-by: Mohamed Khalfella +Reported-by: Amit Goyal +Cc: stable@vger.kernel.org +Reviewed-by: Eric Dumazet +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/core/skbuff.c | 34 ++++++++++++++++++++-------------- + 1 file changed, 20 insertions(+), 14 deletions(-) + +--- a/net/core/skbuff.c ++++ b/net/core/skbuff.c +@@ -3686,21 +3686,20 @@ struct sk_buff *skb_segment(struct sk_bu + struct sk_buff *segs = NULL; + struct sk_buff *tail = NULL; + struct sk_buff *list_skb = skb_shinfo(head_skb)->frag_list; +- skb_frag_t *frag = skb_shinfo(head_skb)->frags; + unsigned int mss = skb_shinfo(head_skb)->gso_size; + unsigned int doffset = head_skb->data - skb_mac_header(head_skb); +- struct sk_buff *frag_skb = head_skb; + unsigned int offset = doffset; + unsigned int tnl_hlen = skb_tnl_header_len(head_skb); + unsigned int partial_segs = 0; + unsigned int headroom; + unsigned int len = head_skb->len; ++ struct sk_buff *frag_skb; ++ skb_frag_t *frag; + __be16 proto; + bool csum, sg; +- int nfrags = skb_shinfo(head_skb)->nr_frags; + int err = -ENOMEM; + int i = 0; +- int pos; ++ int nfrags, pos; + int dummy; + + if ((skb_shinfo(head_skb)->gso_type & SKB_GSO_DODGY) && +@@ -3778,6 +3777,13 @@ normal: + headroom = skb_headroom(head_skb); + pos = skb_headlen(head_skb); + ++ if (skb_orphan_frags(head_skb, GFP_ATOMIC)) ++ return ERR_PTR(-ENOMEM); ++ ++ nfrags = skb_shinfo(head_skb)->nr_frags; ++ frag = skb_shinfo(head_skb)->frags; ++ frag_skb = head_skb; ++ + do { + struct sk_buff *nskb; + skb_frag_t *nskb_frag; +@@ -3802,6 +3808,10 @@ normal: + (skb_headlen(list_skb) == len || sg)) { + BUG_ON(skb_headlen(list_skb) > len); + ++ nskb = skb_clone(list_skb, GFP_ATOMIC); ++ if (unlikely(!nskb)) ++ goto err; ++ + i = 0; + nfrags = skb_shinfo(list_skb)->nr_frags; + frag = skb_shinfo(list_skb)->frags; +@@ -3820,12 +3830,8 @@ normal: + frag++; + } + +- nskb = skb_clone(list_skb, GFP_ATOMIC); + list_skb = list_skb->next; + +- if (unlikely(!nskb)) +- goto err; +- + if (unlikely(pskb_trim(nskb, len))) { + kfree_skb(nskb); + goto err; +@@ -3890,12 +3896,16 @@ normal: + skb_shinfo(nskb)->tx_flags |= skb_shinfo(head_skb)->tx_flags & + SKBTX_SHARED_FRAG; + +- if (skb_orphan_frags(frag_skb, GFP_ATOMIC) || +- skb_zerocopy_clone(nskb, frag_skb, GFP_ATOMIC)) ++ if (skb_zerocopy_clone(nskb, frag_skb, GFP_ATOMIC)) + goto err; + + while (pos < offset + len) { + if (i >= nfrags) { ++ if (skb_orphan_frags(list_skb, GFP_ATOMIC) || ++ skb_zerocopy_clone(nskb, list_skb, ++ GFP_ATOMIC)) ++ goto err; ++ + i = 0; + nfrags = skb_shinfo(list_skb)->nr_frags; + frag = skb_shinfo(list_skb)->frags; +@@ -3909,10 +3919,6 @@ normal: + i--; + frag--; + } +- if (skb_orphan_frags(frag_skb, GFP_ATOMIC) || +- skb_zerocopy_clone(nskb, frag_skb, +- GFP_ATOMIC)) +- goto err; + + list_skb = list_skb->next; + }