]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 23 Jun 2025 08:47:12 +0000 (10:47 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 23 Jun 2025 08:47:12 +0000 (10:47 +0200)
added patches:
net-fix-checksum-update-for-ila-adj-transport.patch
xprtrdma-fix-pointer-derefs-in-error-cases-of-rpcrdma_ep_create.patch

queue-5.4/net-fix-checksum-update-for-ila-adj-transport.patch [new file with mode: 0644]
queue-5.4/series
queue-5.4/xprtrdma-fix-pointer-derefs-in-error-cases-of-rpcrdma_ep_create.patch [new file with mode: 0644]

diff --git a/queue-5.4/net-fix-checksum-update-for-ila-adj-transport.patch b/queue-5.4/net-fix-checksum-update-for-ila-adj-transport.patch
new file mode 100644 (file)
index 0000000..36c5fcb
--- /dev/null
@@ -0,0 +1,158 @@
+From 6043b794c7668c19dabc4a93c75b924a19474d59 Mon Sep 17 00:00:00 2001
+From: Paul Chaignon <paul.chaignon@gmail.com>
+Date: Thu, 29 May 2025 12:28:05 +0200
+Subject: net: Fix checksum update for ILA adj-transport
+
+From: Paul Chaignon <paul.chaignon@gmail.com>
+
+commit 6043b794c7668c19dabc4a93c75b924a19474d59 upstream.
+
+During ILA address translations, the L4 checksums can be handled in
+different ways. One of them, adj-transport, consist in parsing the
+transport layer and updating any found checksum. This logic relies on
+inet_proto_csum_replace_by_diff and produces an incorrect skb->csum when
+in state CHECKSUM_COMPLETE.
+
+This bug can be reproduced with a simple ILA to SIR mapping, assuming
+packets are received with CHECKSUM_COMPLETE:
+
+  $ ip a show dev eth0
+  14: eth0@if15: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
+      link/ether 62:ae:35:9e:0f:8d brd ff:ff:ff:ff:ff:ff link-netnsid 0
+      inet6 3333:0:0:1::c078/64 scope global
+         valid_lft forever preferred_lft forever
+      inet6 fd00:10:244:1::c078/128 scope global nodad
+         valid_lft forever preferred_lft forever
+      inet6 fe80::60ae:35ff:fe9e:f8d/64 scope link proto kernel_ll
+         valid_lft forever preferred_lft forever
+  $ ip ila add loc_match fd00:10:244:1 loc 3333:0:0:1 \
+      csum-mode adj-transport ident-type luid dev eth0
+
+Then I hit [fd00:10:244:1::c078]:8000 with a server listening only on
+[3333:0:0:1::c078]:8000. With the bug, the SYN packet is dropped with
+SKB_DROP_REASON_TCP_CSUM after inet_proto_csum_replace_by_diff changed
+skb->csum. The translation and drop are visible on pwru [1] traces:
+
+  IFACE   TUPLE                                                        FUNC
+  eth0:9  [fd00:10:244:3::3d8]:51420->[fd00:10:244:1::c078]:8000(tcp)  ipv6_rcv
+  eth0:9  [fd00:10:244:3::3d8]:51420->[fd00:10:244:1::c078]:8000(tcp)  ip6_rcv_core
+  eth0:9  [fd00:10:244:3::3d8]:51420->[fd00:10:244:1::c078]:8000(tcp)  nf_hook_slow
+  eth0:9  [fd00:10:244:3::3d8]:51420->[fd00:10:244:1::c078]:8000(tcp)  inet_proto_csum_replace_by_diff
+  eth0:9  [fd00:10:244:3::3d8]:51420->[3333:0:0:1::c078]:8000(tcp)     tcp_v6_early_demux
+  eth0:9  [fd00:10:244:3::3d8]:51420->[3333:0:0:1::c078]:8000(tcp)     ip6_route_input
+  eth0:9  [fd00:10:244:3::3d8]:51420->[3333:0:0:1::c078]:8000(tcp)     ip6_input
+  eth0:9  [fd00:10:244:3::3d8]:51420->[3333:0:0:1::c078]:8000(tcp)     ip6_input_finish
+  eth0:9  [fd00:10:244:3::3d8]:51420->[3333:0:0:1::c078]:8000(tcp)     ip6_protocol_deliver_rcu
+  eth0:9  [fd00:10:244:3::3d8]:51420->[3333:0:0:1::c078]:8000(tcp)     raw6_local_deliver
+  eth0:9  [fd00:10:244:3::3d8]:51420->[3333:0:0:1::c078]:8000(tcp)     ipv6_raw_deliver
+  eth0:9  [fd00:10:244:3::3d8]:51420->[3333:0:0:1::c078]:8000(tcp)     tcp_v6_rcv
+  eth0:9  [fd00:10:244:3::3d8]:51420->[3333:0:0:1::c078]:8000(tcp)     __skb_checksum_complete
+  eth0:9  [fd00:10:244:3::3d8]:51420->[3333:0:0:1::c078]:8000(tcp)     kfree_skb_reason(SKB_DROP_REASON_TCP_CSUM)
+  eth0:9  [fd00:10:244:3::3d8]:51420->[3333:0:0:1::c078]:8000(tcp)     skb_release_head_state
+  eth0:9  [fd00:10:244:3::3d8]:51420->[3333:0:0:1::c078]:8000(tcp)     skb_release_data
+  eth0:9  [fd00:10:244:3::3d8]:51420->[3333:0:0:1::c078]:8000(tcp)     skb_free_head
+  eth0:9  [fd00:10:244:3::3d8]:51420->[3333:0:0:1::c078]:8000(tcp)     kfree_skbmem
+
+This is happening because inet_proto_csum_replace_by_diff is updating
+skb->csum when it shouldn't. The L4 checksum is updated such that it
+"cancels" the IPv6 address change in terms of checksum computation, so
+the impact on skb->csum is null.
+
+Note this would be different for an IPv4 packet since three fields
+would be updated: the IPv4 address, the IP checksum, and the L4
+checksum. Two would cancel each other and skb->csum would still need
+to be updated to take the L4 checksum change into account.
+
+This patch fixes it by passing an ipv6 flag to
+inet_proto_csum_replace_by_diff, to skip the skb->csum update if we're
+in the IPv6 case. Note the behavior of the only other user of
+inet_proto_csum_replace_by_diff, the BPF subsystem, is left as is in
+this patch and fixed in the subsequent patch.
+
+With the fix, using the reproduction from above, I can confirm
+skb->csum is not touched by inet_proto_csum_replace_by_diff and the TCP
+SYN proceeds to the application after the ILA translation.
+
+Link: https://github.com/cilium/pwru [1]
+Fixes: 65d7ab8de582 ("net: Identifier Locator Addressing module")
+Signed-off-by: Paul Chaignon <paul.chaignon@gmail.com>
+Acked-by: Daniel Borkmann <daniel@iogearbox.net>
+Link: https://patch.msgid.link/b5539869e3550d46068504feb02d37653d939c0b.1748509484.git.paul.chaignon@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+[ Fixed conflict due to unrelated change in inet_proto_csum_replace_by_diff. ]
+Signed-off-by: Paul Chaignon <paul.chaignon@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/net/checksum.h    |    2 +-
+ net/core/filter.c         |    2 +-
+ net/core/utils.c          |    4 ++--
+ net/ipv6/ila/ila_common.c |    6 +++---
+ 4 files changed, 7 insertions(+), 7 deletions(-)
+
+--- a/include/net/checksum.h
++++ b/include/net/checksum.h
+@@ -152,7 +152,7 @@ void inet_proto_csum_replace16(__sum16 *
+                              const __be32 *from, const __be32 *to,
+                              bool pseudohdr);
+ void inet_proto_csum_replace_by_diff(__sum16 *sum, struct sk_buff *skb,
+-                                   __wsum diff, bool pseudohdr);
++                                   __wsum diff, bool pseudohdr, bool ipv6);
+ static __always_inline
+ void inet_proto_csum_replace2(__sum16 *sum, struct sk_buff *skb,
+--- a/net/core/filter.c
++++ b/net/core/filter.c
+@@ -1949,7 +1949,7 @@ BPF_CALL_5(bpf_l4_csum_replace, struct s
+               if (unlikely(from != 0))
+                       return -EINVAL;
+-              inet_proto_csum_replace_by_diff(ptr, skb, to, is_pseudo);
++              inet_proto_csum_replace_by_diff(ptr, skb, to, is_pseudo, false);
+               break;
+       case 2:
+               inet_proto_csum_replace2(ptr, skb, from, to, is_pseudo);
+--- a/net/core/utils.c
++++ b/net/core/utils.c
+@@ -473,11 +473,11 @@ void inet_proto_csum_replace16(__sum16 *
+ EXPORT_SYMBOL(inet_proto_csum_replace16);
+ void inet_proto_csum_replace_by_diff(__sum16 *sum, struct sk_buff *skb,
+-                                   __wsum diff, bool pseudohdr)
++                                   __wsum diff, bool pseudohdr, bool ipv6)
+ {
+       if (skb->ip_summed != CHECKSUM_PARTIAL) {
+               *sum = csum_fold(csum_add(diff, ~csum_unfold(*sum)));
+-              if (skb->ip_summed == CHECKSUM_COMPLETE && pseudohdr)
++              if (skb->ip_summed == CHECKSUM_COMPLETE && pseudohdr && !ipv6)
+                       skb->csum = ~csum_add(diff, ~skb->csum);
+       } else if (pseudohdr) {
+               *sum = ~csum_fold(csum_add(diff, csum_unfold(*sum)));
+--- a/net/ipv6/ila/ila_common.c
++++ b/net/ipv6/ila/ila_common.c
+@@ -86,7 +86,7 @@ static void ila_csum_adjust_transport(st
+                       diff = get_csum_diff(ip6h, p);
+                       inet_proto_csum_replace_by_diff(&th->check, skb,
+-                                                      diff, true);
++                                                      diff, true, true);
+               }
+               break;
+       case NEXTHDR_UDP:
+@@ -97,7 +97,7 @@ static void ila_csum_adjust_transport(st
+                       if (uh->check || skb->ip_summed == CHECKSUM_PARTIAL) {
+                               diff = get_csum_diff(ip6h, p);
+                               inet_proto_csum_replace_by_diff(&uh->check, skb,
+-                                                              diff, true);
++                                                              diff, true, true);
+                               if (!uh->check)
+                                       uh->check = CSUM_MANGLED_0;
+                       }
+@@ -111,7 +111,7 @@ static void ila_csum_adjust_transport(st
+                       diff = get_csum_diff(ip6h, p);
+                       inet_proto_csum_replace_by_diff(&ih->icmp6_cksum, skb,
+-                                                      diff, true);
++                                                      diff, true, true);
+               }
+               break;
+       }
index 21efd68f2e2e6ffa841737fc1bcfd5113031f51b..a818571711fc2327b150f9912315bccfbc0637b6 100644 (file)
@@ -213,3 +213,5 @@ arm-dts-am335x-bone-common-add-gpio-phy-reset-on-revision-c3-board.patch
 arm-dts-am335x-bone-common-increase-mdio-reset-deassert-time.patch
 arm-dts-am335x-bone-common-increase-mdio-reset-deassert-delay-to-50ms.patch
 posix-cpu-timers-fix-race-between-handle_posix_cpu_timers-and-posix_cpu_timer_del.patch
+xprtrdma-fix-pointer-derefs-in-error-cases-of-rpcrdma_ep_create.patch
+net-fix-checksum-update-for-ila-adj-transport.patch
diff --git a/queue-5.4/xprtrdma-fix-pointer-derefs-in-error-cases-of-rpcrdma_ep_create.patch b/queue-5.4/xprtrdma-fix-pointer-derefs-in-error-cases-of-rpcrdma_ep_create.patch
new file mode 100644 (file)
index 0000000..84d613f
--- /dev/null
@@ -0,0 +1,42 @@
+From a9c10b5b3b67b3750a10c8b089b2e05f5e176e33 Mon Sep 17 00:00:00 2001
+From: Dan Aloni <dan.aloni@vastdata.com>
+Date: Tue, 25 Jan 2022 22:06:46 +0200
+Subject: xprtrdma: fix pointer derefs in error cases of rpcrdma_ep_create
+
+From: Dan Aloni <dan.aloni@vastdata.com>
+
+commit a9c10b5b3b67b3750a10c8b089b2e05f5e176e33 upstream.
+
+If there are failures then we must not leave the non-NULL pointers with
+the error value, otherwise `rpcrdma_ep_destroy` gets confused and tries
+free them, resulting in an Oops.
+
+Signed-off-by: Dan Aloni <dan.aloni@vastdata.com>
+Acked-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
+[ Larry: backport to 5.4.y. Minor conflict resolved due to missing commit 93aa8e0a9de80
+  xprtrdma: Merge struct rpcrdma_ia into struct rpcrdma_ep ]
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Larry Bassel <larry.bassel@oracle.com>
+---
+ net/sunrpc/xprtrdma/verbs.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/net/sunrpc/xprtrdma/verbs.c
++++ b/net/sunrpc/xprtrdma/verbs.c
+@@ -525,6 +525,7 @@ int rpcrdma_ep_create(struct rpcrdma_xpr
+                                IB_POLL_WORKQUEUE);
+       if (IS_ERR(sendcq)) {
+               rc = PTR_ERR(sendcq);
++              sendcq = NULL;
+               goto out1;
+       }
+@@ -533,6 +534,7 @@ int rpcrdma_ep_create(struct rpcrdma_xpr
+                                IB_POLL_WORKQUEUE);
+       if (IS_ERR(recvcq)) {
+               rc = PTR_ERR(recvcq);
++              recvcq = NULL;
+               goto out2;
+       }