When using Unix Domain Sockets you need to pass
tcp_bind(Socket, UnixDomainSocketFileName) a
UnixDomainSocketFileName that is the name of a file that doesn’t exist yet. Turns out to be surprisingly complicated to do correctly (and securely).
Since using temp files improperly represents a security risk, I was hoping to use the
tmp_file_stream/3 predicate to do this. My problem is that this predicate actually creates the file. My thought was to delete it immediately and just use the name and let the socket recreate it:
tmp_file_stream(UnixDomainSocketFileName, Stream, [extension(sock)]), close(Stream), delete_file(UnixDomainSocketFileName), ... tcp_bind(Socket, UnixDomainSocketFileName)
I realize that this means the system won’t automatically clean it up anymore.
My concern is this phrase from the docs:
If the OS supports it, the created file is only accessible to the current user and the file is created using the open()-flag
O_EXCL, which guarantees that the file did not exist before this call.
It appears that my approach will remove those two protections:
- I’m OK losing the “guarantees that the file did not exist before this call” protection since the socket API fails if the file is already created. The system won’t be able to be tricked into using an existing file.
- The problem is that I don’t have a way to have the file “only accessible to the current user” since the socket creates it and I’m pretty sure it doesn’t set the permissions that way (and that the tmp directory isn’t set that way).
The best approach I’ve come up with is to avoid using the above predicate altogether and create a special directory with permissions set to “this user only” and generate temp file names using a GUID so they aren’t guessable (or conflicting).
Does anyone know of a better approach?