Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: REM Cost Reform

According to its C99 definition, the effect of calling Invoking remove() on a an open file is implementation-defined by the implementation. Therefore, care must be taken when remove() is called on . Removing 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 secureis 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, however, remove() should not be called on an open file.

...

Noncompliant Code Example

The following non-compliant code illustrates This noncompliant code example shows a case where a file is removed after while it is first opened.still open:

Code Block
bgColor#FFcccc
langc
char *file_name;
FILE *file;

/* Initialize file_name */

file = fopen(file_name, "w+");
if (file == NULL
#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) {
  /* Handle 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++error condition */
}

/* ... */

if (remove(file_name) != 0) {
  /* Handle 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:

Code Block

AAAAAAAAA

Output from a Red Hat Linux Distribution:

Code Block

Remove Success
Good OPEN
First: AAAAAAAAA
Second: QQQQQQQQQ

Output from a Cygwin session (Windows XP):

Code Block

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

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]This compliant solution eliminated the call to remove() because the program is intended to run on all platforms.

Code Block
bgColor#ccccff
langc
FILE *file;
char *file_name;

/* Initialize file_name */

file = fopen(file_name, "w+");
if (file == NULL) {
  /* Handle error condition */
}

if (unlink(file_name) != 0
#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++) {
  /* Handle 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);
}
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 closed removed file is written to or read from, but most implementations allow for remove() to be called on an open file without a problem.or it may result in unintended information disclosure from files not deleted as intended.

Recommendation

Rule

Severity

Likelihood

Detectable

Remediation Cost

Repairable

Priority

Level

FIOxx-A

1 (low)

1 (low)

2 (medium)

P2

L3

References

FIO08-C

Medium

Probable

No

No

P4

L3

Automated Detection

Tool

Version

Checker

Description

CodeSonar
Include Page
CodeSonar_V
CodeSonar_V
(customization)Users can implement a custom check for calls to remove() on a file that is currently open.
Compass/ROSE




Helix QAC

Include Page
Helix QAC_V
Helix QAC_V

C5014
LDRA tool suite
Include Page
LDRA_V
LDRA_V

81 D

Fully implemented

Polyspace Bug Finder

Include Page
Polyspace Bug Finder_V
Polyspace Bug Finder_V

CERT C: Rec. FIO08-C

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


...

Image Added Image Added Image Added Wiki Markup\[[ISO/IEC 9899-1999:TC2|AA. C References#ISO/IEC 9899-1999TC2]\] Section 7.19.4.1, "The remove function"