Processes inside network namespaces can't use flipping and G-Sync

So, this issue is very specific but it’s important to me. I use VPN all the time as a default route but I need to run Steam through my router directly. For that purpose I set up a network namespace with veth that bridges to the physical eth interface and routes through the router. All works fine but I recently bought a G-Sync compatible monitor and suddenly the games can’t use G-Sync. Long story short, that network namespace setup somehow affects the driver ability to flip the buffers so it always blits. How to reproduce:

  1. Enable flipping, G-Sync, indicators (both G-Sync and GAPI)
  2. run glxgears or a game in fullscreen (for glxgears I use an Awesome WM hotkey to make window fullscreen), flip and G-sync work: https://i.imgur.com/4beagH0.jpg
  3. install newpid https://github.com/ChristophBerg/newpid (a helper program to run programs inside different namespaces)
  4. run
newpid -n glxgears
  1. now no matter what flipping and G-sync don’t work: https://i.imgur.com/Ap6wBqn.jpg

Maybe I’m missing something and the driver needs to communicate with localhost using sockets. Inside a network namespace there’s a different localhost so it’s not quite possible. But this is the first issue I’ve got with this setup in more than 7 years, otherwise Steam and all the games work flawlessly and are not aware of my VPN default route.

I actually use command

newpid -N newpidsteam steam

to run Steam and setup the namespace like this:

#!/bin/sh
ip link add type veth peer name veth1
ip link set dev veth1 up
brctl addif br0 veth1
ip net add newpidsteam
ip link set veth0 netns newpidsteam
ip net exec newpidsteam ip link set dev lo up
ip net exec newpidsteam ip link set dev veth0 up
ip net exec newpidsteam ip a a 172.25.10.50/24 b 172.25.10.255 dev veth0
ip net exec newpidsteam ip r a default via 172.25.10.36

Other options of newpid like -i (new IPC namespace) and -u (new UTS namespace) don’t affect flipping. Another related issue is that flipping also doesn’t work at all when Awesome WM is run without --no-argb option. With it flipping works.
nvidia-bug-report.log.gz (1.01 MB)

Sooooo I’ve solved this for me but in a hacky way. The root of the issue is the abstract unix domain socket that the driver uses, it’s not documented but apparently needed for flipping to work. I straced both cases, when flipping works and not and found a noticeable difference:

connect(8, {sa_family=AF_UNIX, sun_path=@"nvidia12792329

connect(8, {sa_family=AF_UNIX, sun_path=@“nvidia12792329\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0”}, 66) = 0


connect(8, {sa_family=AF_UNIX, sun_path=@“nvidia12792329\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0”}, 66) = 0


connect(8, {sa_family=AF_UNIX, sun_path=@“nvidia12792329\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0”}, 66) = 0


connect(8, {sa_family=AF_UNIX, sun_path=@“nvidia12792329\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0”}, 66) = 0


connect(8, {sa_family=AF_UNIX, sun_path=@“nvidia12792329\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0”}, 66) = 0


connect(8, {sa_family=AF_UNIX, sun_path=@“nvidia12792329\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0”}, 66) = 0


connect(8, {sa_family=AF_UNIX, sun_path=@“nvidia12792329\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0”}, 66) = 0


connect(8, {sa_family=AF_UNIX, sun_path=@“nvidia12792329\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0”}, 66) = 0


connect(8, {sa_family=AF_UNIX, sun_path=@“nvidia12792329\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0”}, 66) = 0


connect(8, {sa_family=AF_UNIX, sun_path=@“nvidia12792329\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0”}, 66) = 0


connect(8, {sa_family=AF_UNIX, sun_path=@“nvidia12792329\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0”}, 66) = 0


connect(8, {sa_family=AF_UNIX, sun_path=@“nvidia12792329\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0”}, 66) = 0


connect(8, {sa_family=AF_UNIX, sun_path=@“nvidia12792329\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0”}, 66) = 0


connect(8, {sa_family=AF_UNIX, sun_path=@“nvidia12792329\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0”}, 66) = 0


connect(8, {sa_family=AF_UNIX, sun_path=@“nvidia12792329\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0”}, 66) = 0


connect(8, {sa_family=AF_UNIX, sun_path=@“nvidia12792329\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0”}, 66) = 0


connect(8, {sa_family=AF_UNIX, sun_path=@“nvidia12792329\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0”}, 66) = 0


connect(8, {sa_family=AF_UNIX, sun_path=@“nvidia12792329\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0”}, 66) = 0


connect(8, {sa_family=AF_UNIX, sun_path=@“nvidia12792329\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0”}, 66) = 0


connect(8, {sa_family=AF_UNIX, sun_path=@“nvidia12792329\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0”}, 66) = 0


connect(8, {sa_family=AF_UNIX, sun_path=@“nvidia12792329\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0”}, 66) = 0


connect(8, {sa_family=AF_UNIX, sun_path=@“nvidia12792329\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0”}, 66) = 0


connect(8, {sa_family=AF_UNIX, sun_path=@“nvidia12792329\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0”}, 66) = 0


connect(8, {sa_family=AF_UNIX, sun_path=@“nvidia12792329\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0”}, 66) = 0


connect(8, {sa_family=AF_UNIX, sun_path=@“nvidia12792329\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0”}, 66) = 0


connect(8, {sa_family=AF_UNIX, sun_path=@“nvidia12792329\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0”}, 66) = 0


connect(8, {sa_family=AF_UNIX, sun_path=@“nvidia12792329\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0”}, 66) = 0


connect(8, {sa_family=AF_UNIX, sun_path=@“nvidia12792329\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0”}, 66) = 0


connect(8, {sa_family=AF_UNIX, sun_path=@“nvidia12792329\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0”}, 66) = 0


connect(8, {sa_family=AF_UNIX, sun_path=@“nvidia12792329\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0”}, 66) = 0


connect(8, {sa_family=AF_UNIX, sun_path=@“nvidia12792329\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0”}, 66) = 0


connect(8, {sa_family=AF_UNIX, sun_path=@“nvidia12792329\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0”}, 66) = 0


connect(8, {sa_family=AF_UNIX, sun_path=@“nvidia12792329\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0”}, 66) = 0


connect(8, {sa_family=AF_UNIX, sun_path=@“nvidia12792329\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0”}, 66) = 0


connect(8, {sa_family=AF_UNIX, sun_path=@“nvidia12792329\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0”}, 66) = 0


connect(8, {sa_family=AF_UNIX, sun_path=@“nvidia12792329\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0”}, 66) = 0


connect(8, {sa_family=AF_UNIX, sun_path=@“nvidia12792329\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0”}, 66) = 0


connect(8, {sa_family=AF_UNIX, sun_path=@“nvidia12792329\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0”}, 66) = 0


connect(8, {sa_family=AF_UNIX, sun_path=@“nvidia12792329\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0”}, 66) = 0


connect(8, {sa_family=AF_UNIX, sun_path=@“nvidia12792329\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0”}, 66) = 0


connect(8, {sa_family=AF_UNIX, sun_path=@“nvidia12792329\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0”}, 66) = 0


connect(8, {sa_family=AF_UNIX, sun_path=@“nvidia12792329\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0”}, 66) = 0


connect(8, {sa_family=AF_UNIX, sun_path=@“nvidia12792329\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0”}, 66) = 0


connect(8, {sa_family=AF_UNIX, sun_path=@“nvidia12792329\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0”}, 66) = 0


connect(8, {sa_family=AF_UNIX, sun_path=@“nvidia12792329\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0”}, 66) = 0


connect(8, {sa_family=AF_UNIX, sun_path=@“nvidia12792329\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0”}, 66) = 0


connect(8, {sa_family=AF_UNIX, sun_path=@“nvidia12792329\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0”}, 66) = 0


connect(8, {sa_family=AF_UNIX, sun_path=@“nvidia12792329\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0”}, 66) = 0


connect(8, {sa_family=AF_UNIX, sun_path=@“nvidia12792329\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0”}, 66) = 0

"}, 66) = 0

This call succeeds when the process is run in the main namespace. It results in ECONNREFUSED when run in another namespace. I tried to establish a link between the namespaces using socat (via a regular unix socket that’s visible from both default and other namespaces) but it didn’t work because the socket name has zeroes in it and it doesn’t play well with the shell arguments. Of course, I can write a makeshift program that proxies this traffic back and forth and finds the required socket name with netstat or so but I wanted to check if I’m on the right track first. So I patched the kernel and removed the namespace equality check:

diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index c754f3a90a2e..1d37636c8f5c 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -280,8 +280,8 @@ static struct sock *__unix_find_socket_byname(struct net *net,
 	sk_for_each(s, &unix_socket_table[hash ^ type]) {
 		struct unix_sock *u = unix_sk(s);
 
-		if (!net_eq(sock_net(s), net))
-			continue;
+//		if (!net_eq(sock_net(s), net))
+//			continue;
 
 		if (u->addr->len == len &&
 		    !memcmp(u->addr->name, sunname, len))

And yep, it worked. Now I can use G-Sync in the games launched in another network namespace. Like I said, it’s a really dirty hack that might have unforeseen consequences so I’d like to know if there’s a better way to access that socket. Or, even better, to specify it explicitly as a non-abstract socket that resides in the filesystem. For example, glxgears accesses another socket from a namespace just fine:

connect(3, {sa_family=AF_UNIX, sun_path="/tmp/.X11-unix/X0"}, 110) = 0

Tracked as NVIDIA bug 2462524.

That bug is now fixed in our trunk. It will take a while to appear in a public release, when it does there will be a changelog entry.
Thanks for reporting it!

Hello, I only now found out this is fixed. However, I still observe the same behavior on 430.50 and kernel 5.3.5. Could it be that the fix didn’t make it into the release? I checked with strace again and indeed that anonymous socket connection is refused when the target program (glxgears in my case) is run inside a namespace.

It doesn’t look like the fix is in these public releases, it will appear in the next branch. Watch for a changelog entry.

Confirming it’s fixed in 440.31. Many thanks, now I can use the vanilla kernel without my ugly hack!