Versions Compared

Key

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

...

Code Block
bgColor#ffcccc
langc
char *file_name;
FILE *file;

/* Initialize file_name */

if (!fgets(file_name, sizeof(file_name), stdin)#include <stdio.h>
 
void func(const char *file_name) {
  /* Handle error */
}

FILE *file;

  if ((file = fopen(file_name, "wb")) == NULL) {
    /* Handle error */
  }

  /* Operate on file. */

  fclose(file);
}

Compliant Solution (POSIX)

...

Code Block
bgColor#ccccff
langc
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#ifdef O_NOFOLLOW
  #define OPEN_FLAGS O_NOFOLLOW | O_NONBLOCK
#else
  #define OPEN_FLAGS O_NONBLOCK
#endif

/* ... */

void func(const char *file_name) {
  struct stat orig_st;
  struct stat open_st;
  int fd;
  int flags;
char *file_name;

/* Initialize file_name */

if (!fgets(file_name, sizeof(file_name), stdin)) {
  /* Handle error */
}

if ((lstat(file_name, &orig_st) != 0)
 ||
      (!S_ISREG(orig_st.st_mode)))
 {
    /* Handle error */
  }

  /* A TOCTOU race condition exists here, see below. */

  fd = open(file_name, OPEN_FLAGS | O_WRONLY);
  if (fd == -1) {
    /* Handle error */
  }

  if (fstat(fd, &open_st) != 0) {
    /* Handle error */
  }

  if ((orig_st.st_mode != open_st.st_mode) ||
      (orig_st.st_ino  != open_st.st_ino) ||
      (orig_st.st_dev  != open_st.st_dev)) {
    /* File was tampered with. */
  }

  /* Optional: drop the O_NONBLOCK now that we are sure
  *   this is a good file. */
  if ((flags = fcntl(fd, F_GETFL)) == -1) {
    /* Handle error */
  }

  if (fcntl(fd, F_SETFL, flags & ~O_NONBLOCK) != 0) {
    /* Handle error */
  }

  /* Operate on file */

  close(fd);
}

This code contains an intractable TOCTOU (time-of-check, time-of-use) race condition under which an attacker can alter the file referenced by file_name following the call to lstat() but before the call to open(). The switch will be discovered after the file is opened, but opening the file cannot be prevented in the case where this action itself causes undesired behavior.

...

Code Block
bgColor#ccccff
langc
#include <Windows.h>
 
void func(const TCHAR *file_name) {
  HANDLE hFile = CreateFile(file_name,
                            GENERIC_READ | GENERIC_WRITE, 0, 
                            NULL, OPEN_EXISTING,
                            FILE_ATTRIBUTE_NORMAL, NULL);
  if (hFile == INVALID_HANDLE_VALUE) {
    /* Handle error */
  } else if (GetFileType(hFile) != FILE_TYPE_DISK) {
    /* Handle error */
    CloseHandle(hFile);
  } else {
    /* Operate on file */
    CloseHandle(hFile);
  }
}

Risk Assessment

Allowing operations that are appropriate only for files to be performed on devices can result in denial-of-service attacks or more serious exploits depending on the platform.

...

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

Related Guidelines

...