Versions Compared

Key

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

...

  1. created unpredictable file names.
  2. created with unique names.
  3. opened only if the file doesn't already exist (atomic open).
  4. opened with exclusive access.
  5. opened with appropriate permissions.
  6. removed before the program exits.

The following table lists common temporary file functions and their respective conformance to these criteria:

...

This noncompliant code example creates a file with a hard-coded file_name (presumably in a shared directory such as /tmp or C:\Temp).:

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

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

...

The next noncompliant code example attempts to remedy the problem by using the POSIX open() function and providing a mechanism to indicate whether an existing file has been opened for writing or a new file has been created [Open Group 2004]. If the O_CREAT and O_EXCL flags are used together, the open() function fails when the file specified by file_name already exists. To prevent an existing file from being opened and truncated, include the flags O_CREAT and O_EXCL when calling open().:

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

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

/* A TOCTOU race condition exists here */

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

...

A call to mkstemp() replaces the six X's in the template string with six randomly selected characters and returns a file descriptor for the file (opened for reading and writing), as in this compliant solution.:

Code Block
bgColor#ccccff
langc
const char *sdn = "/home/usr1/";
char sfn[] = "/home/usr1/temp-XXXXXX";
FILE *sfp;

if (!secure_dir(sdn)) {
  /* Handle error */
}

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

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

if (unlink(sfn) == -1) {
  /* Handle error */
}

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

/* Use temporary file */

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

...

Tool

Version

Checker

Description

Compass/ROSE

 

 

Can detect violations of this recommendation. Specifically, Rose reports use of tmpnam(), tmpnam_s(), tmpfile(), and mktemp().

Coverity6.5SECURE_TEMPFully Implemented.

LDRA tool suite

Include Page
LDRA_V
LDRA_V

489 S

Partially implemented.

PRQA QA-C
Include Page
PRQA_V
PRQA_V
warncall tmpnam, tmpfile, mktemp, tmpnam_sPartially implemented

...

CERT C++ Secure Coding StandardFIO43-CPP. Do not create temporary files in shared directories
CERT Oracle Secure Coding Standard for JavaFIO03-J. Remove temporary files before termination
ISO/IEC TR 24731-1:2007Section 6.5.1.1, "The tmpfile_s Function,"
Section 6.5.1.2, "The tmpnam_s Function"
Section 6.5.2.1, "The fopen_s Function"
ISO/IEC TR 24772:2013Path Traversal [EWR]
MITRE CWECWE-379, Creation of temporary file in directory with insecure permissions

Bibliography

...

[Austin Group 2008] 
[HP 2003] 
[Kennaway 2000] 
[Open Group 2004]mktemp()
mkstemp()
open()
[Seacord 2013]Chapter 3, "Pointer Subterfuge"
Chapter 8, "File I/O"
[Viega 2003]Section 2.1, "Creating Files for Temporary Use"
[Wheeler 2003]Chapter 7, "Structure Program Internals and Approach"

...