]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.15-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 21 Sep 2022 09:01:48 +0000 (11:01 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 21 Sep 2022 09:01:48 +0000 (11:01 +0200)
added patches:
net-find-dst-with-sk-s-xfrm-policy-not-ctl_sk.patch

queue-5.15/net-find-dst-with-sk-s-xfrm-policy-not-ctl_sk.patch [new file with mode: 0644]
queue-5.15/series

diff --git a/queue-5.15/net-find-dst-with-sk-s-xfrm-policy-not-ctl_sk.patch b/queue-5.15/net-find-dst-with-sk-s-xfrm-policy-not-ctl_sk.patch
new file mode 100644 (file)
index 0000000..015e70e
--- /dev/null
@@ -0,0 +1,107 @@
+From e22aa14866684f77b4f6b6cae98539e520ddb731 Mon Sep 17 00:00:00 2001
+From: sewookseo <sewookseo@google.com>
+Date: Thu, 7 Jul 2022 10:01:39 +0000
+Subject: net: Find dst with sk's xfrm policy not ctl_sk
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: sewookseo <sewookseo@google.com>
+
+commit e22aa14866684f77b4f6b6cae98539e520ddb731 upstream.
+
+If we set XFRM security policy by calling setsockopt with option
+IPV6_XFRM_POLICY, the policy will be stored in 'sock_policy' in 'sock'
+struct. However tcp_v6_send_response doesn't look up dst_entry with the
+actual socket but looks up with tcp control socket. This may cause a
+problem that a RST packet is sent without ESP encryption & peer's TCP
+socket can't receive it.
+This patch will make the function look up dest_entry with actual socket,
+if the socket has XFRM policy(sock_policy), so that the TCP response
+packet via this function can be encrypted, & aligned on the encrypted
+TCP socket.
+
+Tested: We encountered this problem when a TCP socket which is encrypted
+in ESP transport mode encryption, receives challenge ACK at SYN_SENT
+state. After receiving challenge ACK, TCP needs to send RST to
+establish the socket at next SYN try. But the RST was not encrypted &
+peer TCP socket still remains on ESTABLISHED state.
+So we verified this with test step as below.
+[Test step]
+1. Making a TCP state mismatch between client(IDLE) & server(ESTABLISHED).
+2. Client tries a new connection on the same TCP ports(src & dst).
+3. Server will return challenge ACK instead of SYN,ACK.
+4. Client will send RST to server to clear the SOCKET.
+5. Client will retransmit SYN to server on the same TCP ports.
+[Expected result]
+The TCP connection should be established.
+
+Cc: Maciej Żenczykowski <maze@google.com>
+Cc: Eric Dumazet <edumazet@google.com>
+Cc: Steffen Klassert <steffen.klassert@secunet.com>
+Cc: Sehee Lee <seheele@google.com>
+Signed-off-by: Sewook Seo <sewookseo@google.com>
+Reviewed-by: Eric Dumazet <edumazet@google.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/net/xfrm.h   |    2 ++
+ net/ipv4/ip_output.c |    2 +-
+ net/ipv4/tcp_ipv4.c  |    2 ++
+ net/ipv6/tcp_ipv6.c  |    5 ++++-
+ 4 files changed, 9 insertions(+), 2 deletions(-)
+
+--- a/include/net/xfrm.h
++++ b/include/net/xfrm.h
+@@ -1190,6 +1190,8 @@ int __xfrm_sk_clone_policy(struct sock *
+ static inline int xfrm_sk_clone_policy(struct sock *sk, const struct sock *osk)
+ {
++      if (!sk_fullsock(osk))
++              return 0;
+       sk->sk_policy[0] = NULL;
+       sk->sk_policy[1] = NULL;
+       if (unlikely(osk->sk_policy[0] || osk->sk_policy[1]))
+--- a/net/ipv4/ip_output.c
++++ b/net/ipv4/ip_output.c
+@@ -1704,7 +1704,7 @@ void ip_send_unicast_reply(struct sock *
+                          tcp_hdr(skb)->source, tcp_hdr(skb)->dest,
+                          arg->uid);
+       security_skb_classify_flow(skb, flowi4_to_flowi_common(&fl4));
+-      rt = ip_route_output_key(net, &fl4);
++      rt = ip_route_output_flow(net, &fl4, sk);
+       if (IS_ERR(rt))
+               return;
+--- a/net/ipv4/tcp_ipv4.c
++++ b/net/ipv4/tcp_ipv4.c
+@@ -817,6 +817,7 @@ static void tcp_v4_send_reset(const stru
+               ctl_sk->sk_priority = (sk->sk_state == TCP_TIME_WAIT) ?
+                                  inet_twsk(sk)->tw_priority : sk->sk_priority;
+               transmit_time = tcp_transmit_time(sk);
++              xfrm_sk_clone_policy(ctl_sk, sk);
+       }
+       ip_send_unicast_reply(ctl_sk,
+                             skb, &TCP_SKB_CB(skb)->header.h4.opt,
+@@ -825,6 +826,7 @@ static void tcp_v4_send_reset(const stru
+                             transmit_time);
+       ctl_sk->sk_mark = 0;
++      xfrm_sk_free_policy(ctl_sk);
+       sock_net_set(ctl_sk, &init_net);
+       __TCP_INC_STATS(net, TCP_MIB_OUTSEGS);
+       __TCP_INC_STATS(net, TCP_MIB_OUTRSTS);
+--- a/net/ipv6/tcp_ipv6.c
++++ b/net/ipv6/tcp_ipv6.c
+@@ -1001,7 +1001,10 @@ static void tcp_v6_send_response(const s
+        * Underlying function will use this to retrieve the network
+        * namespace
+        */
+-      dst = ip6_dst_lookup_flow(sock_net(ctl_sk), ctl_sk, &fl6, NULL);
++      if (sk && sk->sk_state != TCP_TIME_WAIT)
++              dst = ip6_dst_lookup_flow(net, sk, &fl6, NULL); /*sk's xfrm_policy can be referred*/
++      else
++              dst = ip6_dst_lookup_flow(net, ctl_sk, &fl6, NULL);
+       if (!IS_ERR(dst)) {
+               skb_dst_set(buff, dst);
+               ip6_xmit(ctl_sk, buff, &fl6, fl6.flowi6_mark, NULL,
index b98861ffce04c69917d46f350fa71dc396bdf635..faf4a8002b34541fca00ba770ed741cb50843e47 100644 (file)
@@ -39,3 +39,4 @@ mips-octeon-irq-fix-octeon_irq_force_ciu_mapping.patch
 drm-panfrost-devfreq-set-opp-to-the-recommended-one-.patch
 mksysmap-fix-the-mismatch-of-l0-symbols-in-system.ma.patch
 video-fbdev-pxa3xx-gcu-fix-integer-overflow-in-pxa3x.patch
+net-find-dst-with-sk-s-xfrm-policy-not-ctl_sk.patch