summaryrefslogtreecommitdiffstats
path: root/net/l2tp/l2tp_eth.c
diff options
context:
space:
mode:
authorGuillaume Nault2017-10-27 16:51:50 +0200
committerDavid S. Miller2017-10-29 03:16:21 +0100
commit3953ae7b218df4d1e544b98a393666f9ae58a78c (patch)
tree6c1d24f363fe0828c5d43e77f4007282aa3f74ae /net/l2tp/l2tp_eth.c
parenttcp: Remove "linux/unaligned/access_ok.h" include. (diff)
downloadkernel-qcow2-linux-3953ae7b218df4d1e544b98a393666f9ae58a78c.tar.gz
kernel-qcow2-linux-3953ae7b218df4d1e544b98a393666f9ae58a78c.tar.xz
kernel-qcow2-linux-3953ae7b218df4d1e544b98a393666f9ae58a78c.zip
l2tp: don't register sessions in l2tp_session_create()
Sessions created by l2tp_session_create() aren't fully initialised: some pseudo-wire specific operations need to be done before making the session usable. Therefore the PPP and Ethernet pseudo-wires continue working on the returned l2tp session while it's already been exposed to the rest of the system. This can lead to various issues. In particular, the session may enter the deletion process before having been fully initialised, which will confuse the session removal code. This patch moves session registration out of l2tp_session_create(), so that callers can control when the session is exposed to the rest of the system. This is done by the new l2tp_session_register() function. Only pppol2tp_session_create() can be easily converted to avoid modifying its session after registration (the debug message is dropped in order to avoid the need for holding a reference on the session). For pppol2tp_connect() and l2tp_eth_create()), more work is needed. That'll be done in followup patches. For now, let's just register the session right after its creation, like it was done before. The only difference is that we can easily take a reference on the session before registering it, so, at least, we're sure it's not going to be freed while we're working on it. Signed-off-by: Guillaume Nault <g.nault@alphalink.fr> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/l2tp/l2tp_eth.c')
-rw-r--r--net/l2tp/l2tp_eth.c9
1 files changed, 9 insertions, 0 deletions
diff --git a/net/l2tp/l2tp_eth.c b/net/l2tp/l2tp_eth.c
index 014a7bc2a872..a7d76f5f31ff 100644
--- a/net/l2tp/l2tp_eth.c
+++ b/net/l2tp/l2tp_eth.c
@@ -271,6 +271,13 @@ static int l2tp_eth_create(struct net *net, struct l2tp_tunnel *tunnel,
goto out;
}
+ l2tp_session_inc_refcount(session);
+ rc = l2tp_session_register(session, tunnel);
+ if (rc < 0) {
+ kfree(session);
+ goto out;
+ }
+
dev = alloc_netdev(sizeof(*priv), name, name_assign_type,
l2tp_eth_dev_setup);
if (!dev) {
@@ -304,6 +311,7 @@ static int l2tp_eth_create(struct net *net, struct l2tp_tunnel *tunnel,
__module_get(THIS_MODULE);
/* Must be done after register_netdev() */
strlcpy(session->ifname, dev->name, IFNAMSIZ);
+ l2tp_session_dec_refcount(session);
dev_hold(dev);
@@ -314,6 +322,7 @@ out_del_dev:
spriv->dev = NULL;
out_del_session:
l2tp_session_delete(session);
+ l2tp_session_dec_refcount(session);
out:
return rc;
}