Skip to main content

IAR Embedded Workbench for RX 5.20

CERT-FIO32-C

In this section:
Synopsis

Do not perform operations on devices that are only appropriate for files

Enabled by default

Yes

Severity/Certainty

Medium/Low

mediumlow.png
Full description

File names may be used to access special files, which are actually devices. Performing operations on device files that are intended for ordinary character or binary files can result in crashes and denial-of-service attacks. Device files in UNIX can be a security risk when an attacker can access them in an unauthorized way. It is possible to lock certain applications by attempting to open devices rather than files.

Coding standards
CERT FIO32-C

Do not perform operations on devices that are only appropriate for files

Code examples

The following code example fails the check and will give a warning:

#include <stdio.h>

void func(const char *file_name) {
  FILE *file;
  if ((file = fopen(file_name, "wb")) == NULL) {
    /* Handle error */
  }

  /* Operate on the file */

  if (fclose(file) == EOF) {
    /* Handle error */
  }
}

The following code example passes the check and will not give a warning about this issue:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.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;

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

  /* Race window */

  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)) {
    /* The 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) == -1) {
    /* Handle error */
  }

  /* Operate on the file */

  if (close(fd) == -1) {
    /* Handle error */
  }
}