summaryrefslogtreecommitdiff
path: root/drivers/net/wireguard/socket.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2020-06-23 14:50:34 -0700
committerDavid S. Miller <davem@davemloft.net>2020-06-23 14:50:34 -0700
commitd3043c89e415d3754799c60e1b9fef5f2842dd82 (patch)
treeec7ca53c9862c0769edb011dbf8360e6973df215 /drivers/net/wireguard/socket.c
parentdf25f3828e5f181d11919947451df84229de487b (diff)
parentbe0d977e56c769b2610db430604ad7ff1ed31408 (diff)
downloadwireguard-linux-trimmed-d3043c89e415d3754799c60e1b9fef5f2842dd82.tar.gz
wireguard-linux-trimmed-d3043c89e415d3754799c60e1b9fef5f2842dd82.zip
Merge branch 'wg-fixes'
Jason A. Donenfeld says: ==================== wireguard fixes for 5.8-rc3 This series contains two fixes, one cosmetic and one quite important: 1) Avoid the `if ((x = f()) == y)` pattern, from Frank Werner-Krippendorf. 2) Mitigate a potential memory leak by creating circular netns references, while also making the netns semantics a bit more robust. Patch (2) has a "Fixes:" line and should be backported to stable. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/wireguard/socket.c')
-rw-r--r--drivers/net/wireguard/socket.c25
1 files changed, 18 insertions, 7 deletions
diff --git a/drivers/net/wireguard/socket.c b/drivers/net/wireguard/socket.c
index f901802..c33e2c8 100644
--- a/drivers/net/wireguard/socket.c
+++ b/drivers/net/wireguard/socket.c
@@ -347,6 +347,7 @@ static void set_sock_opts(struct socket *sock)
int wg_socket_init(struct wg_device *wg, u16 port)
{
+ struct net *net;
int ret;
struct udp_tunnel_sock_cfg cfg = {
.sk_user_data = wg,
@@ -371,37 +372,47 @@ int wg_socket_init(struct wg_device *wg, u16 port)
};
#endif
+ rcu_read_lock();
+ net = rcu_dereference(wg->creating_net);
+ net = net ? maybe_get_net(net) : NULL;
+ rcu_read_unlock();
+ if (unlikely(!net))
+ return -ENONET;
+
#if IS_ENABLED(CONFIG_IPV6)
retry:
#endif
- ret = udp_sock_create(wg->creating_net, &port4, &new4);
+ ret = udp_sock_create(net, &port4, &new4);
if (ret < 0) {
pr_err("%s: Could not create IPv4 socket\n", wg->dev->name);
- return ret;
+ goto out;
}
set_sock_opts(new4);
- setup_udp_tunnel_sock(wg->creating_net, new4, &cfg);
+ setup_udp_tunnel_sock(net, new4, &cfg);
#if IS_ENABLED(CONFIG_IPV6)
if (ipv6_mod_enabled()) {
port6.local_udp_port = inet_sk(new4->sk)->inet_sport;
- ret = udp_sock_create(wg->creating_net, &port6, &new6);
+ ret = udp_sock_create(net, &port6, &new6);
if (ret < 0) {
udp_tunnel_sock_release(new4);
if (ret == -EADDRINUSE && !port && retries++ < 100)
goto retry;
pr_err("%s: Could not create IPv6 socket\n",
wg->dev->name);
- return ret;
+ goto out;
}
set_sock_opts(new6);
- setup_udp_tunnel_sock(wg->creating_net, new6, &cfg);
+ setup_udp_tunnel_sock(net, new6, &cfg);
}
#endif
wg_socket_reinit(wg, new4->sk, new6 ? new6->sk : NULL);
- return 0;
+ ret = 0;
+out:
+ put_net(net);
+ return ret;
}
void wg_socket_reinit(struct wg_device *wg, struct sock *new4,