Main Content

File access between time of check and use (TOCTOU)

File or folder might change state due to access race

Description

This defect occurs when a race condition happens between checking the existence of a file or folder, and using the file or folder.

Risk

An attacker can access and manipulate your file between your check for the file and your use of a file. Symbolic links are particularly risky because an attacker can change where your symbolic link points.

Fix

Before using a file, do not check its status. Instead, use the file and check the results afterward.

Examples

expand all

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>

extern void print_tofile(FILE* f);

void writeToFile(char * log_path) {
    if (access(log_path, W_OK)==0) {
        FILE* f = fopen(log_path, "w");
        if (f == NULL) {
            print_tofile(f);
            fclose(f);
        }
    }
}

In this example, before opening and using the file, the function writeToFile() checks if the file exists. However, an attacker can change the file between the first and second lines of the function.

Correction — Open File in Exclusive Mode (POSIX)

In POSIX®, you can use the open() function with the flags O_CREAT and O_EXCL that causes the file opening to fail if the file already exists. You can check for the failure before performing further actions on the file.

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>

extern void print_tofile(FILE* f);

void writeToFile(char * log_path) {
    int fd = open(log_path, O_CREAT | O_EXCL | O_WRONLY);
    if (fd!=-1) {
        FILE *f = fdopen(fd, "w");
        if (f) {
            print_tofile(f);
            fclose(f);
        }
    }
}
Correction — Open File in Exclusive Mode (C11)

Since C11, when you open a file using the function fopen() or fopen_s(), you can include the character x in the access mode specifier. This access mode specifier causes the file opening to fail if the file already exists. You can check for the failure before performing further actions on the file.

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>

extern void print_tofile(FILE* f);

void writeToFile(char * log_path) {
        FILE* f = fopen(log_path, "wx");
        if (f == NULL) {
            print_tofile(f);
            fclose(f);
        }
}

Result Information

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

Version History

Introduced in R2015b