Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: somehow my paragraph disappeared

...

This POSIX code example verifies that each subsequent file access operates on the same file. In POSIX, every file can be uniquely identified by using its device and i-node attributes. This code example checks that a file name refers to a regular file (and not a directory, symbolic link, or other special file) by invoking lstat(). This call also retrieves its device and i-node. The file is subsequently opened. Finally, the program verifies that the file that was opened is the same one (matching device and i-nodes) as the file that was confirmed as a regular file.

An attacker can still exploit this code if they have the ability to delete the benign file and create the malicious file within the race window between lstat() and open(). It is possible that the OS kernel will reuse the same device and i-node for both files. This can be mitigated by making sure that the attacker lacks the permissions to delete the benign file.

Code Block
bgColor#ccccff
langc
#include <sys/stat.h>
#include <fcntl.h>

int open_regular_file(char *filename, int flags) {
  struct stat lstat_info;
  struct stat fstat_info;
  int f;
 
  if (lstat(filename, &lstat_info) == -1) {
    /* File does not exist, handle error */
  }
 
  if (!S_ISREG(lstat_info.st_mode)) {
    /* File is not a regular file, handle error */
  }
 
  if ((f = open(filename, flags)) == -1) {
    /* File has disappeared, handle error */
  }
 
  if (fstat(f, &fstat_info) == -1) {
    /* Handle error */
  }
 
  if (lstat_info.st_ino != fstat_info.st_ino  ||
      lstat_info.st_dev != fstat_info.st_dev) {
    /* Open file is not the expected regular file, handle error */
  }
 
  /* f is the expected regular open file */
  return f;
}

...