Main Content

Inappropriate I/O operation on device files

Operation can result in security vulnerabilities or a system failure

Description

This defect occurs when you do not check whether a file name parameter refers to a device file before you pass it to these functions:

  • fopen()

  • fopen_s()

  • freopen()

  • remove()

  • rename()

  • CreateFile()

  • CreateFileA()

  • CreateFileW()

  • _wfopen()

  • _wfopen_s()

Device files are files in a file system that provide an interface to device drivers. You can use these files to interact with devices.

Inappropriate I/O operation on device files does not raise a defect when:

  • You use stat or lstat-family functions to check the file name parameter before calling the previously listed functions.

  • You use a string comparison function to compare the file name against a list of device file names.

Risk

Operations appropriate only for regular files but performed on device files can result in denial-of-service attacks, other security vulnerabilities, or system failures.

Fix

Before you perform an I/O operation on a file:

  • Use stat(), lstat(), or an equivalent function to check whether the file name parameter refers to a regular file.

  • Use a string comparison function to compare the file name against a list of device file names.

Examples

expand all

#include <stdio.h>
#include <string.h>

#define SIZE1024 1024

FILE* func()
{

    FILE* f;
    const char file_name[SIZE1024] = "./tmp/file";
    
    if ((f = fopen(file_name, "w")) == NULL) {
        /*handle error */
    };
    /*operate on file */
}

In this example, func() operates on the file file_name without checking whether it is a regular file. If file_name is a device file, attempts to access it can result in a system failure.

Correction — Check File with lstat() Before Calling fopen()

One possible correction is to use lstat() and the S_ISREG macro to check whether the file is a regular file. This solution contains a TOCTOU race condition that can allow an attacker to modify the file after you check it but before the call to fopen(). To prevent this vulnerability, ensure that file_name refers to a file in a secure folder.

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>

#define SIZE1024 1024

FILE* func()
{

    FILE* f;
    const char file_name[SIZE1024] = "./tmp/file";
    struct stat orig_st;
    if ((lstat(file_name, &orig_st) != 0) ||
        (!S_ISREG(orig_st.st_mode))) {
        exit(0);
    }
    if ((f = fopen(file_name, "w")) == NULL) {
        /*handle error */
    };
    /*operate on file */
} 

Result Information

Group: Security
Language: C | C++
Default: Off
Command-Line Syntax: INAPPROPRIATE_IO_ON_DEVICE
Impact: Medium

Version History

Introduced in R2018b