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.