8

I work on the application that uses Unix domain socket for IPC. The common way as I know is to place the socket file inside /var/run. I work with Ubuntu 18.04 and I see that var/run is a symlink for /run. Unfortunately the folder is accessible for root only:

  ls -Al /
  drwxr-xr-x  27 root root        800 Apr 12 17:39 run

So only root has write access for this folder and that makes it impossible to use Unix domain sockets for regular users.

First of all I can't understand why? And how to use Unix domain sockets for non-root users? I can use the home folder of course, but I prefer to use some correct and common method.

2
  • "The common way to do X is Y" and "Y doesn't work in my case" do not together imply "X is impossible in my case". Commented Apr 12, 2020 at 20:48
  • If your application runs as a systemd unit, e.g. /usr/local/lib/systemd/system/your-app.service, then this answer that explains RuntimeDirectory= is probably all you need.
    – Walf
    Commented Jul 16 at 5:01

2 Answers 2

6

There's nothing wrong with creating the socket in a dotfile or dotdir in the home directory of the user, if the user is not some kind of special, system user. The only problem would be with the home directory shared between multiple machines over nfs, but that could be easily worked around by including the hostname in the name of the socket.


On Linux/Ubuntu you could also use "abstract" Unix domain sockets, which don't use any path or inode in the filesystem. Abstract unix sockets are those whose address/path starts with a NUL byte:

abstract: an abstract socket address is distinguished (from a pathname socket) by the fact that sun_path[0] is a null byte (\0).

The socket's address in this namespace is given by the additional bytes in sun_path that are covered by the specified length of the address structure. (Null bytes in the name have no special significance.) The name has no connection with filesystem pathnames. When the address of an abstract socket is returned, the returned addrlen is greater than sizeof(sa_family_t) (i.e., greater than 2), and the name of the socket is contained in the first (addrlen - sizeof(sa_family_t)) bytes of sun_path.

When displayed for or entered by the user, the NUL bytes in a abstract Unix socket address are usually replaced with @s. Many programs get that horribly wrong, as they don't escape regular @s in any way and/or assume that only the first byte could be NUL.

Unlike regular Unix socket paths, abstract Unix socket names have different semantics, as anybody can bind to them (if the name is not already taken), and anybody can connect to them.

Instead of relying on file/directory permission to restrict who can connect to your socket, and assuming that eg. only root could create sockets inside some directory, you should check the peer's credential with getsockopt(SO_PEERCRED) (to get the uid/pid of who connected or bound the peer), or the SCM_CREDENTIALS ancillary message (the get the uid/pid of who sent a message over the socket).

This (replacing the usual file permission checks) is also the only sane use of SO_PEERCRED/SCM_CREDENTIALS IMHO.

2
  • perfect answer @mosvy and perfect idea. I read something about abstract sockets but I didn't think much of it. I guess it was I need. Thanks.
    – folibis
    Commented Apr 12, 2020 at 20:16
  • If anyone reading this has the rep for a 1-character edit, the http URL for the manpage linked to can now be updated to https.
    – AJM
    Commented Jun 3 at 14:54
3

Your unix domain socket should not go directly into /run, you have to create a folder inside /run, for example /run/my-ipc with the appropiate rights for your user and then write to that folder.

The folder has to be recreated at boot. The accepted answer for this question explains a couple of alternatives.

You must log in to answer this question.

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