From: Greg Kroah-Hartman Date: Thu, 31 Dec 2020 09:23:06 +0000 (+0100) Subject: 4.9-stable patches X-Git-Tag: v4.19.165~33 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=e12f7c69db1c6c88bad8774241eac141626941e7;p=thirdparty%2Fkernel%2Fstable-queue.git 4.9-stable patches added patches: l2tp-fix-races-with-ipv4-mapped-ipv6-addresses.patch net-ipv6-keep-sk-status-consistent-after-datagram-connect-failure.patch --- diff --git a/queue-4.9/l2tp-fix-races-with-ipv4-mapped-ipv6-addresses.patch b/queue-4.9/l2tp-fix-races-with-ipv4-mapped-ipv6-addresses.patch new file mode 100644 index 00000000000..095dca88320 --- /dev/null +++ b/queue-4.9/l2tp-fix-races-with-ipv4-mapped-ipv6-addresses.patch @@ -0,0 +1,173 @@ +From b954f94023dcc61388c8384f0f14eb8e42c863c5 Mon Sep 17 00:00:00 2001 +From: Paolo Abeni +Date: Mon, 12 Mar 2018 14:54:24 +0100 +Subject: l2tp: fix races with ipv4-mapped ipv6 addresses + +From: Paolo Abeni + +commit b954f94023dcc61388c8384f0f14eb8e42c863c5 upstream. + +The l2tp_tunnel_create() function checks for v4mapped ipv6 +sockets and cache that flag, so that l2tp core code can +reusing it at xmit time. + +If the socket is provided by the userspace, the connection +status of the tunnel sockets can change between the tunnel +creation and the xmit call, so that syzbot is able to +trigger the following splat: + +BUG: KASAN: use-after-free in ip6_dst_idev include/net/ip6_fib.h:192 +[inline] +BUG: KASAN: use-after-free in ip6_xmit+0x1f76/0x2260 +net/ipv6/ip6_output.c:264 +Read of size 8 at addr ffff8801bd949318 by task syz-executor4/23448 + +CPU: 0 PID: 23448 Comm: syz-executor4 Not tainted 4.16.0-rc4+ #65 +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS +Google 01/01/2011 +Call Trace: + __dump_stack lib/dump_stack.c:17 [inline] + dump_stack+0x194/0x24d lib/dump_stack.c:53 + print_address_description+0x73/0x250 mm/kasan/report.c:256 + kasan_report_error mm/kasan/report.c:354 [inline] + kasan_report+0x23c/0x360 mm/kasan/report.c:412 + __asan_report_load8_noabort+0x14/0x20 mm/kasan/report.c:433 + ip6_dst_idev include/net/ip6_fib.h:192 [inline] + ip6_xmit+0x1f76/0x2260 net/ipv6/ip6_output.c:264 + inet6_csk_xmit+0x2fc/0x580 net/ipv6/inet6_connection_sock.c:139 + l2tp_xmit_core net/l2tp/l2tp_core.c:1053 [inline] + l2tp_xmit_skb+0x105f/0x1410 net/l2tp/l2tp_core.c:1148 + pppol2tp_sendmsg+0x470/0x670 net/l2tp/l2tp_ppp.c:341 + sock_sendmsg_nosec net/socket.c:630 [inline] + sock_sendmsg+0xca/0x110 net/socket.c:640 + ___sys_sendmsg+0x767/0x8b0 net/socket.c:2046 + __sys_sendmsg+0xe5/0x210 net/socket.c:2080 + SYSC_sendmsg net/socket.c:2091 [inline] + SyS_sendmsg+0x2d/0x50 net/socket.c:2087 + do_syscall_64+0x281/0x940 arch/x86/entry/common.c:287 + entry_SYSCALL_64_after_hwframe+0x42/0xb7 +RIP: 0033:0x453e69 +RSP: 002b:00007f819593cc68 EFLAGS: 00000246 ORIG_RAX: 000000000000002e +RAX: ffffffffffffffda RBX: 00007f819593d6d4 RCX: 0000000000453e69 +RDX: 0000000000000081 RSI: 000000002037ffc8 RDI: 0000000000000004 +RBP: 000000000072bea0 R08: 0000000000000000 R09: 0000000000000000 +R10: 0000000000000000 R11: 0000000000000246 R12: 00000000ffffffff +R13: 00000000000004c3 R14: 00000000006f72e8 R15: 0000000000000000 + +This change addresses the issues: +* explicitly checking for TCP_ESTABLISHED for user space provided sockets +* dropping the v4mapped flag usage - it can become outdated - and + explicitly invoking ipv6_addr_v4mapped() instead + +The issue is apparently there since ancient times. + +v1 -> v2: (many thanks to Guillaume) + - with csum issue introduced in v1 + - replace pr_err with pr_debug + - fix build issue with IPV6 disabled + - move l2tp_sk_is_v4mapped in l2tp_core.c + +v2 -> v3: + - don't update inet_daddr for v4mapped address, unneeded + - drop rendundant check at creation time + +Reported-and-tested-by: syzbot+92fa328176eb07e4ac1a@syzkaller.appspotmail.com +Fixes: 3557baabf280 ("[L2TP]: PPP over L2TP driver core") +Signed-off-by: Paolo Abeni +Signed-off-by: David S. Miller +Cc: Suren Baghdasaryan +Signed-off-by: Greg Kroah-Hartman + + +--- + net/l2tp/l2tp_core.c | 38 ++++++++++++++++++-------------------- + net/l2tp/l2tp_core.h | 3 --- + 2 files changed, 18 insertions(+), 23 deletions(-) + +--- a/net/l2tp/l2tp_core.c ++++ b/net/l2tp/l2tp_core.c +@@ -112,6 +112,13 @@ struct l2tp_net { + spinlock_t l2tp_session_hlist_lock; + }; + ++#if IS_ENABLED(CONFIG_IPV6) ++static bool l2tp_sk_is_v6(struct sock *sk) ++{ ++ return sk->sk_family == PF_INET6 && ++ !ipv6_addr_v4mapped(&sk->sk_v6_daddr); ++} ++#endif + + static inline struct l2tp_tunnel *l2tp_tunnel(struct sock *sk) + { +@@ -1136,7 +1143,7 @@ static int l2tp_xmit_core(struct l2tp_se + skb->ignore_df = 1; + skb_dst_drop(skb); + #if IS_ENABLED(CONFIG_IPV6) +- if (tunnel->sock->sk_family == PF_INET6 && !tunnel->v4mapped) ++ if (l2tp_sk_is_v6(tunnel->sock)) + error = inet6_csk_xmit(tunnel->sock, skb, NULL); + else + #endif +@@ -1199,6 +1206,15 @@ int l2tp_xmit_skb(struct l2tp_session *s + goto out_unlock; + } + ++ /* The user-space may change the connection status for the user-space ++ * provided socket at run time: we must check it under the socket lock ++ */ ++ if (tunnel->fd >= 0 && sk->sk_state != TCP_ESTABLISHED) { ++ kfree_skb(skb); ++ ret = NET_XMIT_DROP; ++ goto out_unlock; ++ } ++ + inet = inet_sk(sk); + fl = &inet->cork.fl; + switch (tunnel->encap) { +@@ -1214,7 +1230,7 @@ int l2tp_xmit_skb(struct l2tp_session *s + + /* Calculate UDP checksum if configured to do so */ + #if IS_ENABLED(CONFIG_IPV6) +- if (sk->sk_family == PF_INET6 && !tunnel->v4mapped) ++ if (l2tp_sk_is_v6(sk)) + udp6_set_csum(udp_get_no_check6_tx(sk), + skb, &inet6_sk(sk)->saddr, + &sk->sk_v6_daddr, udp_len); +@@ -1620,24 +1636,6 @@ int l2tp_tunnel_create(struct net *net, + if (cfg != NULL) + tunnel->debug = cfg->debug; + +-#if IS_ENABLED(CONFIG_IPV6) +- if (sk->sk_family == PF_INET6) { +- struct ipv6_pinfo *np = inet6_sk(sk); +- +- if (ipv6_addr_v4mapped(&np->saddr) && +- ipv6_addr_v4mapped(&sk->sk_v6_daddr)) { +- struct inet_sock *inet = inet_sk(sk); +- +- tunnel->v4mapped = true; +- inet->inet_saddr = np->saddr.s6_addr32[3]; +- inet->inet_rcv_saddr = sk->sk_v6_rcv_saddr.s6_addr32[3]; +- inet->inet_daddr = sk->sk_v6_daddr.s6_addr32[3]; +- } else { +- tunnel->v4mapped = false; +- } +- } +-#endif +- + /* Mark socket as an encapsulation socket. See net/ipv4/udp.c */ + tunnel->encap = encap; + if (encap == L2TP_ENCAPTYPE_UDP) { +--- a/net/l2tp/l2tp_core.h ++++ b/net/l2tp/l2tp_core.h +@@ -191,9 +191,6 @@ struct l2tp_tunnel { + struct sock *sock; /* Parent socket */ + int fd; /* Parent fd, if tunnel socket + * was created by userspace */ +-#if IS_ENABLED(CONFIG_IPV6) +- bool v4mapped; +-#endif + + struct work_struct del_work; + diff --git a/queue-4.9/net-ipv6-keep-sk-status-consistent-after-datagram-connect-failure.patch b/queue-4.9/net-ipv6-keep-sk-status-consistent-after-datagram-connect-failure.patch new file mode 100644 index 00000000000..07f23d7db19 --- /dev/null +++ b/queue-4.9/net-ipv6-keep-sk-status-consistent-after-datagram-connect-failure.patch @@ -0,0 +1,82 @@ +From 2f987a76a97773beafbc615b9c4d8fe79129a7f4 Mon Sep 17 00:00:00 2001 +From: Paolo Abeni +Date: Mon, 12 Mar 2018 14:54:23 +0100 +Subject: net: ipv6: keep sk status consistent after datagram connect failure + +From: Paolo Abeni + +commit 2f987a76a97773beafbc615b9c4d8fe79129a7f4 upstream. + +On unsuccesful ip6_datagram_connect(), if the failure is caused by +ip6_datagram_dst_update(), the sk peer information are cleared, but +the sk->sk_state is preserved. + +If the socket was already in an established status, the overall sk +status is inconsistent and fouls later checks in datagram code. + +Fix this saving the old peer information and restoring them in +case of failure. This also aligns ipv6 datagram connect() behavior +with ipv4. + +v1 -> v2: + - added missing Fixes tag + +Fixes: 85cb73ff9b74 ("net: ipv6: reset daddr and dport in sk if connect() fails") +Signed-off-by: Paolo Abeni +Signed-off-by: David S. Miller +Cc: Suren Baghdasaryan +Signed-off-by: Greg Kroah-Hartman + +--- + net/ipv6/datagram.c | 21 +++++++++++++++++---- + 1 file changed, 17 insertions(+), 4 deletions(-) + +--- a/net/ipv6/datagram.c ++++ b/net/ipv6/datagram.c +@@ -145,10 +145,12 @@ int __ip6_datagram_connect(struct sock * + struct sockaddr_in6 *usin = (struct sockaddr_in6 *) uaddr; + struct inet_sock *inet = inet_sk(sk); + struct ipv6_pinfo *np = inet6_sk(sk); +- struct in6_addr *daddr; ++ struct in6_addr *daddr, old_daddr; ++ __be32 fl6_flowlabel = 0; ++ __be32 old_fl6_flowlabel; ++ __be32 old_dport; + int addr_type; + int err; +- __be32 fl6_flowlabel = 0; + + if (usin->sin6_family == AF_INET) { + if (__ipv6_only_sock(sk)) +@@ -238,9 +240,13 @@ ipv4_connected: + } + } + ++ /* save the current peer information before updating it */ ++ old_daddr = sk->sk_v6_daddr; ++ old_fl6_flowlabel = np->flow_label; ++ old_dport = inet->inet_dport; ++ + sk->sk_v6_daddr = *daddr; + np->flow_label = fl6_flowlabel; +- + inet->inet_dport = usin->sin6_port; + + /* +@@ -249,8 +255,15 @@ ipv4_connected: + */ + + err = ip6_datagram_dst_update(sk, true); +- if (err) ++ if (err) { ++ /* Restore the socket peer info, to keep it consistent with ++ * the old socket state ++ */ ++ sk->sk_v6_daddr = old_daddr; ++ np->flow_label = old_fl6_flowlabel; ++ inet->inet_dport = old_dport; + goto out; ++ } + + sk->sk_state = TCP_ESTABLISHED; + sk_set_txhash(sk); diff --git a/queue-4.9/series b/queue-4.9/series index c8519876881..2c8d9a647a1 100644 --- a/queue-4.9/series +++ b/queue-4.9/series @@ -10,3 +10,5 @@ s390-smp-use-smp_get_base_cpu-helper-function.patch s390-smp-perform-initial-cpu-reset-also-for-smt-sibl.patch s390-dasd-fix-hanging-device-offline-processing.patch usb-serial-digi_acceleport-fix-write-wakeup-deadlock.patch +net-ipv6-keep-sk-status-consistent-after-datagram-connect-failure.patch +l2tp-fix-races-with-ipv4-mapped-ipv6-addresses.patch