Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Code Block
bgColor#FFCCCC
char file_name[] = /* hard coded string */;

FILE *fp;

if (!(fp = fopen(file_name, "wb+")));
if (fp == NULL) {
  /* Handle Error */
}

Because the name is hard coded and consequently neither unique nor unpredictable, an attacker need only place a symbolic link in lieu of the file and the target file referenced by the link is opened and truncated.

...

Code Block
bgColor#FFCCCC
char file_name[L_tmpnam];
FILE* fp;

if (!tmpnam(file_name)) {
  /* Handle Error */
}

/* A TOCTOU race condition exists here */

if (!(fp = fopen(file_name, "wb+"));
if (fp == NULL) {
   /* Handle Error */
}

Because tmpnam() does not guarantee a unique name and fopen() does not provide a facility for an exclusive open, this code is still vulnerable.

...

Code Block
bgColor#FFCCCC
char file_name[L_tmpnam];
int fd;

if (!(tmpnam(file_name))) {
  /* Handle Error */
}

/* A TOCTOU race condition exists here */

if ((fd = open(file_name, O_WRONLY | O_CREAT | O_EXCL | O_TRUNC, 0600));
if (fd < 0) {
   /* Handle Error */
}

...

Code Block
bgColor#FFCCCC
char file_name[L_tmpnam_s];
int fd;

if (tmpnam_s(file_name, L_tmpnam_s) != 0) {
  /* Handle Error */
}

/* A TOCTOU race condition exists here */

if ((fd = open(file_name, O_WRONLY | O_CREAT | O_EXCL | O_TRUNC, 0600));
if (fd < 0) {
   /* Handle Error */
}

Non-normative text in TR 24731-1 also recommends the following:

...

Code Block
bgColor#FFCCCC
char file_name[] = "tmp-XXXXXX";
int fd;

if (!mktemp(file_name)) {
  /* Handle Error */
}

/* A TOCTOU race condition exists here */

if ((fd = open(file_name, O_WRONLY | O_CREAT | O_EXCL | O_TRUNC, 0600));
if (fd < 0) {
  /* Handle Error */
}

The mktemp() function has been marked "LEGACY" in the Open Group Base Specifications Issue 6. The man page for mktemp() gives more detail:

...

Wiki Markup
It should be possible to open at least {{TMP_MAX}} temporary files during the lifetime of the program (this limit may be shared with {{tmpfile()}}). C99 Section 7.19.4.4 allows for the value of the macro {{TMP_MAX}} to be atas littlesmall as 25 \[[ISO/IEC 9899:1999|AA. C References#ISO/IEC 9899-1999]\].

...

Code Block
bgColor#FFCCCC
FILE* fp = tmpfile();

if (!(fp == tmpfile()NULL)) {
  /* Handle Error */
}

Compliant Solution: mkstemp() (POSIX)

...

Code Block
char template[] = "temp-XXXXXX";
if ((
fd = mkstemp(template));
if (fd == -1) {
   /* Handle Error */
}

The mkstemp() algorithm for selecting file names has proven to be immune to attacks. This solution is not serially reusable, however, because the mkstemp() function replaces the "XXXXXX" in template the first it is invoked. On subsequent passes through the code, the mkstemp() function will do nothing because the template passed to it contains no X's.

Code Block
bgColor#ccccff
char sfn[] = "temp-XXXXXX";
FILE *sfp;
int fd;

if ((fd = mkstemp(sfn));
if (fd == -1) {
  /* Handle Error */
}

/* 
 * Unlink immediately to allow the name to be recycled.
 * The race condition here is inconsequential if the file
 * is created with exclusive permissions (glibc >= 2.0.7) 
 */

unlink(sfn);

if ((sfp = fdopen(fd, "w+"));
if (sfp == NULL) {
  close(fd);
  /* Handle Error */
}

/* use temporary file */

fclose(sfp); /* also closes fd */

...

Wiki Markup
In many older [implementations|BB. Definitions#implementation], the name is a function of process ID and time, so it is possible for the attacker to predict the name and create a decoy in advance.  FreeBSD has recently changed the {{mk*temp()}} family to eliminate the PID component of the file name and replace the entire field with base-62 encoded randomness.  This raises the number of possible temporary files for the typical use of 6 Xs significantly, meaning that even {{mktemp()}} with 6 Xs is reasonably (probabilistically) secure against guessing, except under frequent usage \[[Kennaway 00|AA. C References#Kennaway 00]\] .

Compliant Solution: tmpfile_s() (ISO/IEC TR 24731-1 )

...