Missing l2tp patch in v4.9.y series
Subsystems (2)
cover Missing l2tp patch in v4.9.y series
Hi,
the following l2tp patch originates from v4.14 and has been backported to 3.16.y and 4.13.y but it is missing in the 4.9.y branch (accidentally?). As it applies cleanly to 4.9.y and as I couldn't find any mails discouraging the inclusion into 4.9, I am now asking for inclusion into 4.9.y.
Kind regards,
Nicolas
Guillaume Nault (1):
l2tp: don't use l2tp_tunnel_find() in l2tp_ip and l2tp_ip6
net/l2tp/l2tp_ip.c | 24 +++++++++--------------- net/l2tp/l2tp_ip6.c | 24 +++++++++--------------- 2 files changed, 18 insertions(+), 30 deletions(-)
Signature · 1 line
2.24.0
PATCH 1/1 l2tp: don't use l2tp_tunnel_find() in l2tp_ip and l2tp_ip6
From: Guillaume Nault <[email protected]>
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.
---
Please consider queuing this patch for v4.9.y.
net/l2tp/l2tp_ip.c | 24 +++++++++--------------- net/l2tp/l2tp_ip6.c | 24 +++++++++--------------- 2 files changed, 18 insertions(+), 30 deletions(-)
net/l2tp/l2tp_ip.c +9 -15
@@ -116,6 +116,7 @@ static int l2tp_ip_recv(struct sk_buff *skb)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 @@ static int l2tp_ip_recv(struct sk_buff *skb) 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;
net/l2tp/l2tp_ip6.c +9 -15
@@ -128,6 +128,7 @@ static int l2tp_ip6_recv(struct sk_buff *skb)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 @@ static int l2tp_ip6_recv(struct sk_buff *skb) 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;
Signature · 1 line
2.24.0
Re: [PATCH 1/1] l2tp: don't use l2tp_tunnel_find() in l2tp_ip and l2tp_ip6
Quoted 27 lines · Nicolas Schier
From: Guillaume Nault <[email protected]>
commit
8f7dc9ae4a7aece9fbc3e6637bdfa38b36bcdf09upstream.Using
l2tp_tunnel_find()inl2tp_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. Callingsk_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 replacel2tp_tunnel_find()in the general case.Fix
l2tp_ip6in the same way.
Quoted 7 lines
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 <[email protected]>Signed-off-by David S. Miller <[email protected]>Signed-off-by Nicolas Schier <[email protected]>---
Please consider queuing this patch for v4.9.y.
Now queued up, thanks.
greg k-h