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?

  • By-the-way note: On Linux, you could also use a path whose first byte is a null byte. This is a special Linux kernel convention for AF_UNIX socket addresses which are in a space that has no file system mapping. – Kaz Sep 28 '16 at 21:15
  • 2
    Speaking of permissions, not all Unix-like OS's honor the file system permissions on sockets. (LInux does.) You can't portably rely on the fact that "if the client connected to this socket, it is authenticated and authorized because of the perms on the socket itself". – Kaz Sep 28 '16 at 21:17
  • @Kaz my idea is to put the socket in a secure directory, and use the permissions on the directory. – Demi Sep 28 '16 at 22:59
  • @thrig in what way? – Demi Sep 28 '16 at 22:59
  • From Perl module smoke test reports, folks do (if rarely) screw up their /tmp directory permissions. Details vary, though I've seen 0700 mode permissions or other wacky changes from the default. So you'll need lots of error checking (and to yell at the user or otherwise log the problem) and shouldn't assume anything about /tmp working. – thrig Sep 28 '16 at 23:19

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.

  • If ssh-agent and gpg-agent (both of which can be assumed to be by people who know what they are doing regarding security), then I am not too worried. I guess I can assume that some other user can't do mv /tmp/my_directory /tmp/some_other_directory? – Demi Sep 29 '16 at 2:30
  • @Demi Another user can't remove or rename your files, due to the sticky bit on the directory. – Gilles Sep 29 '16 at 7:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.