Versions Compared

Key

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

Programmers frequently create temporary files in directories that are writable by everyone (examples are /tmp and /var/tmp on UNIX and C:\TEMP %TEMP% on Windows) and may be purged regularly (for example, every night or during reboot).

...

  1. Use other low-level IPC (interprocess communication) mechanisms such as sockets or shared memory.
  2. Use higher-level IPC mechanisms such as remote procedure calls.
  3. Use a secure directory or a jail that can be accessed only by application instances (making sure ensuring that multiple instances of the application running on the same platform do not compete).

...

  • O_SHLOCK: Atomically obtain a shared lock.
  • O_EXLOCK: Atomically obtain an exclusive lock.

Noncompliant Code Example (tmpnam_s()/open(),

...

Annex K, POSIX)

The C Standard function The TR 24731-1 tmpnam_s() function generates a string that is a valid file name and that is not the same as the name of an existing file. It is almost identical to the tmpnam() function except for an added maxsize argument for the supplied buffer.

Code Block
bgColor#FFCCCC
langc
#define __STDC_WANT_LIB_EXT1__
#include <stdio.h>
 
void func(void) {
  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 */
 
  fd = open(file_name, O_WRONLY | O_CREAT | O_EXCL | O_TRUNC,
            0600);
  if (fd < 0) {
    /* Handle error */
  }
}

Nonnormative text in TR 24731-1 in the C Standard, subclause K.3.5.1.2 [ISO/IEC TR 24731-1:20079899:2011] also recommends the following:

...

If implemented, this reduces the space for unique names and increases the predictability of the resulting names. In general, TR 24731-1 does  Annex K does not establish any criteria for the predictability of names. For example, the name generated by the tmpnam_s function from Microsoft Visual Studio consists of a program-generated file name and, after the first call to tmpnam_s(), a file extension of sequential numbers in base 32 (.1-.1vvvvvu).

...

The POSIX function mktemp() takes a given file name template and overwrites a portion of it to create a file name. The template may be any file name with some number of Xwith exactly six X's appended to it (for example, /tmp/temp.XXXXXX). The six trailing X's are replaced with the current process number and/or a unique letter combination. The number of unique file names mktemp() can return depends on the number of X's provided.

Code Block
Code Block
bgColor#FFCCCC
langc
#include <stdio.h>
#include <stdlib.h>
 
void func(void) {
  char file_name[] = "tmp-XXXXXX";
  int fd;

  if (!mktemp(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 */
  }
}

...

Noncompliant Code Example (tmpfile())

The C The tmpfile() function creates a temporary binary file that is different from any other existing file and that is automatically removed when it is closed or at program termination.

It should be possible to open at least TMP_MAX temporary files during the lifetime of the program. (This limit may be shared with tmpnam().) Subclause 7.21.4.4 of paragraph 6 of the C Standard allows for the value of the macro TMP_MAX to be as small as 25.

...

Code Block
bgColor#FFCCCC
langc
#include <stdio.h>
 
void func(void) {
  FILE *fp = tmpfile();
  if (fp == NULL) {
    /* Handle error */
  }
}

Noncompliant Code Example (tmpfile_s(),

...

Annex K)

The The ISO/IEC TR 24731-1 function tmpfile_s()function creates a temporary binary file that is different from any other existing file and is automatically removed when it is closed or at program termination. If the program terminates abnormally, whether an open temporary file is removed is implementation-defined.

...

It should be possible to open at least TMP_MAX_S temporary files during the lifetime of the program. (This limit may be shared with tmpnam_s().) The value of the macro TMP_MAX_S is required to be only 25 [ISO/IEC TR 24731-1:20079899:2011].

TR 24731-1 notes The C Standard subclause K3.5.1.2 paragraph 7 notes the following regarding the use of tmpfile_s() instead of tmpnam_s() [ISO/IEC TR 24731-1:20079899:2011]:

After a program obtains a file name using the the tmpnam_s function and before the program creates a file with that name, the possibility exists that someone else may create a file with that same name. To avoid this race condition, the the tmpfile_s function should be used instead of of tmpnam_s when possible. One situation that requires the use of the the tmpnam_s function is when the program needs to create a temporary directory rather than a temporary file.

Code Block
bgColor#FFCCCC
langc
#define __STDC_WANT_LIB_EXT1__
#include <stdio.h>
 
void func(void) {
  FILE *fp;
 
  if (tmpfile_s(&fp)) {
    /* Handle error */
  }
}

The TR24731-1 The tmpfile_s() function should not be used with implementations that create temporary files in shared directory, such as /tmp or C:, because the function does not allow the user to specify a directory in which the temporary file should be created.

...

In many older implementations, 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 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 six X's significantly, meaning that even mktemp() with six X's is reasonably (probabilistically) secure against guessing except under frequent usage [Kennaway 2000].

Exceptions

FIO43-EX1: The TR24731-1 EX0: The Annex K tmpfile_s() function can be used if all the targeted implementations create temporary files in secure directories.

...

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

FIO43-C

High

Probable

Medium

P12

L1

The unlink() function doesn't follow symlinks and doesn't really have much of an affect on hard links. So, I guess your options for attacking something like that would be:
*SIGSTOP or SIGTSTP it before the unlink, maybe unlink it yourself and wait (a while) until something created something with the same name, or try to use that name somehow. Probably not that useful, but maybe in a specific attack it could work with a lot of effort.
*You could sorta do a symlink attack with an intermediate path component, for example, if it was /tmp/tmp2/ed.XXXXXX, you could rm tmp2 and then symlink it to /etc or something. It would then rm /etc/ed.XXXXXX, but that probably wouldn't buy you much.

John McDonald

Automated Detection

 Automated Detection

Tool

Version

Checker

Description

Compass/ROSE

 

 

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

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

...

Search for vulnerabilities resulting from the violation of this rule on the CERT website.

...

the CERT website.

Related Guidelines

...

[Austin Group 2008] 
[HP 2003] 
[ISO/IEC 9899:2011]Subclause K.3.5.1.2, "The tmpnam_s Function"
Subclause 7.21.4.4, "The tmpnam Function
[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"

...