Skip to contentSkip to conversation

l2tp: l2tp_ppp must ignore non-PPP sessions

PATCH In review Guillaume Nault 2 participants 4 messages Jun 15, 2018

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

cover l2tp: l2tp_ppp must ignore non-PPP sessions

The original L2TP code was written for version 2 of the protocol, which could only carry PPP sessions. Then L2TPv3 generalised the protocol so that it could transport different kinds of pseudo-wires. But parts of the l2tp_ppp module still break in presence of non-PPP sessions.

Assuming L2TPv2 tunnels can only transport PPP sessions is right, but l2tp_netlink failed to ensure that (fixed in patch 1). When retrieving a session from an arbitrary tunnel, l2tp_ppp needs to filter out non-PPP sessions (last occurrence fixed in patch 2).

Guillaume Nault (2):
l2tp: reject creation of non-PPP sessions on L2TPv2 tunnels
l2tp: filter out non-PPP sessions in pppol2tp_tunnel_ioctl()

 net/l2tp/l2tp_netlink.c | 6 ++++++
 net/l2tp/l2tp_ppp.c     | 2 +-
 2 files changed, 7 insertions(+), 1 deletion(-)
Signature · 1 line
2.17.1
#1 lore raw

PATCH 1/2 l2tp: reject creation of non-PPP sessions on L2TPv2 tunnels

The /proc/net/pppol2tp handlers (pppol2tp_seq_*()) iterate over all L2TPv2 tunnels, and rightfully expect that only PPP sessions can be found there. However, l2tp_netlink accepts creating Ethernet sessions regardless of the underlying tunnel version.

This confuses pppol2tp_seq_session_show(), which expects that l2tp_session_priv() returns a pppol2tp_session structure. When the session is an Ethernet pseudo-wire, a struct l2tp_eth_sess is returned instead. This leads to invalid memory access when pppol2tp_session_get_sock() later tries to dereference ps->sk.

Fixes d9e31d17ceba ("l2tp: Add L2TP ethernet pseudowire support")
---
 net/l2tp/l2tp_netlink.c | 6 ++++++
 1 file changed, 6 insertions(+)
net/l2tp/l2tp_netlink.c +6 -0
index 6616c9fd292f..5b9900889e31 100644
@@ -553,6 +553,12 @@ static int l2tp_nl_cmd_session_create(struct sk_buff *skb, struct genl_info *inf
 		goto out_tunnel;
 	}
 
+	/* L2TPv2 only accepts PPP pseudo-wires */
+	if (tunnel->version == 2 && cfg.pw_type != L2TP_PWTYPE_PPP) {
+		ret = -EPROTONOSUPPORT;
+		goto out_tunnel;
+	}
+
 	if (tunnel->version > 2) {
 		if (info->attrs[L2TP_ATTR_DATA_SEQ])
 			cfg.data_seq = nla_get_u8(info->attrs[L2TP_ATTR_DATA_SEQ]);
Signature · 1 line
2.17.1
#2 lore raw

PATCH 2/2 l2tp: filter out non-PPP sessions in pppol2tp_tunnel_ioctl()

In reply to Guillaume Nault

pppol2tp_tunnel_ioctl() can act on an L2TPv3 tunnel, in which case 'session' may be an Ethernet pseudo-wire.

However, pppol2tp_session_ioctl() expects a PPP pseudo-wire, as it assumes l2tp_session_priv() points to a pppol2tp_session structure. For an Ethernet pseudo-wire l2tp_session_priv() points to an l2tp_eth_sess structure instead, making pppol2tp_session_ioctl() access invalid memory.

Fixes d9e31d17ceba ("l2tp: Add L2TP ethernet pseudowire support")
---
 net/l2tp/l2tp_ppp.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
net/l2tp/l2tp_ppp.c +1 -1
index f429fed06a1e..55188382845c 100644
@@ -1201,7 +1201,7 @@ static int pppol2tp_tunnel_ioctl(struct l2tp_tunnel *tunnel,
 				l2tp_session_get(sock_net(sk), tunnel,
 						 stats.session_id);
 
-			if (session) {
+			if (session && session->pwtype == L2TP_PWTYPE_PPP) {
 				err = pppol2tp_session_ioctl(session, cmd,
 							     arg);
 				l2tp_session_dec_refcount(session);
Signature · 1 line
2.17.1
maintainer
#3 lore raw
In reply to Guillaume Nault

From: Guillaume Nault <[email protected]>
Date: Fri, 15 Jun 2018 15:39:15 +0200

Quoted 9 lines

The original L2TP code was written for version 2 of the protocol, which could only carry PPP sessions. Then L2TPv3 generalised the protocol so that it could transport different kinds of pseudo-wires. But parts of the l2tp_ppp module still break in presence of non-PPP sessions.

Assuming L2TPv2 tunnels can only transport PPP sessions is right, but l2tp_netlink failed to ensure that (fixed in patch 1). When retrieving a session from an arbitrary tunnel, l2tp_ppp needs to filter out non-PPP sessions (last occurrence fixed in patch 2).

Series applied, thank you.