According to its C99 definition, the effect of calling remove() on a file is defined by the implementation. Therefore, care must be taken when remove() is called on an open file. It is often the case that calling remove on a file that is open can help mitigate a file input/output race condition, but the underlying implementation needs to be understood before doing so can be considered secure. To be strictly conforming and portable, however, remove() should not be called on an open file.
Non-Compliant Code Example
The following non-compliant code illustrates a case where a file is removed after it is first opened.
#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("Remove Failed\n");
} else {
printf("Remove 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);
}
Contents of a.in:
AAAAAAAAA
Output from a Red Hat Linux Distribution:
Remove Success Good OPEN First: AAAAAAAAA Second: QQQQQQQQQ
Output from a Cygwin session (Windows XP):
Remove Failed Good OPEN 15568 [main] rule11 5048 _cygtls::handle_exceptions: Error while dumping state (probably corrupted stack) Segmentation fault (core dumped)
As shown above, the code worked as intended for the Red Hat Linux Distribution but did not work in Cygwin. For the code to be completely portable and conform to the C99 standard, the call to remove() needs to be eliminated.
Compliant Solution
This compliant solution eliminated the call to remove() because the program is intended to run on all platforms.
#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");
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);
}
Risk Assessment
Calling remove() on an open file may cause abnormal termination if the closed file is written to or read from, but most implementations allow for remove() to be called on an open file without a problem.
Rule |
Severity |
Likelihood |
Remediation Cost |
Priority |
Level |
|---|---|---|---|---|---|
FIOxx-A |
1 (low) |
1 (low) |
2 (medium) |
P2 |
L3 |
References
[[ISO/IEC 9899-1999:TC2]] Section 7.19.4.1, "The remove function"