Calling Invoking remove() on a an open file that is currently open has implementation-defined behavior. In the case of Cygwin it just fails, and in the case of Andrew Linux is acts like the file still exists, but you can create a new file with the same name without worrying about overwriting the file pointer from the first time the file was opened.
Code
| Code Block | ||
|---|---|---|
| ||
#include <stdio.h>
int main(int argc, char* argv) {
FILE* first;
FILE* second;
char buf1[10];
char buf2[10];
int i;
first = fopen("a.in", "r");
if (remove("a.in") == -1) {
printf("Unlink Failed\n");
} else {
printf("Unlink Success\n");
}
second = fopen("a.in", "w");
if (second) {
printf("Good OPEN\n");
} else {
printf("Bad OPEN\n");
}
for (i = 0; i < 10; i++) {
buf2[i] = 'Q';
}
fwrite(buf2, sizeof(char), 9, second);
fflush(second);
fread(buf1, sizeof(char), 9, first);
buf1[9] = '\0';
buf2[9] = '\0';
printf("First: %10s\n", buf1);
printf("Second: %10s\n", buf2);
}
|
File a.in
AAAAAAAAA
Output on Andrew Linux
Unlink Success
Good OPEN
First: AAAAAAAAA
Second: QQQQQQQQQ
| Wiki Markup |
|---|
*Output on Cygwin*
Unlink Failed
Good OPEN
15568 \[main\] rule11 5048 \_cygtls::handle_exceptions: Error while dumping state (probably corrupted stack)
Segmentation fault (core dumped) |
. Removing an open file is sometimes recommended to hide the names of temporary files that may be prone to attack. (See FIO21-C. Do not create temporary files in shared directories.)
In cases requiring the removal of an open file, a more strongly defined function, such as the POSIX unlink() function, should be considered. To be strictly conforming and portable, remove() should not be called on an open file.
Noncompliant Code Example
This noncompliant code example shows a case where a file is removed while it is still open:
| Code Block | ||||
|---|---|---|---|---|
| ||||
char *file_name;
FILE *file;
/* Initialize file_name */
file = fopen(file_name, "w+");
if (file == NULL) {
/* Handle error condition */
}
/* ... */
if (remove(file_name) != 0) {
/* Handle error condition */
}
/* Continue performing I/O operations on file */
fclose(file);
|
Some implementations will not remove the file specified by file_name because the stream is still open.
Implementation Details
Code compiled for Microsoft Windows prevents the remove() call from succeeding when the file is open, meaning that the file link will remain after execution completes.
Compliant Solution (POSIX)
This compliant solution uses the POSIX unlink() function to remove the file. The unlink() function is guaranteed to unlink the file from the file system hierarchy but keep the file on disk until all open instances of the file are closed [IEEE Std 1003.1:2013].
| Code Block | ||||
|---|---|---|---|---|
| ||||
FILE *file;
char *file_name;
/* Initialize file_name */
file = fopen(file_name, "w+");
if (file == NULL) {
/* Handle error condition */
}
if (unlink(file_name) != 0) {
/* Handle error condition */
}
/* Continue performing I/O operations on file */
fclose(file);
|
Note that there is a race window between the fopen() call and the unlink() call, which could be exploited. This exploitation can be mitigated if the operations occur in a secure directory; see FIO45-C. Avoid TOCTOU race conditions while accessing files for more information.
Risk Assessment
Calling remove() on an open file has different implications for different implementations and may cause abnormal termination if the removed file is written to or read from, or it may result in unintended information disclosure from files not deleted as intended.
Recommendation | Severity | Likelihood | Detectable | Repairable | Priority | Level |
|---|---|---|---|---|---|---|
FIO08-C | Medium | Probable | No | No | P4 | L3 |
Automated Detection
Tool | Version | Checker | Description | ||||||
|---|---|---|---|---|---|---|---|---|---|
| CodeSonar |
| (customization) | Users can implement a custom check for calls to remove() on a file that is currently open. | ||||||
| Compass/ROSE | |||||||||
| Helix QAC |
| C5014 | |||||||
| LDRA tool suite |
| 81 D | Fully implemented | ||||||
| Polyspace Bug Finder |
| Checks for function remove() called on open file |
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
Related Guidelines
Bibliography
...
From 'man 2 unlink':
BUGS
Infelicities in the protocol underlying NFS can cause the unexpected disappearance of files which are still being used.