2

I'm trying to understand the permissions of a unix domain socket, when using an existing file, umask changes are required as well as the dir permissions.

If I create a world readable dir as root and open a socket with netcat:

root$: mkdir /tmp/mydir
root$: chmod 777 /tmp/mydir
root$: nc -l -U /tmp/mydir/sock

Then as a non root user try to connect to aforementioned socket it fails, though the dir is world readable as per:

https://man7.org/linux/man-pages/man7/unix.7.html

In the Linux implementation, pathname sockets honor the permissions of the directory they are in. Creation of a new socket fails if the process does not have write and search (execute) permission on the directory in which the socket is created.

root$: runuser -u user1 -- nc -U /tmp/mydir/sock 
nc: unix connect failed: Permission denied

Now by doing umask 0, and restarting the same socket again, it can be connected to from the non root user.

root$: umask 0
root$: nc -l -U /tmp/mydir/sock
root$: runuser -u user1 -- nc -U /tmp/mydir/sock 
ping 

Furthermore modifying the /tmp/mydir permissions to chmod 600 will stop the non root user from accessing the socket again.

root$: chmod 600 /tmp/mydir
root$: runuser -u user1 -- nc -U /tmp/mydir/sock 
nc: unix connect failed: Permission denied

It's clear the dir permissions work as intended according to the manual, but why is umask 0 required if the parent dir has the correct permissions ? Is netcat still creating some sort of other file ?

3
  • I'm wondering why you think an ordinary file would work. It's not a socket file. See stackoverflow.com/questions/6025755/… on how to create one. Commented Oct 16, 2021 at 12:01
  • Thanks @Bib / zevzek, I've edited with a comment the references to a regular file as a socket file. I was confused indeed. Still trying to understand why the directory permissions aren't enough.
    – nd6654ssd
    Commented Oct 16, 2021 at 12:34
  • You should never chmod 600 a directory unless your intent is to make it inaccessible to everyone. Directories need execute priv to be usable.
    – user10489
    Commented Oct 16, 2021 at 13:02

1 Answer 1

1

You missed this in that same unix(7) manpage you're quoting from:

On Linux, connecting to a stream socket object requires write permission on that socket; sending a datagram to a datagram socket likewise requires write permission on that socket.

Of course, you also need search(execute) permission to all the leading directories from its path, just like with any other file.

The part you're quoting refers to creating a socket, which only happens when bind(2)ing to it, which is what nc -l -U /path/to/sock does. Again, just like with creating any other file, the umask will affect the permissions of the created socket (umask == 022 => no write permission for other users => they cannot connect to the socket):

$ umask
0022
$ nc -Ul sock
^C
$ ls -l sock
srwxr-xr-x 1 xxx xxx 0 Oct 16 18:35 sock
^    ^  ^

Binding to a unix domain socket always has to create it from scratch. You cannot bind to an existing file, that will fail with EADDRINUSE. Consequently, most programs (including nc) will forcefully remove any file with the same name before binding to it:

$ echo text > file
$ strace nc -l -U file
...
socket(AF_UNIX, SOCK_STREAM, 0)         = 3
unlink("file")                          = 0
bind(3, {sa_family=AF_UNIX, sun_path="file"}, 110) = 0
listen(3, 5)                            = 0
accept4(3, 

NB: both snippets talk about the on-disk "socket" special file / inode, not about the inode representing the active socket object (which appears in /proc/<pid>/fd, /proc/net/unix, etc):

$ nc -lU sock &
[1] 4424
$ ls -li sock
20983212 srwxr-xr-x 1 xxx xxx 0 Oct 17 18:01 sock
^^^^^^^^
$ ls -li /proc/4424/fd
total 0
43825 lrwx------ 1 xxx xxx 64 Oct 17 18:02 0 -> /dev/pts/4
43826 lrwx------ 1 xxx xxx 64 Oct 17 18:02 1 -> /dev/pts/4
43827 lrwx------ 1 xxx xxx 64 Oct 17 18:02 2 -> /dev/pts/4
43828 lrwx------ 1 xxx xxx 64 Oct 17 18:02 3 -> socket:[46378]
                                                        ^^^^^
$ grep 46378 /proc/net/unix
00000000ee8c0faa: 00000002 00000000 00010000 0001 01 46378 sock
1
  • Thanks your answer helped a lot, after playing around I figured out two things: 1. If the file exists its deleted as you said and recreated as a socket file. (I missed the srwxr-xr-x file type appearing), so I couldn't workout why it wasn't being deleted like you said. But it was... 2. Now the the new socket file has been created, chmod'ing the file gives permission to the socket after the socket has been bound to by the listening command. umask was only helping because the new file (socket) will be created with public permissions. Adding this POV in your post may help others.
    – nd6654ssd
    Commented Oct 16, 2021 at 13:19

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .