From 57f01cb1e1b61ba6e89b2ec6ceafd5a498f76d71 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 21 Sep 2022 11:01:48 +0200 Subject: [PATCH] 5.15-stable patches added patches: net-find-dst-with-sk-s-xfrm-policy-not-ctl_sk.patch --- ...dst-with-sk-s-xfrm-policy-not-ctl_sk.patch | 107 ++++++++++++++++++ queue-5.15/series | 1 + 2 files changed, 108 insertions(+) create mode 100644 queue-5.15/net-find-dst-with-sk-s-xfrm-policy-not-ctl_sk.patch 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 index 00000000000..015e70e1259 --- /dev/null +++ b/queue-5.15/net-find-dst-with-sk-s-xfrm-policy-not-ctl_sk.patch @@ -0,0 +1,107 @@ +From e22aa14866684f77b4f6b6cae98539e520ddb731 Mon Sep 17 00:00:00 2001 +From: sewookseo +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 + +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 +Cc: Eric Dumazet +Cc: Steffen Klassert +Cc: Sehee Lee +Signed-off-by: Sewook Seo +Reviewed-by: Eric Dumazet +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + 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, diff --git a/queue-5.15/series b/queue-5.15/series index b98861ffce0..faf4a8002b3 100644 --- a/queue-5.15/series +++ b/queue-5.15/series @@ -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 -- 2.47.3