Skip to content

Commit c956562

Browse files
authored
Merge pull request #282 from blackgnezdo/wip/T266
cbits: Ensure that fork pipe doesn't shadow std fds
2 parents 484286a + 50ef0a3 commit c956562

File tree

1 file changed

+36
-1
lines changed

1 file changed

+36
-1
lines changed

cbits/posix/fork_exec.c

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ setup_std_handle_fork(int fd,
6464
{
6565
switch (b->behavior) {
6666
case STD_HANDLE_CLOSE:
67-
if (close(fd) == -1) {
67+
if (close(fd) == -1 && errno != EBADF) {
6868
child_failed(pipe, "close");
6969
}
7070
return 0;
@@ -101,6 +101,31 @@ setup_std_handle_fork(int fd,
101101
}
102102
}
103103

104+
/* We must ensure that the fork communications pipe does not inhabit fds 0
105+
* through 2 since we will need to manipulate these fds in
106+
* setup_std_handle_fork while keeping the pipe available so that it can report
107+
* errors. See #266.
108+
*/
109+
int unshadow_pipe_fd(int fd, char **failed_doing) {
110+
int i = 0;
111+
int fds[3] = {0};
112+
for (i = 0; fd < 3 && i < 3; ++i) {
113+
fds[i] = fd;
114+
fd = dup(fd);
115+
if (fd == -1) {
116+
*failed_doing = "dup(unshadow)";
117+
return -1;
118+
}
119+
}
120+
for (int j = 0; j < i; ++j) {
121+
if (close(fds[j]) == -1) {
122+
*failed_doing = "close(unshadow)";
123+
return -1;
124+
}
125+
}
126+
return fd;
127+
}
128+
104129
/* Try spawning with fork. */
105130
ProcHandle
106131
do_spawn_fork (char *const args[],
@@ -119,6 +144,16 @@ do_spawn_fork (char *const args[],
119144
return -1;
120145
}
121146

147+
// Ensure that the pipe fds don't shadow stdin/stdout/stderr
148+
forkCommunicationFds[0] = unshadow_pipe_fd(forkCommunicationFds[0], failed_doing);
149+
if (forkCommunicationFds[0] == -1) {
150+
return -1;
151+
}
152+
forkCommunicationFds[1] = unshadow_pipe_fd(forkCommunicationFds[1], failed_doing);
153+
if (forkCommunicationFds[1] == -1) {
154+
return -1;
155+
}
156+
122157
// Block signals with Haskell handlers. The danger here is that
123158
// with the threaded RTS, a signal arrives in the child process,
124159
// the RTS writes the signal information into the pipe (which is

0 commit comments

Comments
 (0)