Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: swap read vs write NCCE/CS pairs

...

A program that performs a file operation on a filename or path twice creates a race window between the two file operations. This race window comes from the assumption that the filename refers to the same file both times. If an attacker can modify the file, remove it, or replace it with a different file, then this assumption will not hold.

Noncompliant Code Example (POSIX

...

write)

If an existing file is opened for writing, the file's previous contents are destroyed. This noncompliant code example attempts example tries to ensure that an open will succeed by first calling the POSIX access() function, which returns zero if the file exists and can be accessed using the specified permissionsprevent an existing file from being overwritten by first ensuring that a file does not exist before opening it for writing. An attacker can exploit the race window between the access and the open to cause cause fopen() to fail in spite of the check to overwrite an existing file.

Code Block
bgColor#ffcccc
langc
#include <stdio.h>
#include <unistd.h> 

void open_some_file(const char *file) {
  FILE *f; 
  if (access(file, R_OK | W_OK) == 0) {
    printf("access granted.\n");
    f = fopen(file, "rbwb+");
    if (NULL == f) {
      /* Handle error */
    }
    /* write readto file */
    fclose(f);
  }
}

Compliant Solution (

...

C11 write)

This compliant solution dispenses with an access call and merely relies on fopen() to verify the fileuses the x mode of fopen(), which was added in C11. This mode causes fopen() to fail if the file exists. This check and subsequent open is done without creating a race window. Note that the x mode provides exclusive access to the file if the operating platform provides this support.

Code Block
bgColor#ccccff
langc
#include <stdio.h>

void open_some_file(const char *file) {
  FILE *f; 
  f = fopen(file, "rbwb+x");
  if (NULLf == fNULL) {
    /* Handle error */
  }
  printf("access granted.\n");
  /* write to readthe file */
  fclose(f);
}

...

Compliant Solution (POSIX write)

If an existing file is opened for writing, the file's previous contents are destroyed. This noncompliant code example tries to prevent an existing file from being overwritten by first ensuring that a file does not exist before opening it for writing. An attacker can exploit the race window between the access and the open to cause fopen() to overwrite an existing fileThis compliant solution uses the O_CREAT and O_EXCL flags of POSIX's open() system call. These flags cause open() to fail if the file exists.

Code Block
bgColor#ffcccc#ccccff
langc
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>

void open_some_file(const char *file) {
  FILEint *f;fd 
  if (access= open(file, RO_OKCREAT | WO_OK)EXCL == 0) {| O_RDWR);
  if  printf("access granted.\n");
(fd != -1) {
    FILE *f = fopenfdopen(filefd, "wbrw+");
    if (NULLf !== fNULL) {
      /* Handle error */printf("access granted.\n");
    }
    /* write to file */
      fclose(f);
    }
    close(fd);
  }
}

Compliant Solution (C11 write)

Noncompliant Code Example (POSIX read)

This noncompliant code example attempts to ensure that an open will succeed by first calling the POSIX access() function, which returns zero if the file exists and can be accessed using the specified permissions. An attacker can exploit the race window between the access and the open to cause fopen() to fail in spite of the checkThis compliant solution uses the x mode of fopen(), which was added in C11. This mode causes fopen() to fail if the file exists. This check and subsequent open is done without creating a race window. Note that the x mode provides exclusive access to the file if the operating platform provides this support.

Code Block
bgColor#ccccff#ffcccc
langc
#include <stdio.h>
#include <unistd.h> 

void open_some_file(const char *file) {
  FILE *f; 
  if (access(file, R_OK | W_OK) == 0) {
    printf("access granted.\n");
    f = fopen(file, "wbrb+x");
    if (fNULL == NULLf) {
      /* Handle error */
    }
  printf("access granted.\n");
  /* write to theread file */
    fclose(f);
  }
}

Compliant Solution (

...

read)

This compliant solution uses the O_CREAT and O_EXCL flags of POSIX's open() system call. These flags cause open() to fail if the file existsdispenses with an access call and merely relies on fopen() to verify the file.

Code Block
bgColor#ccccff
langc
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>

void open_some_file(const char *file) {
  intFILE fd*f = openfopen(file, O_CREAT | O_EXCL | O_RDWR"rb+");
  if (fdNULL !== -1f) {
    FILE /*f = fdopen(fd, "rw+");
    if (f != NULL) {
      Handle error */
  }
  printf("access granted.\n");
      /* writeread to file */
      fclose(f);
    }
    close(fd);
  }
}

Exceptions

FIO45-EX1: Accessing a path multiple times is permitted if it is requested specifically by a user. A program that accepts commands from a user to read or write a specific filename does not violate this standard. Example programs would include file managers or text editors.

...