Windows/WSL Interop with AF_UNIX
Starting in Windows Insider build 17093, a WSL application can communicate with a Windows application over Unix sockets. Back in December, we blogged about bringing AF_UNIX to Windows. Now, we’re building on that functionality. Consider a requirement where you want to run some kind of service as a Windows application. Additionally, you would like to make this service available to both Windows and WSL applications. Now, that’s possible with Unix sockets.
How To Code
Let’s look at how the code for such applications would be written.
Windows Unix socket server code (link to the GitHub repo with the sample code):
WSL Unix socket client code(link to the GitHub repo with the sample code):
The above code is self-explanatory. But, one thing worth noting is the path of the socket. For Windows application, the path is in Win32 format and for WSL applications, the format is as in Linux file system.
Requirements & Limitations:
- A WSL Unix socket can only communicate with a Win32 Unix socket OR with a WSL Unix socket, but not both. For instance, a WSL Unix socket server can only accept connections from either WSL Unix socket(s) OR Win32 Unix socket(s). So, how is it determined which one is it? It’s based on the path the socket is bound to or connecting to, as specified in the `bind` or `connect` syscall. If the Unix socket path is a DrvFS path (i.e your system volumes mounted within WSL, ex: /mnt/c, /mnt/d etc.) then it can only communicate to a Windows Unix socket. If the path is a LxFS path (i.e Linux mounted volume within WSL, ex: /home, /var, /usr etc.) then it can only communicate with WSL Unix sockets.
- For a WSL Unix socket to establish connection with Windows Unix sockets, the first operation after the socket is created should be either a bind or connect. Any other operation on the socket will render it an exclusive WSL Unix socket that can only communicate with other WSL Unix sockets.
- As Windows Unix socket implementation does not currently support passing ancillary data such as `SCM_RIGHTS` etc., the ancillary data will also not be supported for Win32<->WSL interop over Unix sockets.
It is important to note that we enforce both Unix and Windows permissions for Unix interop between WSL/Windows–this is illustrated in the samples below.
NOTE: Turn on DrvFS metadata for these examples.
Binding Sample 1: No Windows Permissions
In this sample, we’ll bind a WSL Unix socket process to a path which it does not have access to. The binding will fail because I don’t have write permissions in Windows.
But grant write access to the path in Windows and it will bind successfully…
Binding Sample 2: Linux Permissions, No Windows Permissions
In this sample, a WSL Unix socket process connects to a Windows Unix socket path which it has access to from WSL, but not from Windows (I removed write permissions from user on this folder in Windows)
But if I run an elevated ubuntu (so that we do have write access on the file), I can connect as expected.
Binding Sample 3: No Linux Permissions, Windows Permissions
In this sample, a WSL Unix socket process connects to a Windows Unix socket path which it has access to from Windows, but not from WSL. You’ll see that I revoke access in WSL, which causes my client to fail to connect. Then, I’ll grant write access in WSL and the client will succeed.
Cheers, from Sunil Muthuswamy and Craig (@CraigWilhite)