From: Greg Kroah-Hartman Date: Wed, 27 Nov 2019 10:32:36 +0000 (+0100) Subject: 4.9-stable patches X-Git-Tag: v4.4.204~41 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=0a6dc7b4603d08bd1970562318ea25f25dc1ab72;p=thirdparty%2Fkernel%2Fstable-queue.git 4.9-stable patches added patches: l2tp-don-t-use-l2tp_tunnel_find-in-l2tp_ip-and-l2tp_ip6.patch --- diff --git a/queue-4.9/l2tp-don-t-use-l2tp_tunnel_find-in-l2tp_ip-and-l2tp_ip6.patch b/queue-4.9/l2tp-don-t-use-l2tp_tunnel_find-in-l2tp_ip-and-l2tp_ip6.patch new file mode 100644 index 00000000000..3611aa0d0ae --- /dev/null +++ b/queue-4.9/l2tp-don-t-use-l2tp_tunnel_find-in-l2tp_ip-and-l2tp_ip6.patch @@ -0,0 +1,130 @@ +From 8f7dc9ae4a7aece9fbc3e6637bdfa38b36bcdf09 Mon Sep 17 00:00:00 2001 +From: Guillaume Nault +Date: Fri, 3 Nov 2017 16:49:00 +0100 +Subject: l2tp: don't use l2tp_tunnel_find() in l2tp_ip and l2tp_ip6 + +From: Guillaume Nault + +commit 8f7dc9ae4a7aece9fbc3e6637bdfa38b36bcdf09 upstream. + +Using l2tp_tunnel_find() in l2tp_ip_recv() is wrong for two reasons: + + * It doesn't take a reference on the returned tunnel, which makes the + call racy wrt. concurrent tunnel deletion. + + * The lookup is only based on the tunnel identifier, so it can return + a tunnel that doesn't match the packet's addresses or protocol. + +For example, a packet sent to an L2TPv3 over IPv6 tunnel can be +delivered to an L2TPv2 over UDPv4 tunnel. This is worse than a simple +cross-talk: when delivering the packet to an L2TP over UDP tunnel, the +corresponding socket is UDP, where ->sk_backlog_rcv() is NULL. Calling +sk_receive_skb() will then crash the kernel by trying to execute this +callback. + +And l2tp_tunnel_find() isn't even needed here. __l2tp_ip_bind_lookup() +properly checks the socket binding and connection settings. It was used +as a fallback mechanism for finding tunnels that didn't have their data +path registered yet. But it's not limited to this case and can be used +to replace l2tp_tunnel_find() in the general case. + +Fix l2tp_ip6 in the same way. + +Fixes: 0d76751fad77 ("l2tp: Add L2TPv3 IP encapsulation (no UDP) support") +Fixes: a32e0eec7042 ("l2tp: introduce L2TPv3 IP encapsulation support for IPv6") +Signed-off-by: Guillaume Nault +Signed-off-by: David S. Miller +Cc: Nicolas Schier +Signed-off-by: Greg Kroah-Hartman + +--- + net/l2tp/l2tp_ip.c | 24 +++++++++--------------- + net/l2tp/l2tp_ip6.c | 24 +++++++++--------------- + 2 files changed, 18 insertions(+), 30 deletions(-) + +--- a/net/l2tp/l2tp_ip.c ++++ b/net/l2tp/l2tp_ip.c +@@ -116,6 +116,7 @@ static int l2tp_ip_recv(struct sk_buff * + unsigned char *ptr, *optr; + struct l2tp_session *session; + struct l2tp_tunnel *tunnel = NULL; ++ struct iphdr *iph; + int length; + + if (!pskb_may_pull(skb, 4)) +@@ -174,24 +175,17 @@ pass_up: + goto discard; + + tunnel_id = ntohl(*(__be32 *) &skb->data[4]); +- tunnel = l2tp_tunnel_find(net, tunnel_id); +- if (tunnel) { +- sk = tunnel->sock; +- sock_hold(sk); +- } else { +- struct iphdr *iph = (struct iphdr *) skb_network_header(skb); +- +- read_lock_bh(&l2tp_ip_lock); +- sk = __l2tp_ip_bind_lookup(net, iph->daddr, iph->saddr, +- inet_iif(skb), tunnel_id); +- if (!sk) { +- read_unlock_bh(&l2tp_ip_lock); +- goto discard; +- } ++ iph = (struct iphdr *)skb_network_header(skb); + +- sock_hold(sk); ++ read_lock_bh(&l2tp_ip_lock); ++ sk = __l2tp_ip_bind_lookup(net, iph->daddr, iph->saddr, inet_iif(skb), ++ tunnel_id); ++ if (!sk) { + read_unlock_bh(&l2tp_ip_lock); ++ goto discard; + } ++ sock_hold(sk); ++ read_unlock_bh(&l2tp_ip_lock); + + if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb)) + goto discard_put; +--- a/net/l2tp/l2tp_ip6.c ++++ b/net/l2tp/l2tp_ip6.c +@@ -128,6 +128,7 @@ static int l2tp_ip6_recv(struct sk_buff + unsigned char *ptr, *optr; + struct l2tp_session *session; + struct l2tp_tunnel *tunnel = NULL; ++ struct ipv6hdr *iph; + int length; + + if (!pskb_may_pull(skb, 4)) +@@ -187,24 +188,17 @@ pass_up: + goto discard; + + tunnel_id = ntohl(*(__be32 *) &skb->data[4]); +- tunnel = l2tp_tunnel_find(net, tunnel_id); +- if (tunnel) { +- sk = tunnel->sock; +- sock_hold(sk); +- } else { +- struct ipv6hdr *iph = ipv6_hdr(skb); +- +- read_lock_bh(&l2tp_ip6_lock); +- sk = __l2tp_ip6_bind_lookup(net, &iph->daddr, &iph->saddr, +- inet6_iif(skb), tunnel_id); +- if (!sk) { +- read_unlock_bh(&l2tp_ip6_lock); +- goto discard; +- } ++ iph = ipv6_hdr(skb); + +- sock_hold(sk); ++ read_lock_bh(&l2tp_ip6_lock); ++ sk = __l2tp_ip6_bind_lookup(net, &iph->daddr, &iph->saddr, ++ inet6_iif(skb), tunnel_id); ++ if (!sk) { + read_unlock_bh(&l2tp_ip6_lock); ++ goto discard; + } ++ sock_hold(sk); ++ read_unlock_bh(&l2tp_ip6_lock); + + if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb)) + goto discard_put; diff --git a/queue-4.9/series b/queue-4.9/series index 3d18983d2c7..8a46aee6860 100644 --- a/queue-4.9/series +++ b/queue-4.9/series @@ -120,3 +120,4 @@ x86-insn-fix-awk-regexp-warnings.patch x86-speculation-fix-incorrect-mds-taa-mitigation-status.patch x86-speculation-fix-redundant-mds-mitigation-message.patch nfc-port100-handle-command-failure-cleanly.patch +l2tp-don-t-use-l2tp_tunnel_find-in-l2tp_ip-and-l2tp_ip6.patch