Versions Compared

Key

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

...

Code Block
bgColor#FFCCCC
langc

char *filename = /* file name */;
char *userbuf = /* user data */;
unsigned int userlen = /* length of userbuf string */;

struct stat lstat_info;
int fd;
/* ... */
if (lstat(filename, &lstat_info) == -1) {
  /* Handle error */
}

if (!S_ISLNK(lstat_info.st_mode)) {
   fd = open(filename, O_RDWR);
   if (fd == -1) {
       /* Handle error */
   }
}
if (write(fd, userbuf, userlen) < userlen) {
  /* Handle error */
}

This code contains a time-of-check-, time-of-use (TOCTOU) race condition between the call to lstat() and the subsequent call to open() because both functions operate on a file name that can be manipulated asynchronously to the execution of the program. (See recommendation FIO01-C. Be careful using functions that use file names for identification.)

...

  1. calling lstat() on the file name.
  2. calling open() to open the file.
  3. calling fstat() on the file descriptor returned by open().
  4. comparing the file information returned by the calls to lstat() and fstat() to ensure that the files are the same.
Code Block
bgColor#ccccff
langc

char *filename = /* file name */;
char *userbuf = /* user data */;
unsigned int userlen = /* length of userbuf string */;

struct stat lstat_info;
struct stat fstat_info;
int fd;
/* ... */
if (lstat(filename, &lstat_info) == -1) {
  /* handle error */
}

fd = open(filename, O_RDWR);
if (fd == -1) {
  /* handle error */
}

if (fstat(fd, &fstat_info) == -1) {
  /* handle error */
}

if (lstat_info.st_mode == fstat_info.st_mode &&
    lstat_info.st_ino == fstat_info.st_ino  &&
    lstat_info.st_dev == fstat_info.st_dev) {
  if (write(fd, userbuf, userlen) < userlen) {
    /* Handle Error */
  }
}

...

Comparing i-nodes, using the st_ino fields, and devices, using the st_dev fields, ensures that the file passed to lstat() is the same as the file passed to fstat(). (See recommendation FIO05-C. Identify files using multiple file attributes.)

...

sectioncan

Can detect some violations of this rule. In particular, it ensures that calls to open() that are preceded by a call to lstat() are also followed by a call to fstat().

Tool

Version

Checker

Description

Compass/ROSE

 

 

Section

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

ISO/IEC 9899:1999] Section 2011 Section 7.1921, "Input/output <stdio.h>"

MITRE CWE: CWE-363, "Race Condition Enabling Link Following"

MITRE CWE: CWE-365, "Race Condition in Switch"

...

[Dowd 2006] Chapter 9, "UNIX 1: Privileges and Files"
[Open Group 2004] lstat(), fstat(), open()
[Seacord 2005a] Chapter 7, "File I/O"

...