next up previous
Next: Exchanging data via a Up: Working with Temporary Files Previous: There be Dragons

Creating a One-shot File

This is the most common case, and all examples covered above revolved around this issue: create a file, operate on it, and throw it away when the program exits.

Fortunately, there is an easy solution that works in most cases. When you call the fopen function, you really invoke some code that sits in the C library and eventually ends up invoking the open system call. File modes given in fopen are translated to flag values passed as the second argument to open. For instance, "r" translates to O_RDONLY, and "w" translates to O_RDWR|O_CREAT|O_TRUNC which tells the kernel to open the file in read/write mode, truncate it if it exists already and create it if it not.

In addition to these, open supports a bunch of other flags. One of them is O_EXCL which tells the kernel kernel to fail if the file already exists. Since this check does not follow symlinks, it will also fail if a symbolic link of that name already exists. This flag can be used to create a file safely without having to be afraid of symlink or hard link attacks, because the check-and-create operation is atomic (i.e. there's no way an attacker can modify the directory inbetween the existence check and the creation of the file). Here's how:

    char    filename[MAXPATHLEN];
    FILE    *fp;
    int     fd;

    /* Generate unique file name */
    strcpy(filename, "/tmp/fooXXXXXX");
    if (!mktemp(filename))
        fatal("mktemp failed: %s", strerror(errno));
    /* Open file, fail if it exists: */
    if ((fd = open(filename, O_RDWR|O_CREAT|O_EXCL, 0644)) < 0)
        fatal("Cannot open %s: %s", filename, strerror(errno));
    /* Turn the file descriptor into an stdio FILE stream */
    fp = fdopen(fd, "w");

There are also variants of the mktemp function that use the above approach to create a temporary file securely, such as mkstemp introduced in BSD 4.3 and also available on Linux. mkstemp works much like mktemp, except it's safer (which is probably what the s in its name stands for). Just like mktemp, it creates a unique file name, but rather than returning the name and leaving it to the caller to create it some time later, it calls open with the O_EXCL flag to create it right away.

    char    filename[MAXPATHLEN];

    strcpy(filename, "/tmp/fooXXXXXX");
    fd = mkstemp(filename);
    if (fd < 0)
        fatal("unable to create temp file");

Note that after you've safely created your temporary file, you can re-open it many times if it resides in a directory like /tmp that has the sticky bit set. The sticky bit guarantees that even though the directory is writable by everyone, a file can only be removed by the user who created it. That means, once you've created the file, an attacker is unable to replace it with a symbolic link.

Recent Linux kernels also support a flag called O_NOFOLLOW. If specified in a call to open, the kernel will not follow symlinks. This stops all symlink attacks; it does not help against hard link attacks however.


next up previous
Next: Exchanging data via a Up: Working with Temporary Files Previous: There be Dragons
Olaf Kirch 2002-01-16