aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2021-12-06 18:31:49 +0100
committerJason A. Donenfeld <Jason@zx2c4.com>2021-12-06 18:34:54 +0100
commit8e40dd627085ca9cf1e7ab1725709f26ab0a5b73 (patch)
tree72f6f3ac1eece78417e05d527b2a5ac82b7b816b
parentcompat: siphash: use _unaligned version by default (diff)
downloadwireguard-linux-compat-8e40dd627085ca9cf1e7ab1725709f26ab0a5b73.tar.xz
wireguard-linux-compat-8e40dd627085ca9cf1e7ab1725709f26ab0a5b73.zip
compat: udp_tunnel: don't take reference to non-init namespace
The comment to sk_change_net is instructive: Kernel sockets, f.e. rtnl or icmp_socket, are a part of a namespace. They should not hold a reference to a namespace in order to allow to stop it. Sockets after sk_change_net should be released using sk_release_kernel We weren't following these rules before, and were instead using __sock_create, which means we kept a reference to the namespace, which in turn meant that interfaces were not cleaned up on namespace exit. Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
-rw-r--r--src/compat/udp_tunnel/udp_tunnel.c12
1 files changed, 7 insertions, 5 deletions
diff --git a/src/compat/udp_tunnel/udp_tunnel.c b/src/compat/udp_tunnel/udp_tunnel.c
index 9b8770a..d287b91 100644
--- a/src/compat/udp_tunnel/udp_tunnel.c
+++ b/src/compat/udp_tunnel/udp_tunnel.c
@@ -38,9 +38,10 @@ int udp_sock_create4(struct net *net, struct udp_port_cfg *cfg,
struct socket *sock = NULL;
struct sockaddr_in udp_addr;
- err = __sock_create(net, AF_INET, SOCK_DGRAM, 0, &sock, 1);
+ err = sock_create_kern(AF_INET, SOCK_DGRAM, 0, &sock);
if (err < 0)
goto error;
+ sk_change_net(sock->sk, net);
udp_addr.sin_family = AF_INET;
udp_addr.sin_addr = cfg->local_ip;
@@ -72,7 +73,7 @@ int udp_sock_create4(struct net *net, struct udp_port_cfg *cfg,
error:
if (sock) {
kernel_sock_shutdown(sock, SHUT_RDWR);
- sock_release(sock);
+ sk_release_kernel(sock->sk);
}
*sockp = NULL;
return err;
@@ -229,7 +230,7 @@ void udp_tunnel_sock_release(struct socket *sock)
{
rcu_assign_sk_user_data(sock->sk, NULL);
kernel_sock_shutdown(sock, SHUT_RDWR);
- sock_release(sock);
+ sk_release_kernel(sock->sk);
}
#if IS_ENABLED(CONFIG_IPV6)
@@ -254,9 +255,10 @@ int udp_sock_create6(struct net *net, struct udp_port_cfg *cfg,
int err;
struct socket *sock = NULL;
- err = __sock_create(net, AF_INET6, SOCK_DGRAM, 0, &sock, 1);
+ err = sock_create_kern(AF_INET6, SOCK_DGRAM, 0, &sock);
if (err < 0)
goto error;
+ sk_change_net(sock->sk, net);
if (cfg->ipv6_v6only) {
int val = 1;
@@ -301,7 +303,7 @@ int udp_sock_create6(struct net *net, struct udp_port_cfg *cfg,
error:
if (sock) {
kernel_sock_shutdown(sock, SHUT_RDWR);
- sock_release(sock);
+ sk_release_kernel(sock->sk);
}
*sockp = NULL;
return err;