About temporary files

Temporary files leak


Programs create temporary files all the time. Because they need to allow user to edit something, because they are invoking another program that can't read input data from stdin, because data doesn't fit into memory, because they need read-write access to data (think djb's constant database). And sometimes programs do not remove temporary files they created. Check your /tmp

Any Unix programmer worth his salt knows following shell idiom for creating temporary file in quite safe manner:

cleanup() { rm -f "${tempfile}"; }
tempfile=$(mktemp)
# line 1
trap cleanup 0
# line 2

Still, there is chance that this script would leave temporary file behind,
either if it gets interrupted by user (^C) at line 1, or if it is killed forcefully (SIGKILL, SIGQUIT) while executing line 2.

Unlike memory leaks, which are cleaned up by kernel when process dies, temporary files are not tied to process created it, and will not be removed automatically by kernel.

What can be done?


We can do better and make kernel handle temporary files too, at least on Linux and NetBSD. Comments regarding other Unix systems are welcome.
../personal/contacts.gmi

Trick is that file referred by file descriptor N is accessible at /proc/self/fd/N, even if that file is no longer linked anywhere at file system.

On Linux it one can get descriptor of temporary file never linked at file
system using O_TMPFILE flag to open(2); on NetBSD one can open temporary file
with mkstemp(3) and unlink(2) it immediately, which still leaves window when unfortunate signal may leave temporary file orphaned, but that window is quite short.

Once file descriptor to unlinked file is acquired, process starts working with "/proc/self/fd/{N}" as it would with usual regular file somewhere under /tmp, except it will be cleaned up after process dies (more accurately, when there are no more references to it) and other process can't inadvertently access temporary file (processes peek at /proc for a reason). I wrote simple C program (Linux-only) that executes subprocess with path to such temporary file exported as environment variable:
https://git.sr.ht/~kaction/config/tree/569cada1bc5709b76d4fd05eb2696044ad68c338/universe/tempfile/tempfile.c

As already mentioned, on OpenBSD line 23 should be replaced with calls to mkstemp(3) and unlink(2).

Temporary directories?


This trick does not work with directories. If you open directory at file
descriptor N and remove that directory afterward, /proc/self/fd/N would still
exist, but you can do nothing useful with it.

On Linux, it is possible to create private, self-removing temporary directory
using namespaces(7), like following:

$ cat with-private-tmp.sh
#!/bin/sh
mount none -t tmpfs /tmp
exec "$@"
$ unshare --map-root-user --mount ./with-private-tmp touch /tmp/junk.txt

While I strongly advocate for the technique described in previous section,
namespaces in Linux were source of multiple security vulnerabilities, and are quite controversial, so I just mention possibility, not judging how wise it to use it.