Skip to content

Commit f6cd651

Browse files
Guillaume Naultdavem330
authored andcommitted
l2tp: fix race in duplicate tunnel detection
We can't use l2tp_tunnel_find() to prevent l2tp_nl_cmd_tunnel_create() from creating a duplicate tunnel. A tunnel can be concurrently registered after l2tp_tunnel_find() returns. Therefore, searching for duplicates must be done at registration time. Finally, remove l2tp_tunnel_find() entirely as it isn't use anywhere anymore. Fixes: 309795f ("l2tp: Add netlink control API for L2TP") Signed-off-by: Guillaume Nault <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 6b9f342 commit f6cd651

File tree

3 files changed

+14
-28
lines changed

3 files changed

+14
-28
lines changed

net/l2tp/l2tp_core.c

Lines changed: 14 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -335,26 +335,6 @@ int l2tp_session_register(struct l2tp_session *session,
335335
}
336336
EXPORT_SYMBOL_GPL(l2tp_session_register);
337337

338-
/* Lookup a tunnel by id
339-
*/
340-
struct l2tp_tunnel *l2tp_tunnel_find(const struct net *net, u32 tunnel_id)
341-
{
342-
struct l2tp_tunnel *tunnel;
343-
struct l2tp_net *pn = l2tp_pernet(net);
344-
345-
rcu_read_lock_bh();
346-
list_for_each_entry_rcu(tunnel, &pn->l2tp_tunnel_list, list) {
347-
if (tunnel->tunnel_id == tunnel_id) {
348-
rcu_read_unlock_bh();
349-
return tunnel;
350-
}
351-
}
352-
rcu_read_unlock_bh();
353-
354-
return NULL;
355-
}
356-
EXPORT_SYMBOL_GPL(l2tp_tunnel_find);
357-
358338
struct l2tp_tunnel *l2tp_tunnel_find_nth(const struct net *net, int nth)
359339
{
360340
struct l2tp_net *pn = l2tp_pernet(net);
@@ -1501,6 +1481,7 @@ static int l2tp_validate_socket(const struct sock *sk, const struct net *net,
15011481
int l2tp_tunnel_register(struct l2tp_tunnel *tunnel, struct net *net,
15021482
struct l2tp_tunnel_cfg *cfg)
15031483
{
1484+
struct l2tp_tunnel *tunnel_walk;
15041485
struct l2tp_net *pn;
15051486
struct socket *sock;
15061487
struct sock *sk;
@@ -1529,7 +1510,16 @@ int l2tp_tunnel_register(struct l2tp_tunnel *tunnel, struct net *net,
15291510
tunnel->l2tp_net = net;
15301511

15311512
pn = l2tp_pernet(net);
1513+
15321514
spin_lock_bh(&pn->l2tp_tunnel_list_lock);
1515+
list_for_each_entry(tunnel_walk, &pn->l2tp_tunnel_list, list) {
1516+
if (tunnel_walk->tunnel_id == tunnel->tunnel_id) {
1517+
spin_unlock_bh(&pn->l2tp_tunnel_list_lock);
1518+
1519+
ret = -EEXIST;
1520+
goto err_sock;
1521+
}
1522+
}
15331523
list_add_rcu(&tunnel->list, &pn->l2tp_tunnel_list);
15341524
spin_unlock_bh(&pn->l2tp_tunnel_list_lock);
15351525

@@ -1558,7 +1548,10 @@ int l2tp_tunnel_register(struct l2tp_tunnel *tunnel, struct net *net,
15581548
return 0;
15591549

15601550
err_sock:
1561-
sockfd_put(sock);
1551+
if (tunnel->fd < 0)
1552+
sock_release(sock);
1553+
else
1554+
sockfd_put(sock);
15621555
err:
15631556
return ret;
15641557
}

net/l2tp/l2tp_core.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,6 @@ struct l2tp_session *l2tp_session_get(const struct net *net,
220220
struct l2tp_session *l2tp_session_get_nth(struct l2tp_tunnel *tunnel, int nth);
221221
struct l2tp_session *l2tp_session_get_by_ifname(const struct net *net,
222222
const char *ifname);
223-
struct l2tp_tunnel *l2tp_tunnel_find(const struct net *net, u32 tunnel_id);
224223
struct l2tp_tunnel *l2tp_tunnel_find_nth(const struct net *net, int nth);
225224

226225
int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id,

net/l2tp/l2tp_netlink.c

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -236,12 +236,6 @@ static int l2tp_nl_cmd_tunnel_create(struct sk_buff *skb, struct genl_info *info
236236
if (info->attrs[L2TP_ATTR_DEBUG])
237237
cfg.debug = nla_get_u32(info->attrs[L2TP_ATTR_DEBUG]);
238238

239-
tunnel = l2tp_tunnel_find(net, tunnel_id);
240-
if (tunnel != NULL) {
241-
ret = -EEXIST;
242-
goto out;
243-
}
244-
245239
ret = -EINVAL;
246240
switch (cfg.encap) {
247241
case L2TP_ENCAPTYPE_UDP:

0 commit comments

Comments
 (0)