Skip to content

Commit

Permalink
lib-sieve: util: program-client-local: Made FD handling in child proc…
Browse files Browse the repository at this point in the history
…ess a little more robust.

Prevent mishaps with dup2(); e.g., when source and destination are identicial, which could happen.
  • Loading branch information
stephanbosch committed Feb 22, 2016
1 parent 7ba41a7 commit 6308045
Showing 1 changed file with 30 additions and 13 deletions.
43 changes: 30 additions & 13 deletions src/lib-sieve/util/program-client-local.c
Expand Up @@ -47,34 +47,51 @@ static void exec_child
i_fatal("open(/dev/null) failed: %m");
}

if ( dup2(in_fd, STDIN_FILENO) < 0 )
if ( in_fd != STDIN_FILENO &&
dup2(in_fd, STDIN_FILENO) < 0 )
i_fatal("dup2(stdin) failed: %m");
if ( dup2(out_fd, STDOUT_FILENO) < 0 )
if ( out_fd != STDOUT_FILENO &&
dup2(out_fd, STDOUT_FILENO) < 0 )
i_fatal("dup2(stdout) failed: %m");

if ( close(in_fd) < 0 )
if ( in_fd != STDIN_FILENO &&
close(in_fd) < 0 )
i_error("close(in_fd) failed: %m");
if ( (out_fd != in_fd) && close(out_fd) < 0 )
if ( out_fd != STDOUT_FILENO &&
(out_fd != in_fd) && close(out_fd) < 0 )
i_error("close(out_fd) failed: %m");

/* Drop stderr if requested */
if ( drop_stderr ) {
int err_fd = open("/dev/null", O_WRONLY);
if ( err_fd == -1 )
i_fatal("open(/dev/null) failed: %m");
if ( dup2(err_fd, STDERR_FILENO) < 0 )
i_fatal("dup2(stderr) failed: %m");
if ( close(err_fd) < 0 )
i_error("close(err_fd) failed: %m");
if ( err_fd != STDERR_FILENO ) {
if ( dup2(err_fd, STDERR_FILENO) < 0 )
i_fatal("dup2(stderr) failed: %m");
if ( close(err_fd) < 0 )
i_error("close(err_fd) failed: %m");
}
}

/* Setup extra fds */
if ( extra_fds != NULL ) {
for (; *extra_fds != -1; extra_fds += 2 ) {
if ( dup2(extra_fds[0], extra_fds[1]) < 0 )
i_fatal("dup2(extra_fd=%d) failed: %m", extra_fds[1]);
if ( close(extra_fds[0]) < 0 )
i_error("close(extra_fd=%d) failed: %m", extra_fds[1]);
int *efd;
for (efd = extra_fds; *efd != -1; efd += 2 ) {
i_assert(efd[1] != STDIN_FILENO);
i_assert(efd[1] != STDOUT_FILENO);
i_assert(efd[1] != STDERR_FILENO);
if ( efd[0] != efd[1] ) {
if ( dup2(efd[0], efd[1]) < 0 )
i_fatal("dup2(extra_fd=%d) failed: %m", efd[1]);
}
}
for (efd = extra_fds; *efd != -1; efd += 2 ) {
if ( efd[0] != efd[1] && efd[0] != STDIN_FILENO &&
efd[0] != STDOUT_FILENO && efd[0] != STDERR_FILENO) {
if ( close(efd[0]) < 0 )
i_error("close(extra_fd=%d) failed: %m", efd[1]);
}
}
}

Expand Down

0 comments on commit 6308045

Please sign in to comment.