From: Greg Kroah-Hartman Date: Mon, 8 Feb 2021 13:21:22 +0000 (+0100) Subject: 5.10-stable patches X-Git-Tag: v4.4.257~4 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=fe4cc7b28756c2bb83b59fbe99ee2184de0d35ba;p=thirdparty%2Fkernel%2Fstable-queue.git 5.10-stable patches added patches: igc-report-speed-and-duplex-as-unknown-when-device-is-runtime-suspended.patch neighbour-prevent-a-dead-entry-from-updating-gc_list.patch net-dsa-mv88e6xxx-override-existent-unicast-portvec-in-port_fdb_add.patch net-ip_tunnel-fix-mtu-calculation.patch net-sched-replaced-invalid-qdisc-tree-flush-helper-in-qdisc_replace.patch udp-ipv4-manipulate-network-header-of-nated-udp-gro-fraglist.patch --- diff --git a/queue-5.10/igc-report-speed-and-duplex-as-unknown-when-device-is-runtime-suspended.patch b/queue-5.10/igc-report-speed-and-duplex-as-unknown-when-device-is-runtime-suspended.patch new file mode 100644 index 00000000000..8754a09cc3d --- /dev/null +++ b/queue-5.10/igc-report-speed-and-duplex-as-unknown-when-device-is-runtime-suspended.patch @@ -0,0 +1,93 @@ +From 2e99dedc73f004f650b197c9b269c15c7e01ad15 Mon Sep 17 00:00:00 2001 +From: Kai-Heng Feng +Date: Wed, 2 Dec 2020 15:50:17 +0800 +Subject: igc: Report speed and duplex as unknown when device is runtime suspended + +From: Kai-Heng Feng + +commit 2e99dedc73f004f650b197c9b269c15c7e01ad15 upstream. + +Similar to commit 165ae7a8feb5 ("igb: Report speed and duplex as unknown +when device is runtime suspended"), if we try to read speed and duplex +sysfs while the device is runtime suspended, igc will complain and +stops working: + +[ 123.449883] igc 0000:03:00.0 enp3s0: PCIe link lost, device now detached +[ 123.450052] BUG: kernel NULL pointer dereference, address: 0000000000000008 +[ 123.450056] #PF: supervisor read access in kernel mode +[ 123.450058] #PF: error_code(0x0000) - not-present page +[ 123.450059] PGD 0 P4D 0 +[ 123.450064] Oops: 0000 [#1] SMP NOPTI +[ 123.450068] CPU: 0 PID: 2525 Comm: udevadm Tainted: G U W OE 5.10.0-1002-oem #2+rkl2-Ubuntu +[ 123.450078] RIP: 0010:igc_rd32+0x1c/0x90 [igc] +[ 123.450080] Code: c0 5d c3 b8 fd ff ff ff c3 0f 1f 44 00 00 0f 1f 44 00 00 55 89 f0 48 89 e5 41 56 41 55 41 54 49 89 c4 53 48 8b 57 08 48 01 d0 <44> 8b 28 41 83 fd ff 74 0c 5b 44 89 e8 41 5c 41 5d 4 + +[ 123.450083] RSP: 0018:ffffb0d100d6fcc0 EFLAGS: 00010202 +[ 123.450085] RAX: 0000000000000008 RBX: ffffb0d100d6fd30 RCX: 0000000000000000 +[ 123.450087] RDX: 0000000000000000 RSI: 0000000000000008 RDI: ffff945a12716c10 +[ 123.450089] RBP: ffffb0d100d6fce0 R08: ffff945a12716550 R09: ffff945a09874000 +[ 123.450090] R10: 0000000000000000 R11: 0000000000000000 R12: 0000000000000008 +[ 123.450092] R13: ffff945a12716000 R14: ffff945a037da280 R15: ffff945a037da290 +[ 123.450094] FS: 00007f3b34c868c0(0000) GS:ffff945b89200000(0000) knlGS:0000000000000000 +[ 123.450096] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +[ 123.450098] CR2: 0000000000000008 CR3: 00000001144de006 CR4: 0000000000770ef0 +[ 123.450100] PKRU: 55555554 +[ 123.450101] Call Trace: +[ 123.450111] igc_ethtool_get_link_ksettings+0xd6/0x1b0 [igc] +[ 123.450118] __ethtool_get_link_ksettings+0x71/0xb0 +[ 123.450123] duplex_show+0x74/0xc0 +[ 123.450129] dev_attr_show+0x1d/0x40 +[ 123.450134] sysfs_kf_seq_show+0xa1/0x100 +[ 123.450137] kernfs_seq_show+0x27/0x30 +[ 123.450142] seq_read+0xb7/0x400 +[ 123.450148] ? common_file_perm+0x72/0x170 +[ 123.450151] kernfs_fop_read+0x35/0x1b0 +[ 123.450155] vfs_read+0xb5/0x1b0 +[ 123.450157] ksys_read+0x67/0xe0 +[ 123.450160] __x64_sys_read+0x1a/0x20 +[ 123.450164] do_syscall_64+0x38/0x90 +[ 123.450168] entry_SYSCALL_64_after_hwframe+0x44/0xa9 +[ 123.450170] RIP: 0033:0x7f3b351fe142 +[ 123.450173] Code: c0 e9 c2 fe ff ff 50 48 8d 3d 3a ca 0a 00 e8 f5 19 02 00 0f 1f 44 00 00 f3 0f 1e fa 64 8b 04 25 18 00 00 00 85 c0 75 10 0f 05 <48> 3d 00 f0 ff ff 77 56 c3 0f 1f 44 00 00 48 83 ec 28 48 89 54 24 +[ 123.450174] RSP: 002b:00007fffef2ec138 EFLAGS: 00000246 ORIG_RAX: 0000000000000000 +[ 123.450177] RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007f3b351fe142 +[ 123.450179] RDX: 0000000000001001 RSI: 00005644c047f070 RDI: 0000000000000003 +[ 123.450180] RBP: 00007fffef2ec340 R08: 00005644c047f070 R09: 00007f3b352d9320 +[ 123.450182] R10: 00005644c047c010 R11: 0000000000000246 R12: 00005644c047cbf0 +[ 123.450184] R13: 00005644c047e6d0 R14: 0000000000000003 R15: 00007fffef2ec140 +[ 123.450189] Modules linked in: rfcomm ccm cmac algif_hash algif_skcipher af_alg bnep toshiba_acpi industrialio toshiba_haps hp_accel lis3lv02d btusb btrtl btbcm btintel bluetooth ecdh_generic ecc joydev input_leds nls_iso8859_1 snd_sof_pci snd_sof_intel_byt snd_sof_intel_ipc snd_sof_intel_hda_common snd_soc_hdac_hda snd_hda_codec_hdmi snd_sof_xtensa_dsp snd_sof_intel_hda snd_sof snd_hda_ext_core snd_soc_acpi_intel_match snd_soc_acpi snd_hda_codec_realtek snd_hda_codec_generic ledtrig_audio snd_hda_intel snd_intel_dspcfg soundwire_intel soundwire_generic_allocation soundwire_cadence snd_hda_codec snd_hda_core ath10k_pci snd_hwdep intel_rapl_msr intel_rapl_common ath10k_core soundwire_bus snd_soc_core x86_pkg_temp_thermal ath intel_powerclamp snd_compress ac97_bus snd_pcm_dmaengine mac80211 snd_pcm coretemp snd_seq_midi snd_seq_midi_event snd_rawmidi kvm_intel cfg80211 snd_seq snd_seq_device snd_timer mei_hdcp kvm libarc4 snd crct10dif_pclmul ghash_clmulni_intel aesni_intel + mei_me dell_wmi +[ 123.450266] dell_smbios soundcore sparse_keymap dcdbas crypto_simd cryptd mei dell_uart_backlight glue_helper ee1004 wmi_bmof intel_wmi_thunderbolt dell_wmi_descriptor mac_hid efi_pstore acpi_pad acpi_tad intel_cstate sch_fq_codel parport_pc ppdev lp parport ip_tables x_tables autofs4 btrfs blake2b_generic raid10 raid456 async_raid6_recov async_memcpy async_pq async_xor async_tx xor raid6_pq libcrc32c raid1 raid0 multipath linear dm_mirror dm_region_hash dm_log hid_generic usbhid hid i915 i2c_algo_bit drm_kms_helper syscopyarea sysfillrect sysimgblt fb_sys_fops cec crc32_pclmul rc_core drm intel_lpss_pci i2c_i801 ahci igc intel_lpss i2c_smbus idma64 xhci_pci libahci virt_dma xhci_pci_renesas wmi video pinctrl_tigerlake +[ 123.450335] CR2: 0000000000000008 +[ 123.450338] ---[ end trace 9f731e38b53c35cc ]--- + +The more generic approach will be wrap get_link_ksettings() with begin() +and complete() callbacks, and calls runtime resume and runtime suspend +routine respectively. However, igc is like igb, runtime resume routine +uses rtnl_lock() which upper ethtool layer also uses. + +So to prevent a deadlock on rtnl, take a different approach, use +pm_runtime_suspended() to avoid reading register while device is runtime +suspended. + +Fixes: 8c5ad0dae93c ("igc: Add ethtool support") +Signed-off-by: Kai-Heng Feng +Acked-by: Sasha Neftin +Signed-off-by: Tony Nguyen +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/intel/igc/igc_ethtool.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/net/ethernet/intel/igc/igc_ethtool.c ++++ b/drivers/net/ethernet/intel/igc/igc_ethtool.c +@@ -1714,7 +1714,8 @@ static int igc_ethtool_get_link_ksetting + Asym_Pause); + } + +- status = rd32(IGC_STATUS); ++ status = pm_runtime_suspended(&adapter->pdev->dev) ? ++ 0 : rd32(IGC_STATUS); + + if (status & IGC_STATUS_LU) { + if (status & IGC_STATUS_SPEED_1000) { diff --git a/queue-5.10/neighbour-prevent-a-dead-entry-from-updating-gc_list.patch b/queue-5.10/neighbour-prevent-a-dead-entry-from-updating-gc_list.patch new file mode 100644 index 00000000000..0b57e9f5894 --- /dev/null +++ b/queue-5.10/neighbour-prevent-a-dead-entry-from-updating-gc_list.patch @@ -0,0 +1,67 @@ +From eb4e8fac00d1e01ada5e57c05d24739156086677 Mon Sep 17 00:00:00 2001 +From: Chinmay Agarwal +Date: Wed, 27 Jan 2021 22:24:54 +0530 +Subject: neighbour: Prevent a dead entry from updating gc_list + +From: Chinmay Agarwal + +commit eb4e8fac00d1e01ada5e57c05d24739156086677 upstream. + +Following race condition was detected: + - neigh_flush_dev() is under execution and calls +neigh_mark_dead(n) marking the neighbour entry 'n' as dead. + + - Executing: __netif_receive_skb() -> +__netif_receive_skb_core() -> arp_rcv() -> arp_process().arp_process() +calls __neigh_lookup() which takes a reference on neighbour entry 'n'. + + - Moves further along neigh_flush_dev() and calls +neigh_cleanup_and_release(n), but since reference count increased in t2, +'n' couldn't be destroyed. + + - Moves further along, arp_process() and calls +neigh_update()-> __neigh_update() -> neigh_update_gc_list(), which adds +the neighbour entry back in gc_list(neigh_mark_dead(), removed it +earlier in t0 from gc_list) + + - arp_process() finally calls neigh_release(n), destroying +the neighbour entry. + +This leads to 'n' still being part of gc_list, but the actual +neighbour structure has been freed. + +The situation can be prevented from happening if we disallow a dead +entry to have any possibility of updating gc_list. This is what the +patch intends to achieve. + +Fixes: 9c29a2f55ec0 ("neighbor: Fix locking order for gc_list changes") +Signed-off-by: Chinmay Agarwal +Reviewed-by: Cong Wang +Reviewed-by: David Ahern +Link: https://lore.kernel.org/r/20210127165453.GA20514@chinagar-linux.qualcomm.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Greg Kroah-Hartman +--- + net/core/neighbour.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +--- a/net/core/neighbour.c ++++ b/net/core/neighbour.c +@@ -1245,13 +1245,14 @@ static int __neigh_update(struct neighbo + old = neigh->nud_state; + err = -EPERM; + +- if (!(flags & NEIGH_UPDATE_F_ADMIN) && +- (old & (NUD_NOARP | NUD_PERMANENT))) +- goto out; + if (neigh->dead) { + NL_SET_ERR_MSG(extack, "Neighbor entry is now dead"); ++ new = old; + goto out; + } ++ if (!(flags & NEIGH_UPDATE_F_ADMIN) && ++ (old & (NUD_NOARP | NUD_PERMANENT))) ++ goto out; + + ext_learn_change = neigh_update_ext_learned(neigh, flags, ¬ify); + diff --git a/queue-5.10/net-dsa-mv88e6xxx-override-existent-unicast-portvec-in-port_fdb_add.patch b/queue-5.10/net-dsa-mv88e6xxx-override-existent-unicast-portvec-in-port_fdb_add.patch new file mode 100644 index 00000000000..ea089f38ab3 --- /dev/null +++ b/queue-5.10/net-dsa-mv88e6xxx-override-existent-unicast-portvec-in-port_fdb_add.patch @@ -0,0 +1,39 @@ +From f72f2fb8fb6be095b98af5d740ac50cffd0b0cae Mon Sep 17 00:00:00 2001 +From: DENG Qingfang +Date: Sat, 30 Jan 2021 21:43:34 +0800 +Subject: net: dsa: mv88e6xxx: override existent unicast portvec in port_fdb_add + +From: DENG Qingfang + +commit f72f2fb8fb6be095b98af5d740ac50cffd0b0cae upstream. + +Having multiple destination ports for a unicast address does not make +sense. +Make port_db_load_purge override existent unicast portvec instead of +adding a new port bit. + +Fixes: 884729399260 ("net: dsa: mv88e6xxx: handle multiple ports in ATU") +Signed-off-by: DENG Qingfang +Reviewed-by: Vladimir Oltean +Link: https://lore.kernel.org/r/20210130134334.10243-1-dqfext@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/dsa/mv88e6xxx/chip.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +--- a/drivers/net/dsa/mv88e6xxx/chip.c ++++ b/drivers/net/dsa/mv88e6xxx/chip.c +@@ -1669,7 +1669,11 @@ static int mv88e6xxx_port_db_load_purge( + if (!entry.portvec) + entry.state = 0; + } else { +- entry.portvec |= BIT(port); ++ if (state == MV88E6XXX_G1_ATU_DATA_STATE_UC_STATIC) ++ entry.portvec = BIT(port); ++ else ++ entry.portvec |= BIT(port); ++ + entry.state = state; + } + diff --git a/queue-5.10/net-ip_tunnel-fix-mtu-calculation.patch b/queue-5.10/net-ip_tunnel-fix-mtu-calculation.patch new file mode 100644 index 00000000000..fc06e1c70a9 --- /dev/null +++ b/queue-5.10/net-ip_tunnel-fix-mtu-calculation.patch @@ -0,0 +1,79 @@ +From 28e104d00281ade30250b24e098bf50887671ea4 Mon Sep 17 00:00:00 2001 +From: Vadim Fedorenko +Date: Sat, 30 Jan 2021 01:27:47 +0300 +Subject: net: ip_tunnel: fix mtu calculation + +From: Vadim Fedorenko + +commit 28e104d00281ade30250b24e098bf50887671ea4 upstream. + +dev->hard_header_len for tunnel interface is set only when header_ops +are set too and already contains full overhead of any tunnel encapsulation. +That's why there is not need to use this overhead twice in mtu calc. + +Fixes: fdafed459998 ("ip_gre: set dev->hard_header_len and dev->needed_headroom properly") +Reported-by: Slava Bacherikov +Signed-off-by: Vadim Fedorenko +Link: https://lore.kernel.org/r/1611959267-20536-1-git-send-email-vfedorenko@novek.ru +Signed-off-by: Jakub Kicinski +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv4/ip_tunnel.c | 16 +++++++--------- + 1 file changed, 7 insertions(+), 9 deletions(-) + +--- a/net/ipv4/ip_tunnel.c ++++ b/net/ipv4/ip_tunnel.c +@@ -317,7 +317,7 @@ static int ip_tunnel_bind_dev(struct net + } + + dev->needed_headroom = t_hlen + hlen; +- mtu -= (dev->hard_header_len + t_hlen); ++ mtu -= t_hlen; + + if (mtu < IPV4_MIN_MTU) + mtu = IPV4_MIN_MTU; +@@ -347,7 +347,7 @@ static struct ip_tunnel *ip_tunnel_creat + nt = netdev_priv(dev); + t_hlen = nt->hlen + sizeof(struct iphdr); + dev->min_mtu = ETH_MIN_MTU; +- dev->max_mtu = IP_MAX_MTU - dev->hard_header_len - t_hlen; ++ dev->max_mtu = IP_MAX_MTU - t_hlen; + ip_tunnel_add(itn, nt); + return nt; + +@@ -488,11 +488,10 @@ static int tnl_update_pmtu(struct net_de + int mtu; + + tunnel_hlen = md ? tunnel_hlen : tunnel->hlen; +- pkt_size = skb->len - tunnel_hlen - dev->hard_header_len; ++ pkt_size = skb->len - tunnel_hlen; + + if (df) +- mtu = dst_mtu(&rt->dst) - dev->hard_header_len +- - sizeof(struct iphdr) - tunnel_hlen; ++ mtu = dst_mtu(&rt->dst) - (sizeof(struct iphdr) + tunnel_hlen); + else + mtu = skb_valid_dst(skb) ? dst_mtu(skb_dst(skb)) : dev->mtu; + +@@ -972,7 +971,7 @@ int __ip_tunnel_change_mtu(struct net_de + { + struct ip_tunnel *tunnel = netdev_priv(dev); + int t_hlen = tunnel->hlen + sizeof(struct iphdr); +- int max_mtu = IP_MAX_MTU - dev->hard_header_len - t_hlen; ++ int max_mtu = IP_MAX_MTU - t_hlen; + + if (new_mtu < ETH_MIN_MTU) + return -EINVAL; +@@ -1149,10 +1148,9 @@ int ip_tunnel_newlink(struct net_device + + mtu = ip_tunnel_bind_dev(dev); + if (tb[IFLA_MTU]) { +- unsigned int max = IP_MAX_MTU - dev->hard_header_len - nt->hlen; ++ unsigned int max = IP_MAX_MTU - (nt->hlen + sizeof(struct iphdr)); + +- mtu = clamp(dev->mtu, (unsigned int)ETH_MIN_MTU, +- (unsigned int)(max - sizeof(struct iphdr))); ++ mtu = clamp(dev->mtu, (unsigned int)ETH_MIN_MTU, max); + } + + err = dev_set_mtu(dev, mtu); diff --git a/queue-5.10/net-sched-replaced-invalid-qdisc-tree-flush-helper-in-qdisc_replace.patch b/queue-5.10/net-sched-replaced-invalid-qdisc-tree-flush-helper-in-qdisc_replace.patch new file mode 100644 index 00000000000..3ebf18978ef --- /dev/null +++ b/queue-5.10/net-sched-replaced-invalid-qdisc-tree-flush-helper-in-qdisc_replace.patch @@ -0,0 +1,80 @@ +From 938e0fcd3253efdef8924714158911286d08cfe1 Mon Sep 17 00:00:00 2001 +From: Alexander Ovechkin +Date: Mon, 1 Feb 2021 23:00:49 +0300 +Subject: net: sched: replaced invalid qdisc tree flush helper in qdisc_replace + +From: Alexander Ovechkin + +commit 938e0fcd3253efdef8924714158911286d08cfe1 upstream. + +Commit e5f0e8f8e456 ("net: sched: introduce and use qdisc tree flush/purge helpers") +introduced qdisc tree flush/purge helpers, but erroneously used flush helper +instead of purge helper in qdisc_replace function. +This issue was found in our CI, that tests various qdisc setups by configuring +qdisc and sending data through it. Call of invalid helper sporadically leads +to corruption of vt_tree/cf_tree of hfsc_class that causes kernel oops: + + Oops: 0000 [#1] SMP PTI + CPU: 1 PID: 0 Comm: swapper/1 Not tainted 5.11.0-8f6859df #1 + Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.10.2-0-g5f4c7b1-prebuilt.qemu-project.org 04/01/2014 + RIP: 0010:rb_insert_color+0x18/0x190 + Code: c3 31 c0 c3 0f 1f 40 00 66 2e 0f 1f 84 00 00 00 00 00 48 8b 07 48 85 c0 0f 84 05 01 00 00 48 8b 10 f6 c2 01 0f 85 34 01 00 00 <48> 8b 4a 08 49 89 d0 48 39 c1 74 7d 48 85 c9 74 32 f6 01 01 75 2d + RSP: 0018:ffffc900000b8bb0 EFLAGS: 00010246 + RAX: ffff8881ef4c38b0 RBX: ffff8881d956e400 RCX: ffff8881ef4c38b0 + RDX: 0000000000000000 RSI: ffff8881d956f0a8 RDI: ffff8881d956e4b0 + RBP: 0000000000000000 R08: 000000d5c4e249da R09: 1600000000000000 + R10: ffffc900000b8be0 R11: ffffc900000b8b28 R12: 0000000000000001 + R13: 000000000000005a R14: ffff8881f0905000 R15: ffff8881f0387d00 + FS: 0000000000000000(0000) GS:ffff8881f8b00000(0000) knlGS:0000000000000000 + CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 + CR2: 0000000000000008 CR3: 00000001f4796004 CR4: 0000000000060ee0 + Call Trace: + + init_vf.isra.19+0xec/0x250 [sch_hfsc] + hfsc_enqueue+0x245/0x300 [sch_hfsc] + ? fib_rules_lookup+0x12a/0x1d0 + ? __dev_queue_xmit+0x4b6/0x930 + ? hfsc_delete_class+0x250/0x250 [sch_hfsc] + __dev_queue_xmit+0x4b6/0x930 + ? ip6_finish_output2+0x24d/0x590 + ip6_finish_output2+0x24d/0x590 + ? ip6_output+0x6c/0x130 + ip6_output+0x6c/0x130 + ? __ip6_finish_output+0x110/0x110 + mld_sendpack+0x224/0x230 + mld_ifc_timer_expire+0x186/0x2c0 + ? igmp6_group_dropped+0x200/0x200 + call_timer_fn+0x2d/0x150 + run_timer_softirq+0x20c/0x480 + ? tick_sched_do_timer+0x60/0x60 + ? tick_sched_timer+0x37/0x70 + __do_softirq+0xf7/0x2cb + irq_exit+0xa0/0xb0 + smp_apic_timer_interrupt+0x74/0x150 + apic_timer_interrupt+0xf/0x20 + + +Fixes: e5f0e8f8e456 ("net: sched: introduce and use qdisc tree flush/purge helpers") +Signed-off-by: Alexander Ovechkin +Reported-by: Alexander Kuznetsov +Acked-by: Dmitry Monakhov +Acked-by: Dmitry Yakunin +Acked-by: Cong Wang +Link: https://lore.kernel.org/r/20210201200049.299153-1-ovov@yandex-team.ru +Signed-off-by: Jakub Kicinski +Signed-off-by: Greg Kroah-Hartman +--- + include/net/sch_generic.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/include/net/sch_generic.h ++++ b/include/net/sch_generic.h +@@ -1155,7 +1155,7 @@ static inline struct Qdisc *qdisc_replac + old = *pold; + *pold = new; + if (old != NULL) +- qdisc_tree_flush_backlog(old); ++ qdisc_purge_queue(old); + sch_tree_unlock(sch); + + return old; diff --git a/queue-5.10/series b/queue-5.10/series index 5a2b7174980..850e7b3cf88 100644 --- a/queue-5.10/series +++ b/queue-5.10/series @@ -112,3 +112,9 @@ input-goodix-add-support-for-goodix-gt9286-chip.patch input-xpad-sync-supported-devices-with-fork-on-github.patch input-ili210x-implement-pressure-reporting-for-ili251x.patch md-set-prev_flush_start-and-flush_bio-in-an-atomic-way.patch +igc-report-speed-and-duplex-as-unknown-when-device-is-runtime-suspended.patch +neighbour-prevent-a-dead-entry-from-updating-gc_list.patch +net-ip_tunnel-fix-mtu-calculation.patch +udp-ipv4-manipulate-network-header-of-nated-udp-gro-fraglist.patch +net-dsa-mv88e6xxx-override-existent-unicast-portvec-in-port_fdb_add.patch +net-sched-replaced-invalid-qdisc-tree-flush-helper-in-qdisc_replace.patch diff --git a/queue-5.10/udp-ipv4-manipulate-network-header-of-nated-udp-gro-fraglist.patch b/queue-5.10/udp-ipv4-manipulate-network-header-of-nated-udp-gro-fraglist.patch new file mode 100644 index 00000000000..18fc1d2fc2a --- /dev/null +++ b/queue-5.10/udp-ipv4-manipulate-network-header-of-nated-udp-gro-fraglist.patch @@ -0,0 +1,158 @@ +From c3df39ac9b0e3747bf8233ea9ce4ed5ceb3199d3 Mon Sep 17 00:00:00 2001 +From: Dongseok Yi +Date: Sat, 30 Jan 2021 08:13:27 +0900 +Subject: udp: ipv4: manipulate network header of NATed UDP GRO fraglist + +From: Dongseok Yi + +commit c3df39ac9b0e3747bf8233ea9ce4ed5ceb3199d3 upstream. + +UDP/IP header of UDP GROed frag_skbs are not updated even after NAT +forwarding. Only the header of head_skb from ip_finish_output_gso -> +skb_gso_segment is updated but following frag_skbs are not updated. + +A call path skb_mac_gso_segment -> inet_gso_segment -> +udp4_ufo_fragment -> __udp_gso_segment -> __udp_gso_segment_list +does not try to update UDP/IP header of the segment list but copy +only the MAC header. + +Update port, addr and check of each skb of the segment list in +__udp_gso_segment_list. It covers both SNAT and DNAT. + +Fixes: 9fd1ff5d2ac7 (udp: Support UDP fraglist GRO/GSO.) +Signed-off-by: Dongseok Yi +Acked-by: Steffen Klassert +Link: https://lore.kernel.org/r/1611962007-80092-1-git-send-email-dseok.yi@samsung.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Greg Kroah-Hartman +--- + include/net/udp.h | 2 - + net/ipv4/udp_offload.c | 69 +++++++++++++++++++++++++++++++++++++++++++++---- + net/ipv6/udp_offload.c | 2 - + 3 files changed, 66 insertions(+), 7 deletions(-) + +--- a/include/net/udp.h ++++ b/include/net/udp.h +@@ -178,7 +178,7 @@ struct sk_buff *udp_gro_receive(struct l + int udp_gro_complete(struct sk_buff *skb, int nhoff, udp_lookup_t lookup); + + struct sk_buff *__udp_gso_segment(struct sk_buff *gso_skb, +- netdev_features_t features); ++ netdev_features_t features, bool is_ipv6); + + static inline struct udphdr *udp_gro_udphdr(struct sk_buff *skb) + { +--- a/net/ipv4/udp_offload.c ++++ b/net/ipv4/udp_offload.c +@@ -184,8 +184,67 @@ out_unlock: + } + EXPORT_SYMBOL(skb_udp_tunnel_segment); + ++static void __udpv4_gso_segment_csum(struct sk_buff *seg, ++ __be32 *oldip, __be32 *newip, ++ __be16 *oldport, __be16 *newport) ++{ ++ struct udphdr *uh; ++ struct iphdr *iph; ++ ++ if (*oldip == *newip && *oldport == *newport) ++ return; ++ ++ uh = udp_hdr(seg); ++ iph = ip_hdr(seg); ++ ++ if (uh->check) { ++ inet_proto_csum_replace4(&uh->check, seg, *oldip, *newip, ++ true); ++ inet_proto_csum_replace2(&uh->check, seg, *oldport, *newport, ++ false); ++ if (!uh->check) ++ uh->check = CSUM_MANGLED_0; ++ } ++ *oldport = *newport; ++ ++ csum_replace4(&iph->check, *oldip, *newip); ++ *oldip = *newip; ++} ++ ++static struct sk_buff *__udpv4_gso_segment_list_csum(struct sk_buff *segs) ++{ ++ struct sk_buff *seg; ++ struct udphdr *uh, *uh2; ++ struct iphdr *iph, *iph2; ++ ++ seg = segs; ++ uh = udp_hdr(seg); ++ iph = ip_hdr(seg); ++ ++ if ((udp_hdr(seg)->dest == udp_hdr(seg->next)->dest) && ++ (udp_hdr(seg)->source == udp_hdr(seg->next)->source) && ++ (ip_hdr(seg)->daddr == ip_hdr(seg->next)->daddr) && ++ (ip_hdr(seg)->saddr == ip_hdr(seg->next)->saddr)) ++ return segs; ++ ++ while ((seg = seg->next)) { ++ uh2 = udp_hdr(seg); ++ iph2 = ip_hdr(seg); ++ ++ __udpv4_gso_segment_csum(seg, ++ &iph2->saddr, &iph->saddr, ++ &uh2->source, &uh->source); ++ __udpv4_gso_segment_csum(seg, ++ &iph2->daddr, &iph->daddr, ++ &uh2->dest, &uh->dest); ++ } ++ ++ return segs; ++} ++ + static struct sk_buff *__udp_gso_segment_list(struct sk_buff *skb, +- netdev_features_t features) ++ netdev_features_t features, ++ bool is_ipv6) + { + unsigned int mss = skb_shinfo(skb)->gso_size; + +@@ -195,11 +254,11 @@ static struct sk_buff *__udp_gso_segment + + udp_hdr(skb)->len = htons(sizeof(struct udphdr) + mss); + +- return skb; ++ return is_ipv6 ? skb : __udpv4_gso_segment_list_csum(skb); + } + + struct sk_buff *__udp_gso_segment(struct sk_buff *gso_skb, +- netdev_features_t features) ++ netdev_features_t features, bool is_ipv6) + { + struct sock *sk = gso_skb->sk; + unsigned int sum_truesize = 0; +@@ -211,7 +270,7 @@ struct sk_buff *__udp_gso_segment(struct + __be16 newlen; + + if (skb_shinfo(gso_skb)->gso_type & SKB_GSO_FRAGLIST) +- return __udp_gso_segment_list(gso_skb, features); ++ return __udp_gso_segment_list(gso_skb, features, is_ipv6); + + mss = skb_shinfo(gso_skb)->gso_size; + if (gso_skb->len <= sizeof(*uh) + mss) +@@ -325,7 +384,7 @@ static struct sk_buff *udp4_ufo_fragment + goto out; + + if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4) +- return __udp_gso_segment(skb, features); ++ return __udp_gso_segment(skb, features, false); + + mss = skb_shinfo(skb)->gso_size; + if (unlikely(skb->len <= mss)) +--- a/net/ipv6/udp_offload.c ++++ b/net/ipv6/udp_offload.c +@@ -46,7 +46,7 @@ static struct sk_buff *udp6_ufo_fragment + goto out; + + if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4) +- return __udp_gso_segment(skb, features); ++ return __udp_gso_segment(skb, features, true); + + /* Do software UFO. Complete and fill in the UDP checksum as HW cannot + * do checksum of UDP packets sent as multiple IP fragments.