Files can often be identified by other attributes in addition to the file name, for example, by comparing file ownership or creation time. Information about a file that has been created and closed can be stored and then used to validate the identity of the file when it is reopened.
Comparing multiple attributes of the file increases the likelihood that the reopened file is the same file that had been previously operated on.
Non-Compliant Code Example
This non-compliant code example relies exclusively on the file name to identify the file object.
FILE *fd = fopen(file_name, "w"); if (fd) { /* write to file */ fclose(fd); } else { /* handle error condition */ } /* reopen file_name */ fd = fopen(file_name, "r"); if (fd) { /* read from file */ fclose(fd); } else { /* handle error condition */ }
There is no guarantee that the file opened for reading is the same file that was opened for writing.
Compliant Solution (POSIX)
In this compliant solution, the file is opened using the open()
function. If the file is successfully opened, the fstat()
function is used to read information about the file into the stat
structure. This information is compared with existing information about the file (stored in the dev
and ino
variables) to improve identification.
struct stat st; dev_t dev; /* device */ ino_t ino; /* file serial number */ int fd = open(file_name, O_WRONLY); if ((fd != -1) && (fstat(fd, &st) != -1)) { ino = st.st_ino; dev = st.st_dev; /* write to file */ close(fd); } else { /* handle error condition */ } /* reopen previously written file */ fd = open(file_name, O_RDONLY); if ((fd != -1) && (fstat(fd, &st) != -1) && (st.st_ino == ino) && (st.st_dev == dev) ) { /* read from file */ close(fd); } else { /* handle error condition */ }
Alternatively, the same solution could be implemented using the C99 fopen()
function to open the file and the POSIX fileno()
function to convert the FILE
object pointer to a file descriptor.
The structure members st_mode
, st_ino
, st_dev
, st_uid
, st_gid
, st_atime
, st_ctime
, and st_mtime
should all have meaningful values for all file types on POSIX-compliant systems. The st_ino
field contains the file serial number. The st_dev
field identifies the device containing the file. The st_ino
and st_dev
, taken together, uniquely identify the file. The st_dev value
is not necessarily consistent across reboots or system crashes, however, so you may not be able to use this field for file identification if there is a possibility of a system crash or reboot before you attempt to reopen a file.
It is necessary to call the fstat()
function on an already opened file, rather than calling stat()
on a file name followed by open()
to ensure the file for which the information is being collected is the same file that is opened. See [[FIO01-A. Be careful using functions that use file names for identification]] for more information on avoiding race conditions resulting from the use of file names for identification.
Risk Assessment
Many file-related vulnerabilities are exploited to cause a program to access an unintended file. Proper identification of a file is necessary to prevent exploitation.
Recommendation |
Severity |
Likelihood |
Remediation Cost |
Priority |
Level |
---|---|---|---|---|---|
FIO05-A |
2 (medium) |
2 (probable) |
2 (medium) |
P8 |
L2 |
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
References
[[Drepper 06]] Section 2.2.1 "Identification When Opening"
[[ISO/IEC 9899-1999]] Section 7.19.3, "Files," and Section 7.19.4, "Operations on Files"
[[MITRE 07]] CWE ID 37, "Path Issue - Slash Absolute Path"; CWE ID 38, "Path Issue - Backslash Absolute Path"; CWE ID 39, "Path Issue - Drive Letter or Windows Volume"; CWE ID 62, "UNIX Hard Link"; CWE ID 64, "Windows Shortcut Following (.LNK)"; CWE ID 65, "Windows Hard Link"
[[Open Group 04]] "The open function," "The fstat function"
[[Seacord 05]] Chapter 7, "File I/O"
FIO04-A. Detect and handle input and output errors 09. Input Output (FIO) FIO06-A. Create files with appropriate access permissions