 
                            Standard FILE objects and their underlying representation (file descriptors on POSIX platforms or handles elsewhere) are a finite resource that must be carefully managed. The number of files that an implementation guarantees may be open simultaneously is bounded by the FOPEN_MAX macro defined in <stdio.h>. The value of the macro is guaranteed to be at least 8. Consequently, portable programs must either avoid keeping more than FOPEN_MAX files at the same time or be prepared for functions such as fopen() to fail due to resource exhaustion.
Failing to close files when they are no longer needed may allow attackers to exhaust, and possibly manipulate, system resources. This phenomenon is typically referred to as sometimes called file descriptor leakage, although file pointers may also be used as an attack vector. In addition, keeping files open longer than necessary increases the risk that data written into in-memory file buffers will not be flushed in the event of abnormal program termination. To prevent file descriptor leaks and to guarantee that any buffered data will be flushed into permanent storage, files should must be closed when they are no longer needed.
Be careful not to The behavior of a program is undefined when it uses the value of a pointer to a FILE object after the associated file is closed (see undefined behavior 153.) Programs that close the standard streams (especially stdout): doing so will send an EOF to any application on the other side of a pipe, possibly causing it to take actions that shouldn't have occurred until the first application terminates but also stderr and stdin) must be careful not to use the stream objects in subsequent function calls, particularly those that implicitly operate on such objects (such as printf(), perror(), and getc()).
Noncompliant Code Example
...
In   this   noncompliant   code   example , derived   from   a  [vulnerability|BB. Definitions#vulnerability]  in   OpenBSD's  {{chpass}}  program  \[ [NAI  98|AA. C References#NAI 98]\1998],   a   file   containing   sensitive   data   is   opened   for   reading.  The program then retrieves the registered editor from the {{EDITOR}} environment variable and executes it using the {{system()}} command. If, the {{system()}} command is implemented in a way that spawns a child process, then the child process inherits the file descriptors opened by its parent. As a result, the child process, which in this example is the program specified by the {{EDITOR}} environment variable, will be able to access the contents of the potentially sensitive file called {{file_name}}The get_validated_editor() function retrieves the registered editor from the EDITOR environment variable and sanitizes it to be a valid editor in accordance with FIO02-C. Canonicalize path names originating from tainted sources. The function returns a command for invoking the editor  which is subsequently passed as a command system() function. If the system() function is implemented in a way that spawns a child process, then the child process could inherit the file descriptors opened by its parent. If this happens, as it does in POSIX systems, the child process will be able to access the contents of the potentially sensitive file called file_name.
| Code Block | ||||
|---|---|---|---|---|
| 
 | ||||
| #include <stdio.h> #include <stdlib.h> extern FILE* f; const char *get_validated_editor(void); void func(const char *file_name) { FILE *f; /* Initializeconst file_namechar */editor; f = fopen(file_name, "r"); if (f == NULL) { /* Handle fopen() error */ } /* ... */ editor = getenv("EDITOR"get_validated_editor(); if (editor == NULL) { /* Handle getenv() error */ } if (system(editor) == -1) { /* Handle error */ } } | 
If the command returned by get_validated_editor() will always be a simple path (such as /usr/bin/vim), and runs on a POSIX system, this program could be strengthened by using a call to execve() rather than system(), in accordance with ENV33-C. Do not call system().
On UNIX-based systems, child processes are typically spawned using a form of fork() and exec(), and the child process always receives copies of inherits from its parent 's any file descriptors that do not have the close-on-exec flag set. Under Microsoft Windows, the CreateProcess() function is typically used to start a child process. In Windows, file-handle inheritance is determined on a per-file bases. Additionally, the CreateProcess() function itself provides a mechanism to limit file-handle inheritance. As a result, the child process spawned by CreateProcess() may not receive copies of the parent process's open file handles.and per-spawned process basis. See WIN03-C. Understand HANDLE inheritance for more information.
Compliant Solution
In this compliant solution, file_name is closed before launching the editor.:
| Code Block | ||||
|---|---|---|---|---|
| 
 | ||||
| FILE* f; #include <stdio.h> #include <stdlib.h> extern const char *get_validated_editor(void); void func(const char *file_name) { FILE *f; /* Initializeconst file_namechar */editor; f = fopen(file_name, "r"); if (f == NULL) { /* Handle fopen() error */ } /* ... */ fclose(f); f = NULL; editor = getenv("EDITOR"get_validated_editor(); if (editor == NULL) { /* Handle getenv() error */ } /* Sanitize environment before calling system()! */ if (system(editor) == -1) { /* Handle Errorerror */ } | 
...
|   }
} | 
Compliant Solution (POSIX)
Sometimes it is not practical for a program to close all active file descriptors before issuing a system call such as system() or exec(). An alternative on POSIX systems is to use the FD_CLOEXEC flag, or O_CLOEXEC when available, to set the close-on-exec flag for the file descriptor.:
| Code Block | ||||
|---|---|---|---|---|
| 
 | ||||
| int flags; #include <stdio.h> #include <stdlib.h> #include <unistd.h> extern const char *get_validated_editor(void); void func(const char *file_name) { int flags; /* Initialize file_namechar */editor; int fd = open(file_name, O_RDONLY); if (fd == -1) { /* Handle error */ } flags = fcntl(fd, F_GETFD); if (flags == -1) { /* Handle error */ } if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1) { /* Handle error */ } /* ... */ editor = getenv("EDITOR"get_validated_editor(); if (editor == NULL) { /* Handle getenv() error */ } if (system(editor) == -1) { /* Handle error */ } | 
...
| } | 
Compliant Solution (Linux)
Some   systems   (such   as   those   with   Linux   kernel   versions  greater than or equal to  2.6.23 and later)   have   an  {{O_CLOEXEC}}  flag   that   provides   the   close-on-exec   function   directly   in  {{open()}}.   This   flag   is   required   by  POSIXIEEE Std 1003.1 -2008 \[[Austin Group 08|AA. C References#Austin Group 08]\]. In multithreaded programs, this flag should be used if possible because it prevents a timing hole between {{open()}} and {{fcntl()}} when using {{FD_CLOEXEC}}, during which another thread can create a child process while the file descriptor does not have [IEEE Std 1003.1:2013]. In multithreaded programs, this flag should be used, if possible, because it prevents a timing hole between open() and fcntl() when using FD_CLOEXEC, during which another thread can create a child process while the file descriptor does not have close-on-exec   set.
| Code Block | ||||
|---|---|---|---|---|
| 
 | ||||
| #include <stdio.h> #include <stdlib.h> extern const char *get_validated_editor(void); void func(const char *file_name; /* Initialize file_name */ ) { char *editor; int fd = open(file_name, O_RDONLY | O_CLOEXEC); if (fd == -1) { /* Handle error */ } /* ... */ editor = getenv("EDITOR"get_validated_editor(); if (editor == NULL) { /* Handle getenv() error */ } if (system(editor) == -1) { /* Handle error */ } } | 
Risk Assessment
Failing to properly close files may allow unintended access to, or exhaustion of, system resources.
| Rule | Severity | Likelihood | Detectable | 
|---|
| Repairable | Priority | Level | 
|---|
| FIO22-C | Medium | 
| Unlikely | 
| No | 
| No | 
| P2 | L3 | 
Automated Detection
The LDRA tool suite Version 7.6.0 can detect violations of this recommendation.
Fortify SCA Version 5.0 with CERT C Rule Pack can detect violations of this recommendation.
Klocwork Version 8.0.4.16 can detect violations of this rule with the RH.LEAK checker.
...
| Tool | Version | Checker | Description | ||||||
|---|---|---|---|---|---|---|---|---|---|
| Compass/ROSE | |||||||||
| Klocwork | 
 | RH.LEAK | |||||||
| LDRA tool suite | 
 | 49 D | Partially implemented | ||||||
| Parasoft C/C++test | 
 | CERT_C-FIO22-a | Ensure resources are freed | 
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
References
| Wiki Markup | 
|---|
| \[[Austin Group 08|AA. C References#Austin Group 08]\]
\[[Dowd 06|AA. C References#Dowd 06]\] Chapter 10, "UNIX Processes" (File Descriptor Leaks 582-587)
\[[MITRE 07|AA. C References#MITRE 07]\] [CWE ID 404|http://cwe.mitre.org/data/definitions/404.html], "Improper Resource Shutdown or Release," and [CWE ID 403|http://cwe.mitre.org/data/definitions/403.html], "UNIX File Descriptor Leak"
\[[MSDN|AA. C References#MSDN]\] [Inheritance|http://msdn.microsoft.com/en-us/library/ms683463.aspx] (Windows)
\[[NAI 98|AA. C References#NAI 98]\] | 
Related Guidelines
| CERT C Secure Coding Standard | WIN03-C. Understand HANDLE inheritance | 
| SEI CERT C++ Coding Standard | FIO51-CPP. Close files when they are no longer needed | 
| CERT Oracle Secure Coding Standard for Java | FIO04-J. Release resources when they are no longer needed | 
| MITRE CWE | CWE-403, UNIX file descriptor leak CWE-404, Improper resource shutdown or release CWE-770, Allocation of resources without limits or throttling | 
Bibliography
| [Dowd 2006] | Chapter 10, "UNIX Processes" ("File Descriptor Leaks," pp. 582–587) | 
| [IEEE Std 1003.1:2013] | XSH, System Interfaces, open | 
| [MSDN] | Inheritance (Windows) | 
| [NAI 1998] | 
...
FIO41-C. Do not call getc() or putc() with stream arguments that have side effects 09. Input Output (FIO) FIO43-C. Do not create temporary files in shared directories