|
|
6a8247 |
From b100598ffd55b71a99567555d7971d07e7b42ac3 Mon Sep 17 00:00:00 2001
|
|
|
6a8247 |
From: Guillaume Nault <g.nault@alphalink.fr>
|
|
|
6a8247 |
Date: Tue, 10 Apr 2018 21:01:13 +0200
|
|
|
6a8247 |
Subject: [PATCH 2/3] l2tp: fix race in duplicate tunnel detection
|
|
|
6a8247 |
Git-commit: f6cd651b056ffd3b4e8496afd44d4ed44bf69136
|
|
|
6a8247 |
Patch-mainline: v4.17-rc1
|
|
|
6a8247 |
References: bsc#1205711 CVE-2022-4129
|
|
|
6a8247 |
|
|
|
6a8247 |
We can't use l2tp_tunnel_find() to prevent l2tp_nl_cmd_tunnel_create()
|
|
|
6a8247 |
from creating a duplicate tunnel. A tunnel can be concurrently
|
|
|
6a8247 |
registered after l2tp_tunnel_find() returns. Therefore, searching for
|
|
|
6a8247 |
duplicates must be done at registration time.
|
|
|
6a8247 |
|
|
|
6a8247 |
Finally, remove l2tp_tunnel_find() entirely as it isn't use anywhere
|
|
|
6a8247 |
anymore.
|
|
|
6a8247 |
|
|
|
6a8247 |
Fixes: 309795f4bec2 ("l2tp: Add netlink control API for L2TP")
|
|
|
6a8247 |
Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
|
|
|
6a8247 |
Signed-off-by: David S. Miller <davem@davemloft.net>
|
|
|
6a8247 |
Signed-off-by: Denis Kirjanov <denis.kirjanov@suse.com>
|
|
|
6a8247 |
---
|
|
|
6a8247 |
net/l2tp/l2tp_core.c | 35 ++++++++++++++---------------------
|
|
|
6a8247 |
net/l2tp/l2tp_core.h | 1 -
|
|
|
6a8247 |
net/l2tp/l2tp_netlink.c | 6 ------
|
|
|
6a8247 |
3 files changed, 14 insertions(+), 28 deletions(-)
|
|
|
6a8247 |
|
|
|
6a8247 |
diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c
|
|
|
6a8247 |
index b71becd4d522..c28cf5c0e80a 100644
|
|
|
6a8247 |
--- a/net/l2tp/l2tp_core.c
|
|
|
6a8247 |
+++ b/net/l2tp/l2tp_core.c
|
|
|
6a8247 |
@@ -334,26 +334,6 @@ int l2tp_session_register(struct l2tp_session *session,
|
|
|
6a8247 |
}
|
|
|
6a8247 |
EXPORT_SYMBOL_GPL(l2tp_session_register);
|
|
|
6a8247 |
|
|
|
6a8247 |
-/* Lookup a tunnel by id
|
|
|
6a8247 |
- */
|
|
|
6a8247 |
-struct l2tp_tunnel *l2tp_tunnel_find(const struct net *net, u32 tunnel_id)
|
|
|
6a8247 |
-{
|
|
|
6a8247 |
- struct l2tp_tunnel *tunnel;
|
|
|
6a8247 |
- struct l2tp_net *pn = l2tp_pernet(net);
|
|
|
6a8247 |
-
|
|
|
6a8247 |
- rcu_read_lock_bh();
|
|
|
6a8247 |
- list_for_each_entry_rcu(tunnel, &pn->l2tp_tunnel_list, list) {
|
|
|
6a8247 |
- if (tunnel->tunnel_id == tunnel_id) {
|
|
|
6a8247 |
- rcu_read_unlock_bh();
|
|
|
6a8247 |
- return tunnel;
|
|
|
6a8247 |
- }
|
|
|
6a8247 |
- }
|
|
|
6a8247 |
- rcu_read_unlock_bh();
|
|
|
6a8247 |
-
|
|
|
6a8247 |
- return NULL;
|
|
|
6a8247 |
-}
|
|
|
6a8247 |
-EXPORT_SYMBOL_GPL(l2tp_tunnel_find);
|
|
|
6a8247 |
-
|
|
|
6a8247 |
struct l2tp_tunnel *l2tp_tunnel_find_nth(const struct net *net, int nth)
|
|
|
6a8247 |
{
|
|
|
6a8247 |
struct l2tp_net *pn = l2tp_pernet(net);
|
|
|
6a8247 |
@@ -1513,6 +1493,7 @@ static int l2tp_validate_socket(const struct sock *sk, const struct net *net,
|
|
|
6a8247 |
int l2tp_tunnel_register(struct l2tp_tunnel *tunnel, struct net *net,
|
|
|
6a8247 |
struct l2tp_tunnel_cfg *cfg)
|
|
|
6a8247 |
{
|
|
|
6a8247 |
+ struct l2tp_tunnel *tunnel_walk;
|
|
|
6a8247 |
struct l2tp_net *pn;
|
|
|
6a8247 |
struct socket *sock;
|
|
|
6a8247 |
struct sock *sk;
|
|
|
6a8247 |
@@ -1541,7 +1522,16 @@ int l2tp_tunnel_register(struct l2tp_tunnel *tunnel, struct net *net,
|
|
|
6a8247 |
tunnel->l2tp_net = net;
|
|
|
6a8247 |
|
|
|
6a8247 |
pn = l2tp_pernet(net);
|
|
|
6a8247 |
+
|
|
|
6a8247 |
spin_lock_bh(&pn->l2tp_tunnel_list_lock);
|
|
|
6a8247 |
+ list_for_each_entry(tunnel_walk, &pn->l2tp_tunnel_list, list) {
|
|
|
6a8247 |
+ if (tunnel_walk->tunnel_id == tunnel->tunnel_id) {
|
|
|
6a8247 |
+ spin_unlock_bh(&pn->l2tp_tunnel_list_lock);
|
|
|
6a8247 |
+
|
|
|
6a8247 |
+ ret = -EEXIST;
|
|
|
6a8247 |
+ goto err_sock;
|
|
|
6a8247 |
+ }
|
|
|
6a8247 |
+ }
|
|
|
6a8247 |
list_add_rcu(&tunnel->list, &pn->l2tp_tunnel_list);
|
|
|
6a8247 |
spin_unlock_bh(&pn->l2tp_tunnel_list_lock);
|
|
|
6a8247 |
|
|
|
6a8247 |
@@ -1570,7 +1560,10 @@ int l2tp_tunnel_register(struct l2tp_tunnel *tunnel, struct net *net,
|
|
|
6a8247 |
return 0;
|
|
|
6a8247 |
|
|
|
6a8247 |
err_sock:
|
|
|
6a8247 |
- sockfd_put(sock);
|
|
|
6a8247 |
+ if (tunnel->fd < 0)
|
|
|
6a8247 |
+ sock_release(sock);
|
|
|
6a8247 |
+ else
|
|
|
6a8247 |
+ sockfd_put(sock);
|
|
|
6a8247 |
err:
|
|
|
6a8247 |
return ret;
|
|
|
6a8247 |
}
|
|
|
6a8247 |
diff --git a/net/l2tp/l2tp_core.h b/net/l2tp/l2tp_core.h
|
|
|
6a8247 |
index 076f96f3772b..309ee6e70871 100644
|
|
|
6a8247 |
--- a/net/l2tp/l2tp_core.h
|
|
|
6a8247 |
+++ b/net/l2tp/l2tp_core.h
|
|
|
6a8247 |
@@ -251,7 +251,6 @@ struct l2tp_session *l2tp_session_get(const struct net *net,
|
|
|
6a8247 |
struct l2tp_session *l2tp_session_get_nth(struct l2tp_tunnel *tunnel, int nth);
|
|
|
6a8247 |
struct l2tp_session *l2tp_session_get_by_ifname(const struct net *net,
|
|
|
6a8247 |
const char *ifname);
|
|
|
6a8247 |
-struct l2tp_tunnel *l2tp_tunnel_find(const struct net *net, u32 tunnel_id);
|
|
|
6a8247 |
struct l2tp_tunnel *l2tp_tunnel_find_nth(const struct net *net, int nth);
|
|
|
6a8247 |
|
|
|
6a8247 |
int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id,
|
|
|
6a8247 |
diff --git a/net/l2tp/l2tp_netlink.c b/net/l2tp/l2tp_netlink.c
|
|
|
6a8247 |
index bd12e695fae8..ad9170044f67 100644
|
|
|
6a8247 |
--- a/net/l2tp/l2tp_netlink.c
|
|
|
6a8247 |
+++ b/net/l2tp/l2tp_netlink.c
|
|
|
6a8247 |
@@ -236,12 +236,6 @@ static int l2tp_nl_cmd_tunnel_create(struct sk_buff *skb, struct genl_info *info
|
|
|
6a8247 |
if (info->attrs[L2TP_ATTR_DEBUG])
|
|
|
6a8247 |
cfg.debug = nla_get_u32(info->attrs[L2TP_ATTR_DEBUG]);
|
|
|
6a8247 |
|
|
|
6a8247 |
- tunnel = l2tp_tunnel_find(net, tunnel_id);
|
|
|
6a8247 |
- if (tunnel != NULL) {
|
|
|
6a8247 |
- ret = -EEXIST;
|
|
|
6a8247 |
- goto out;
|
|
|
6a8247 |
- }
|
|
|
6a8247 |
-
|
|
|
6a8247 |
ret = -EINVAL;
|
|
|
6a8247 |
switch (cfg.encap) {
|
|
|
6a8247 |
case L2TP_ENCAPTYPE_UDP:
|
|
|
6a8247 |
--
|
|
|
6a8247 |
2.16.4
|
|
|
6a8247 |
|