summaryrefslogtreecommitdiffstats
path: root/net/l2tp/l2tp_eth.c
diff options
context:
space:
mode:
authorGuillaume Nault <g.nault@alphalink.fr>2017-03-31 13:02:27 +0200
committerDavid S. Miller <davem@davemloft.net>2017-04-01 20:16:41 -0700
commitdbdbc73b44782e22b3b4b6e8b51e7a3d245f3086 (patch)
tree2b4af9a50ad82ed9805c03cde4012d3859647633 /net/l2tp/l2tp_eth.c
parent57377d63547861919ee634b845c7caa38de4a452 (diff)
downloadlinux-dbdbc73b44782e22b3b4b6e8b51e7a3d245f3086.tar.gz
linux-dbdbc73b44782e22b3b4b6e8b51e7a3d245f3086.tar.bz2
linux-dbdbc73b44782e22b3b4b6e8b51e7a3d245f3086.zip
l2tp: fix duplicate session creation
l2tp_session_create() relies on its caller for checking for duplicate sessions. This is racy since a session can be concurrently inserted after the caller's verification. Fix this by letting l2tp_session_create() verify sessions uniqueness upon insertion. Callers need to be adapted to check for l2tp_session_create()'s return code instead of calling l2tp_session_find(). pppol2tp_connect() is a bit special because it has to work on existing sessions (if they're not connected) or to create a new session if none is found. When acting on a preexisting session, a reference must be held or it could go away on us. So we have to use l2tp_session_get() instead of l2tp_session_find() and drop the reference before exiting. Fixes: d9e31d17ceba ("l2tp: Add L2TP ethernet pseudowire support") Fixes: fd558d186df2 ("l2tp: Split pppol2tp patch into separate l2tp and ppp parts") 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.c10
1 files changed, 2 insertions, 8 deletions
diff --git a/net/l2tp/l2tp_eth.c b/net/l2tp/l2tp_eth.c
index 8bf18a5f66e0..6fd41d7afe1e 100644
--- a/net/l2tp/l2tp_eth.c
+++ b/net/l2tp/l2tp_eth.c
@@ -221,12 +221,6 @@ static int l2tp_eth_create(struct net *net, u32 tunnel_id, u32 session_id, u32 p
goto out;
}
- session = l2tp_session_find(net, tunnel, session_id);
- if (session) {
- rc = -EEXIST;
- goto out;
- }
-
if (cfg->ifname) {
dev = dev_get_by_name(net, cfg->ifname);
if (dev) {
@@ -240,8 +234,8 @@ static int l2tp_eth_create(struct net *net, u32 tunnel_id, u32 session_id, u32 p
session = l2tp_session_create(sizeof(*spriv), tunnel, session_id,
peer_session_id, cfg);
- if (!session) {
- rc = -ENOMEM;
+ if (IS_ERR(session)) {
+ rc = PTR_ERR(session);
goto out;
}