diff options
author | Jason A. Donenfeld <Jason@zx2c4.com> | 2021-12-06 18:31:49 +0100 |
---|---|---|
committer | Jason A. Donenfeld <Jason@zx2c4.com> | 2021-12-06 18:34:54 +0100 |
commit | 8e40dd627085ca9cf1e7ab1725709f26ab0a5b73 (patch) | |
tree | 72f6f3ac1eece78417e05d527b2a5ac82b7b816b | |
parent | compat: siphash: use _unaligned version by default (diff) | |
download | wireguard-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.c | 12 |
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; |