]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.19-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 22 Jul 2021 15:45:41 +0000 (17:45 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 22 Jul 2021 15:45:41 +0000 (17:45 +0200)
added patches:
bpftool-properly-close-va_list-ap-by-va_end-on-error.patch
ipv6-tcp-drop-silly-icmpv6-packet-too-big-messages.patch
tcp-annotate-data-races-around-tp-mtu_info.patch
udp-annotate-data-races-around-unix_sk-sk-gso_size.patch

queue-4.19/bpftool-properly-close-va_list-ap-by-va_end-on-error.patch [new file with mode: 0644]
queue-4.19/ipv6-tcp-drop-silly-icmpv6-packet-too-big-messages.patch [new file with mode: 0644]
queue-4.19/series
queue-4.19/tcp-annotate-data-races-around-tp-mtu_info.patch [new file with mode: 0644]
queue-4.19/udp-annotate-data-races-around-unix_sk-sk-gso_size.patch [new file with mode: 0644]

diff --git a/queue-4.19/bpftool-properly-close-va_list-ap-by-va_end-on-error.patch b/queue-4.19/bpftool-properly-close-va_list-ap-by-va_end-on-error.patch
new file mode 100644 (file)
index 0000000..124f0e3
--- /dev/null
@@ -0,0 +1,40 @@
+From bc832065b60f973771ff3e657214bb21b559833c Mon Sep 17 00:00:00 2001
+From: Gu Shengxian <gushengxian@yulong.com>
+Date: Mon, 5 Jul 2021 18:35:43 -0700
+Subject: bpftool: Properly close va_list 'ap' by va_end() on error
+
+From: Gu Shengxian <gushengxian@yulong.com>
+
+commit bc832065b60f973771ff3e657214bb21b559833c upstream.
+
+va_list 'ap' was opened but not closed by va_end() in error case. It should
+be closed by va_end() before the return.
+
+Fixes: aa52bcbe0e72 ("tools: bpftool: Fix json dump crash on powerpc")
+Signed-off-by: Gu Shengxian <gushengxian@yulong.com>
+Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
+Cc: Jiri Olsa <jolsa@redhat.com>
+Link: https://lore.kernel.org/bpf/20210706013543.671114-1-gushengxian507419@gmail.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ tools/bpf/bpftool/jit_disasm.c |    6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+--- a/tools/bpf/bpftool/jit_disasm.c
++++ b/tools/bpf/bpftool/jit_disasm.c
+@@ -51,11 +51,13 @@ static int fprintf_json(void *out, const
+ {
+       va_list ap;
+       char *s;
++      int err;
+       va_start(ap, fmt);
+-      if (vasprintf(&s, fmt, ap) < 0)
+-              return -1;
++      err = vasprintf(&s, fmt, ap);
+       va_end(ap);
++      if (err < 0)
++              return -1;
+       if (!oper_count) {
+               int i;
diff --git a/queue-4.19/ipv6-tcp-drop-silly-icmpv6-packet-too-big-messages.patch b/queue-4.19/ipv6-tcp-drop-silly-icmpv6-packet-too-big-messages.patch
new file mode 100644 (file)
index 0000000..f8e0dff
--- /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
+@@ -1472,6 +1472,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
+@@ -336,11 +336,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;
+@@ -419,6 +428,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).
+@@ -429,7 +440,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 78e4c97c6f7cd9b005ff7accadaf5003d0a8201c..93fd01321134017d6497923aeb2eb564c785d65f 100644 (file)
@@ -45,3 +45,7 @@ net-ti-fix-uaf-in-tlan_remove_one.patch
 net-send-synack-packet-with-accepted-fwmark.patch
 net-validate-lwtstate-data-before-returning-from-skb_tunnel_info.patch
 dma-buf-sync_file-don-t-leak-fences-on-merge-failure.patch
+tcp-annotate-data-races-around-tp-mtu_info.patch
+ipv6-tcp-drop-silly-icmpv6-packet-too-big-messages.patch
+bpftool-properly-close-va_list-ap-by-va_end-on-error.patch
+udp-annotate-data-races-around-unix_sk-sk-gso_size.patch
diff --git a/queue-4.19/tcp-annotate-data-races-around-tp-mtu_info.patch b/queue-4.19/tcp-annotate-data-races-around-tp-mtu_info.patch
new file mode 100644 (file)
index 0000000..096fcb8
--- /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
+@@ -348,7 +348,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;
+@@ -516,7 +516,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
+@@ -340,7 +340,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;
+@@ -429,7 +429,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,
diff --git a/queue-4.19/udp-annotate-data-races-around-unix_sk-sk-gso_size.patch b/queue-4.19/udp-annotate-data-races-around-unix_sk-sk-gso_size.patch
new file mode 100644 (file)
index 0000000..8c6168c
--- /dev/null
@@ -0,0 +1,96 @@
+From 18a419bad63b7f68a1979e28459782518e7b6bbe Mon Sep 17 00:00:00 2001
+From: Eric Dumazet <edumazet@google.com>
+Date: Wed, 30 Jun 2021 09:42:44 -0700
+Subject: udp: annotate data races around unix_sk(sk)->gso_size
+
+From: Eric Dumazet <edumazet@google.com>
+
+commit 18a419bad63b7f68a1979e28459782518e7b6bbe upstream.
+
+Accesses to unix_sk(sk)->gso_size are lockless.
+Add READ_ONCE()/WRITE_ONCE() around them.
+
+BUG: KCSAN: data-race in udp_lib_setsockopt / udpv6_sendmsg
+
+write to 0xffff88812d78f47c of 2 bytes by task 10849 on cpu 1:
+ udp_lib_setsockopt+0x3b3/0x710 net/ipv4/udp.c:2696
+ udpv6_setsockopt+0x63/0x90 net/ipv6/udp.c:1630
+ sock_common_setsockopt+0x5d/0x70 net/core/sock.c:3265
+ __sys_setsockopt+0x18f/0x200 net/socket.c:2104
+ __do_sys_setsockopt net/socket.c:2115 [inline]
+ __se_sys_setsockopt net/socket.c:2112 [inline]
+ __x64_sys_setsockopt+0x62/0x70 net/socket.c:2112
+ do_syscall_64+0x4a/0x90 arch/x86/entry/common.c:47
+ entry_SYSCALL_64_after_hwframe+0x44/0xae
+
+read to 0xffff88812d78f47c of 2 bytes by task 10852 on cpu 0:
+ udpv6_sendmsg+0x161/0x16b0 net/ipv6/udp.c:1299
+ inet6_sendmsg+0x5f/0x80 net/ipv6/af_inet6.c:642
+ sock_sendmsg_nosec net/socket.c:654 [inline]
+ sock_sendmsg net/socket.c:674 [inline]
+ ____sys_sendmsg+0x360/0x4d0 net/socket.c:2337
+ ___sys_sendmsg net/socket.c:2391 [inline]
+ __sys_sendmmsg+0x315/0x4b0 net/socket.c:2477
+ __do_sys_sendmmsg net/socket.c:2506 [inline]
+ __se_sys_sendmmsg net/socket.c:2503 [inline]
+ __x64_sys_sendmmsg+0x53/0x60 net/socket.c:2503
+ do_syscall_64+0x4a/0x90 arch/x86/entry/common.c:47
+ entry_SYSCALL_64_after_hwframe+0x44/0xae
+
+value changed: 0x0000 -> 0x0005
+
+Reported by Kernel Concurrency Sanitizer on:
+CPU: 0 PID: 10852 Comm: syz-executor.0 Not tainted 5.13.0-syzkaller #0
+Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
+
+Fixes: bec1f6f69736 ("udp: generate gso with UDP_SEGMENT")
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Cc: Willem de Bruijn <willemb@google.com>
+Reported-by: syzbot <syzkaller@googlegroups.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv4/udp.c |    6 +++---
+ net/ipv6/udp.c |    2 +-
+ 2 files changed, 4 insertions(+), 4 deletions(-)
+
+--- a/net/ipv4/udp.c
++++ b/net/ipv4/udp.c
+@@ -997,7 +997,7 @@ int udp_sendmsg(struct sock *sk, struct
+       }
+       ipcm_init_sk(&ipc, inet);
+-      ipc.gso_size = up->gso_size;
++      ipc.gso_size = READ_ONCE(up->gso_size);
+       if (msg->msg_controllen) {
+               err = udp_cmsg_send(sk, msg, &ipc.gso_size);
+@@ -2505,7 +2505,7 @@ int udp_lib_setsockopt(struct sock *sk,
+       case UDP_SEGMENT:
+               if (val < 0 || val > USHRT_MAX)
+                       return -EINVAL;
+-              up->gso_size = val;
++              WRITE_ONCE(up->gso_size, val);
+               break;
+       /*
+@@ -2599,7 +2599,7 @@ int udp_lib_getsockopt(struct sock *sk,
+               break;
+       case UDP_SEGMENT:
+-              val = up->gso_size;
++              val = READ_ONCE(up->gso_size);
+               break;
+       /* The following two cannot be changed on UDP sockets, the return is
+--- a/net/ipv6/udp.c
++++ b/net/ipv6/udp.c
+@@ -1175,7 +1175,7 @@ int udpv6_sendmsg(struct sock *sk, struc
+       int (*getfrag)(void *, char *, int, int, int, struct sk_buff *);
+       ipcm6_init(&ipc6);
+-      ipc6.gso_size = up->gso_size;
++      ipc6.gso_size = READ_ONCE(up->gso_size);
+       ipc6.sockc.tsflags = sk->sk_tsflags;
+       /* destination address check */