]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 22 Jul 2021 15:42:04 +0000 (17:42 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 22 Jul 2021 15:42:04 +0000 (17:42 +0200)
added patches:
ipv6-tcp-drop-silly-icmpv6-packet-too-big-messages.patch
tcp-annotate-data-races-around-tp-mtu_info.patch

queue-4.4/ipv6-tcp-drop-silly-icmpv6-packet-too-big-messages.patch [new file with mode: 0644]
queue-4.4/series
queue-4.4/tcp-annotate-data-races-around-tp-mtu_info.patch [new file with mode: 0644]

diff --git a/queue-4.4/ipv6-tcp-drop-silly-icmpv6-packet-too-big-messages.patch b/queue-4.4/ipv6-tcp-drop-silly-icmpv6-packet-too-big-messages.patch
new file mode 100644 (file)
index 0000000..40334f7
--- /dev/null
@@ -0,0 +1,130 @@
+From c7bb4b89033b764eb07db4e060548a6311d801ee Mon Sep 17 00:00:00 2001
+From: Eric Dumazet <edumazet@google.com>
+Date: Thu, 8 Jul 2021 00:21:09 -0700
+Subject: ipv6: tcp: drop silly ICMPv6 packet too big messages
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Eric Dumazet <edumazet@google.com>
+
+commit c7bb4b89033b764eb07db4e060548a6311d801ee upstream.
+
+While TCP stack scales reasonably well, there is still one part that
+can be used to DDOS it.
+
+IPv6 Packet too big messages have to lookup/insert a new route,
+and if abused by attackers, can easily put hosts under high stress,
+with many cpus contending on a spinlock while one is stuck in fib6_run_gc()
+
+ip6_protocol_deliver_rcu()
+ icmpv6_rcv()
+  icmpv6_notify()
+   tcp_v6_err()
+    tcp_v6_mtu_reduced()
+     inet6_csk_update_pmtu()
+      ip6_rt_update_pmtu()
+       __ip6_rt_update_pmtu()
+        ip6_rt_cache_alloc()
+         ip6_dst_alloc()
+          dst_alloc()
+           ip6_dst_gc()
+            fib6_run_gc()
+             spin_lock_bh() ...
+
+Some of our servers have been hit by malicious ICMPv6 packets
+trying to _increase_ the MTU/MSS of TCP flows.
+
+We believe these ICMPv6 packets are a result of a bug in one ISP stack,
+since they were blindly sent back for _every_ (small) packet sent to them.
+
+These packets are for one TCP flow:
+09:24:36.266491 IP6 Addr1 > Victim ICMP6, packet too big, mtu 1460, length 1240
+09:24:36.266509 IP6 Addr1 > Victim ICMP6, packet too big, mtu 1460, length 1240
+09:24:36.316688 IP6 Addr1 > Victim ICMP6, packet too big, mtu 1460, length 1240
+09:24:36.316704 IP6 Addr1 > Victim ICMP6, packet too big, mtu 1460, length 1240
+09:24:36.608151 IP6 Addr1 > Victim ICMP6, packet too big, mtu 1460, length 1240
+
+TCP stack can filter some silly requests :
+
+1) MTU below IPV6_MIN_MTU can be filtered early in tcp_v6_err()
+2) tcp_v6_mtu_reduced() can drop requests trying to increase current MSS.
+
+This tests happen before the IPv6 routing stack is entered, thus
+removing the potential contention and route exhaustion.
+
+Note that IPv6 stack was performing these checks, but too late
+(ie : after the route has been added, and after the potential
+garbage collect war)
+
+v2: fix typo caught by Martin, thanks !
+v3: exports tcp_mtu_to_mss(), caught by David, thanks !
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: Maciej Żenczykowski <maze@google.com>
+Cc: Martin KaFai Lau <kafai@fb.com>
+Acked-by: Martin KaFai Lau <kafai@fb.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv4/tcp_output.c |    1 +
+ net/ipv6/tcp_ipv6.c   |   19 +++++++++++++++++--
+ 2 files changed, 18 insertions(+), 2 deletions(-)
+
+--- a/net/ipv4/tcp_output.c
++++ b/net/ipv4/tcp_output.c
+@@ -1353,6 +1353,7 @@ int tcp_mtu_to_mss(struct sock *sk, int
+       return __tcp_mtu_to_mss(sk, pmtu) -
+              (tcp_sk(sk)->tcp_header_len - sizeof(struct tcphdr));
+ }
++EXPORT_SYMBOL(tcp_mtu_to_mss);
+ /* Inverse of above */
+ int tcp_mss_to_mtu(struct sock *sk, int mss)
+--- a/net/ipv6/tcp_ipv6.c
++++ b/net/ipv6/tcp_ipv6.c
+@@ -308,11 +308,20 @@ failure:
+ static void tcp_v6_mtu_reduced(struct sock *sk)
+ {
+       struct dst_entry *dst;
++      u32 mtu;
+       if ((1 << sk->sk_state) & (TCPF_LISTEN | TCPF_CLOSE))
+               return;
+-      dst = inet6_csk_update_pmtu(sk, READ_ONCE(tcp_sk(sk)->mtu_info));
++      mtu = READ_ONCE(tcp_sk(sk)->mtu_info);
++
++      /* Drop requests trying to increase our current mss.
++       * Check done in __ip6_rt_update_pmtu() is too late.
++       */
++      if (tcp_mtu_to_mss(sk, mtu) >= tcp_sk(sk)->mss_cache)
++              return;
++
++      dst = inet6_csk_update_pmtu(sk, mtu);
+       if (!dst)
+               return;
+@@ -391,6 +400,8 @@ static void tcp_v6_err(struct sk_buff *s
+       }
+       if (type == ICMPV6_PKT_TOOBIG) {
++              u32 mtu = ntohl(info);
++
+               /* We are not interested in TCP_LISTEN and open_requests
+                * (SYN-ACKs send out by Linux are always <576bytes so
+                * they should go through unfragmented).
+@@ -401,7 +412,11 @@ static void tcp_v6_err(struct sk_buff *s
+               if (!ip6_sk_accept_pmtu(sk))
+                       goto out;
+-              WRITE_ONCE(tp->mtu_info, ntohl(info));
++              if (mtu < IPV6_MIN_MTU)
++                      goto out;
++
++              WRITE_ONCE(tp->mtu_info, mtu);
++
+               if (!sock_owned_by_user(sk))
+                       tcp_v6_mtu_reduced(sk);
+               else if (!test_and_set_bit(TCP_MTU_REDUCED_DEFERRED,
index 838bd7e25361ee11345a4433961687687bf0d3e1..01041c06b312cc9b5935d9d92987281773de2765 100644 (file)
@@ -13,3 +13,5 @@ net-bcmgenet-ensure-all-tx-rx-queues-dmas-are-disabled.patch
 net-moxa-fix-uaf-in-moxart_mac_probe.patch
 net-ti-fix-uaf-in-tlan_remove_one.patch
 net-validate-lwtstate-data-before-returning-from-skb_tunnel_info.patch
+tcp-annotate-data-races-around-tp-mtu_info.patch
+ipv6-tcp-drop-silly-icmpv6-packet-too-big-messages.patch
diff --git a/queue-4.4/tcp-annotate-data-races-around-tp-mtu_info.patch b/queue-4.4/tcp-annotate-data-races-around-tp-mtu_info.patch
new file mode 100644 (file)
index 0000000..152cc78
--- /dev/null
@@ -0,0 +1,62 @@
+From 561022acb1ce62e50f7a8258687a21b84282a4cb Mon Sep 17 00:00:00 2001
+From: Eric Dumazet <edumazet@google.com>
+Date: Fri, 2 Jul 2021 13:09:03 -0700
+Subject: tcp: annotate data races around tp->mtu_info
+
+From: Eric Dumazet <edumazet@google.com>
+
+commit 561022acb1ce62e50f7a8258687a21b84282a4cb upstream.
+
+While tp->mtu_info is read while socket is owned, the write
+sides happen from err handlers (tcp_v[46]_mtu_reduced)
+which only own the socket spinlock.
+
+Fixes: 563d34d05786 ("tcp: dont drop MTU reduction indications")
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv4/tcp_ipv4.c |    4 ++--
+ net/ipv6/tcp_ipv6.c |    4 ++--
+ 2 files changed, 4 insertions(+), 4 deletions(-)
+
+--- a/net/ipv4/tcp_ipv4.c
++++ b/net/ipv4/tcp_ipv4.c
+@@ -277,7 +277,7 @@ void tcp_v4_mtu_reduced(struct sock *sk)
+       if ((1 << sk->sk_state) & (TCPF_LISTEN | TCPF_CLOSE))
+               return;
+-      mtu = tcp_sk(sk)->mtu_info;
++      mtu = READ_ONCE(tcp_sk(sk)->mtu_info);
+       dst = inet_csk_update_pmtu(sk, mtu);
+       if (!dst)
+               return;
+@@ -444,7 +444,7 @@ void tcp_v4_err(struct sk_buff *icmp_skb
+                       if (sk->sk_state == TCP_LISTEN)
+                               goto out;
+-                      tp->mtu_info = info;
++                      WRITE_ONCE(tp->mtu_info, info);
+                       if (!sock_owned_by_user(sk)) {
+                               tcp_v4_mtu_reduced(sk);
+                       } else {
+--- a/net/ipv6/tcp_ipv6.c
++++ b/net/ipv6/tcp_ipv6.c
+@@ -312,7 +312,7 @@ static void tcp_v6_mtu_reduced(struct so
+       if ((1 << sk->sk_state) & (TCPF_LISTEN | TCPF_CLOSE))
+               return;
+-      dst = inet6_csk_update_pmtu(sk, tcp_sk(sk)->mtu_info);
++      dst = inet6_csk_update_pmtu(sk, READ_ONCE(tcp_sk(sk)->mtu_info));
+       if (!dst)
+               return;
+@@ -401,7 +401,7 @@ static void tcp_v6_err(struct sk_buff *s
+               if (!ip6_sk_accept_pmtu(sk))
+                       goto out;
+-              tp->mtu_info = ntohl(info);
++              WRITE_ONCE(tp->mtu_info, ntohl(info));
+               if (!sock_owned_by_user(sk))
+                       tcp_v6_mtu_reduced(sk);
+               else if (!test_and_set_bit(TCP_MTU_REDUCED_DEFERRED,