From 8ac1ced115caea70719a29bb9fb2f6f04b324b76 Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Fri, 22 Jul 2016 14:27:43 +0200 Subject: socket: fix compat for 4.1 v6 sockets It turns out 4.1 is even more broken than expected. While both 4.1 and 4.2 need to jigger the sysctl nob temporarily, it turns out that in 4.1 it's looking in the wrong namespace for the nob value. So, we have to account for the different namespace semantics in the different versions. Super ugly. But, all this code goes away once we upstream. Signed-off-by: Jason A. Donenfeld --- src/socket.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/socket.c b/src/socket.c index 9dd1683..aa17c1b 100644 --- a/src/socket.c +++ b/src/socket.c @@ -423,6 +423,7 @@ int socket_init(struct wireguard_device *wg) int ret = 0; #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 3, 0) int old_bindv6only; + struct net *nobns; #endif mutex_lock(&wg->socket_update_lock); @@ -453,15 +454,20 @@ int socket_init(struct wireguard_device *wg) #if IS_ENABLED(CONFIG_IPV6) #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 3, 0) +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 2, 0) + nobns = &init_net; +#else + nobns = wg->creating_net; +#endif /* Since udp_port_cfg only learned of ipv6_v6only in 4.3, we do this horrible * hack here and set the sysctl variable temporarily to something that will * set the right option for us in sock_create. It's super racey! */ - old_bindv6only = wg->creating_net->ipv6.sysctl.bindv6only; - wg->creating_net->ipv6.sysctl.bindv6only = 1; + old_bindv6only = nobns->ipv6.sysctl.bindv6only; + nobns->ipv6.sysctl.bindv6only = 1; #endif ret = udp_sock_create(wg->creating_net, &port6, &new6); #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 3, 0) - wg->creating_net->ipv6.sysctl.bindv6only = old_bindv6only; + nobns->ipv6.sysctl.bindv6only = old_bindv6only; #endif if (ret < 0) { pr_err("Could not create IPv6 socket\n"); -- cgit v1.2.3