...
Be careful not to close the standard streams (especially stdout), this : 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.
...
| Code Block |
|---|
|
FILE* f;
const char *editor;
char *file_name;
/* initializeInitialize file_name */
f = fopen(file_name, "r");
if (f == NULL) {
/* Handle fopen() error */
}
/* ... */
editor = getenv("EDITOR");
if (editor == NULL) {
/* Handle getenv() error */
}
if (system(editor) == -1) {
/* Handle Errorerror */
}
|
On UNIX-based systems, child processes are typically spawned using a form of fork() and exec(), and the child process always receives copies of its parent's file descriptors. 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.
...
| Code Block |
|---|
|
FILE* f;
const char *editor;
char *file_name;
/* initializeInitialize file_name */
f = fopen(file_name, "r");
if (f == NULL) {
/* Handle fopen() error */
}
/* ... */
fclose(f);
f = NULL;
editor = getenv("EDITOR");
if (editor == NULL) {
/* Handle getenv() error */
}
/* Sanitize environment before calling system()! */
if (system(editor) == -1) {
/* Handle Error */
}
|
...
| Code Block |
|---|
|
int flags;
char *editor;
char *file_name;
/* initializeInitialize file_name */
int fd = open(file_name, O_RDONLY);
if (fd == -1) {
/* Handle Errorerror */
}
flags = fcntl(fd, F_GETFD);
if (flags == -1) {
/* Handle Errorerror */
}
if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1) {
/* Handle Errorerror */
}
/* ... */
editor = getenv("EDITOR");
if (editor == NULL) {
/* Handle getenv() error */
}
if (system(editor) == -1) {
/* Handle Errorerror */
}
|
| Wiki Markup |
|---|
Some systems (such as those with Linux kernel versions greater than or equal to 2.6.23) have an {{O_CLOEXEC}} flag whichthat provides the close-on-exec function directly in {{open()}}. This flag is required by POSIX.1-2008 \[[Austin Group 08|AA. C References#Austin Group 08]\]. In multi-threadedmultithreaded programs, this flag should be used if possible asbecause it avoidsprevents 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 |
|---|
|
char *editor;
char *file_name;
/* initializeInitialize file_name */
int fd = open(file_name, O_RDONLY | O_CLOEXEC);
if (fd == -1) {
/* Handle Errorerror */
}
/* ... */
editor = getenv("EDITOR");
if (editor == NULL) {
/* Handle getenv() error */
}
if (system(editor) == -1) {
/* Handle Errorerror */
}
|
Risk Assessment
Failing to properly close files may allow unintended access to, or exhaustion of, system resources.
...
| 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]\] |
...