Is a subdirectory of /tmp a suitable place for Unix sockets

permissionsSecuritytmpunix-sockets

I am looking for a secure place to put Unix domain sockets that will be used to control a REPL.

On Linux, I would use /run/user/$UID, which meets all requirements except for portability. I need the program that handles them to be portable.

One option is to use a directory under ~ but that runs into a different problem: the user's home directory might be in a directory too deep to be able to bind a Unix domain socket to, due to the limit in the path length.

Placing the socket in a directory under /tmp is portable, but I am worried about race conditions upon removing the directory. I am also worried about whether /tmp can be relied on to have the sticky bit set on all platforms (that is, for users to not be able to delete or rename other user's temporary files). I am assuming that /tmp IS sticky, however, as otherwise many, many applications (every script that uses mkstemp) is insecure.

My current plan is for the server to create a temporary directory in /tmp, and for the clients to check the ownership of the containing directory before using the socket. Is this adequate for security?

Best Answer

The de jure standard location for temporary files is given in the environment variable TMPDIR.

This variable shall represent a pathname of a directory made available for programs that need a place to create temporary files.

In fact, many systems do not define TMPDIR. The de facto standard location for temporary files is /tmp. So check TMPDIR, and if it is not set, use /tmp. In a shell script, you can use ${TMPDIR:-/tmp}, or if you find it more convenient,

if [ -z "$TMPDIR" ]; then TMPDIR=/tmp; fi

or to cope with set -u

: "${TMPDIR:=/tmp}"

You can assume that this location is writable, but it may be world-readable and world-writable, so:

  • When you create a regular file, always make sure that you aren't overwriting an existing file, which might not belong to you. Don't use a shell redirection for this. It is not safe to test ownership separately because an adversary may move symbolic links around while your program is running to fool the checks. Additionally you can't rely on a particular name not existing; to prevent a concurrent program from creating a denial of service by creating a file with the same name just before you, use a random name. You can use the mktemp utility (widespread, present on GNU, BusyBox, BSD, but not POSIX) or the mkstemp C library function. Under the hood, open or creat must be called with the O_EXCL flag.
  • You can create a directory with mkdir. This is secure against ownership trickery stealing, because that won't reuse an existing file, but it is prone to the same denial of service as regular files, so you should use a random name. mktemp -d is a fine way to do this.
  • You can create a socket (there's no standard shell utility for that). Like the directory case, it is secure against ownership trickery but not against denial of service.
    Linux honors permissions on named sockets, but there are Unix variants that don't. This is why sockets in /tmp are usually created in subdirectories.

Programs that create a subdirectory of /tmp (or $TMPDIR if set) and create a named socket there include X11 servers, ssh-agent, gpg-agent, KDE, emacs, … (that's just the ones that exist on the machine where I'm posting this). As you can see, you'll be in good company.