Linux's abstract namespace for Unix domain sockets

August 19, 2015

The address of ordinary Unix domain sockets for servers is the file name of a socket file that actually appears in the filesystem. This is pleasantly Unix-y on the surface but winds up requiring you to do a bunch of bureaucracy to manage these socket files, and the socket files by themselves don't actually do anything that would make it useful for them to be in the filesystem; you can't interact with them and the server behind them with normal Unix file tools, for example.

Linux offers you a second choice. Rather than dealing with socket files in the filesystem, you can use names in an abstract (socket) namespace. Each name must be unique, but the namespace is otherwise flat and unstructured, and you can call your server socket whatever you want. Conveniently and unlike socket files, abstract names vanish when the socket is closed (either by you or because your program exited).

Apart from being Linux-only, the abstract socket namespace suffers from two limitations: you have to find a way to get a unique name and it has no permissions. With regular socket files you can use regular Unix file and directory permissions to insure that only you can talk to your server socket. With abstract socket names, anyone who knows or can find the name can connect to your server. If this matters you will have to do access control yourself.

(One approach is to use getsockopt() with SO_PEERCRED to get the UID and so on of the client connecting to you. SO_PEERCRED is Linux specific as far as I know, but then so is the abstract socket namespace.)

Lsof and other tools conventionally represent socket names in the abstract socket namespace by putting an @ in front of them. This is not actually how they're specified at the C API level, but it's a distinct marker and some higher level tools follow it for, eg, specifying socket names.

(The Go net package is one such piece of software.)

As far as picking unique names goes, one trick many programs seem to use is to use whatever filename they would be using if they didn't have the abstract socket namespace available. This gives you a convenient way of expressing, eg, per-user sockets; you can just give it a name based on the user's home directory. Other programs use a hierarchical namespace of their own; Ubuntu's upstart listens on the abstract socket name '/com/ubuntu/upstart', for example.

(For personal hacks, you can of course just make up your own little short names. Little hacks don't need a big process; that's the whole attraction of the abstract namespace.)

Now that I've poked around this, I'm going to use it for future little Linux-only hacks because checking permissions (if it's even necessary) is a lot more convenient than the whole hassle of dealing with socket files. For things I write that are intended to be portable, I don't see much point; portable code has to deal with socket files so I might as well use regular Unix domain socket names and socket files all the time.

(A bunch of my personal hacks are de facto Linux only because my desktop machines are Linux. I'll regret that laziness if I ever try to move my desktop environment to FreeBSD or the like, but that seems highly unlikely at the moment.)

Written on 19 August 2015.
« Getting dd's skip and seek straight once and for all
Using abstract namespace Unix domain sockets and SO_PEERCRED in Python »

Page tools: View Source, Add Comment.
Login: Password:
Atom Syndication: Recent Comments.

Last modified: Wed Aug 19 02:17:35 2015
This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.