Commit 8cc0749a authored by Rusty Russell's avatar Rusty Russell

pipecmd: don't close stderr/stdout/stdin in parent when &pipecmd_preserve

This was reported and fixed by @m-schmoock for stderr, but I decided to
rework to make it clearer and cover the other cases:

	https://github.com/ElementsProject/lightning/pull/2321/commits/67dad01549f876e5e620eeffe2f1e78c35bd0f03Signed-off-by: default avatarRusty Russell <rusty@rustcorp.com.au>
parent e16fc94b
...@@ -47,68 +47,76 @@ pid_t pipecmdarr(int *fd_tochild, int *fd_fromchild, int *fd_errfromchild, ...@@ -47,68 +47,76 @@ pid_t pipecmdarr(int *fd_tochild, int *fd_fromchild, int *fd_errfromchild,
char *const *arr) char *const *arr)
{ {
int tochild[2], fromchild[2], errfromchild[2], execfail[2]; int tochild[2], fromchild[2], errfromchild[2], execfail[2];
/* fds for parent to close */
int par_close[4], num_par_close = 0;
/* fds for child to close */
int child_close[4], num_child_close = 0;
pid_t childpid; pid_t childpid;
int err; int err;
if (fd_tochild) { if (fd_tochild) {
if (fd_tochild == &pipecmd_preserve) { if (fd_tochild == &pipecmd_preserve) {
tochild[0] = STDIN_FILENO; tochild[0] = STDIN_FILENO;
fd_tochild = NULL; } else if (pipe(tochild) == 0) {
} else if (pipe(tochild) != 0) par_close[num_par_close++] = tochild[0];
child_close[num_child_close++] = tochild[1];
} else
goto fail; goto fail;
} else { } else {
tochild[0] = open("/dev/null", O_RDONLY); tochild[0] = open("/dev/null", O_RDONLY);
if (tochild[0] < 0) if (tochild[0] < 0)
goto fail; goto fail;
par_close[num_par_close++] = tochild[0];
} }
if (fd_fromchild) { if (fd_fromchild) {
if (fd_fromchild == &pipecmd_preserve) { if (fd_fromchild == &pipecmd_preserve) {
fromchild[1] = STDOUT_FILENO; fromchild[1] = STDOUT_FILENO;
fd_fromchild = NULL; } else if (pipe(fromchild) == 0) {
} else if (pipe(fromchild) != 0) par_close[num_par_close++] = fromchild[1];
goto close_tochild_fail; child_close[num_child_close++] = fromchild[0];
} else
goto fail;
} else { } else {
fromchild[1] = open("/dev/null", O_WRONLY); fromchild[1] = open("/dev/null", O_WRONLY);
if (fromchild[1] < 0) if (fromchild[1] < 0)
goto close_tochild_fail; goto fail;
par_close[num_par_close++] = fromchild[1];
} }
if (fd_errfromchild) { if (fd_errfromchild) {
if (fd_errfromchild == &pipecmd_preserve) { if (fd_errfromchild == &pipecmd_preserve) {
errfromchild[1] = STDERR_FILENO; errfromchild[1] = STDERR_FILENO;
fd_errfromchild = NULL;
} else if (fd_errfromchild == fd_fromchild) { } else if (fd_errfromchild == fd_fromchild) {
errfromchild[0] = fromchild[0]; errfromchild[0] = fromchild[0];
errfromchild[1] = fromchild[1]; errfromchild[1] = fromchild[1];
} else { } else if (pipe(errfromchild) == 0) {
if (pipe(errfromchild) != 0) par_close[num_par_close++] = errfromchild[1];
goto close_fromchild_fail; child_close[num_child_close++] = errfromchild[0];
} } else
goto fail;
} else { } else {
errfromchild[1] = open("/dev/null", O_WRONLY); errfromchild[1] = open("/dev/null", O_WRONLY);
if (errfromchild[1] < 0) if (errfromchild[1] < 0)
goto close_fromchild_fail; goto fail;
par_close[num_par_close++] = errfromchild[1];
} }
if (pipe(execfail) != 0) if (pipe(execfail) != 0)
goto close_errfromchild_fail; goto fail;
par_close[num_par_close++] = execfail[1];
child_close[num_child_close++] = execfail[0];
if (fcntl(execfail[1], F_SETFD, fcntl(execfail[1], F_GETFD) if (fcntl(execfail[1], F_SETFD, fcntl(execfail[1], F_GETFD)
| FD_CLOEXEC) < 0) | FD_CLOEXEC) < 0)
goto close_execfail_fail; goto fail;
childpid = fork(); childpid = fork();
if (childpid < 0) if (childpid < 0)
goto close_execfail_fail; goto fail;
if (childpid == 0) { if (childpid == 0) {
if (fd_tochild) for (int i = 0; i < num_child_close; i++)
close(tochild[1]); close(child_close[i]);
if (fd_fromchild)
close(fromchild[0]);
if (fd_errfromchild && fd_errfromchild != fd_fromchild)
close(errfromchild[0]);
close(execfail[0]);
// Child runs command. // Child runs command.
if (tochild[0] != STDIN_FILENO) { if (tochild[0] != STDIN_FILENO) {
...@@ -140,10 +148,9 @@ pid_t pipecmdarr(int *fd_tochild, int *fd_fromchild, int *fd_errfromchild, ...@@ -140,10 +148,9 @@ pid_t pipecmdarr(int *fd_tochild, int *fd_fromchild, int *fd_errfromchild,
exit(127); exit(127);
} }
close(tochild[0]); for (int i = 0; i < num_par_close; i++)
close(fromchild[1]); close(par_close[i]);
close(errfromchild[1]);
close(execfail[1]);
/* Child will close this without writing on successful exec. */ /* Child will close this without writing on successful exec. */
if (read(execfail[0], &err, sizeof(err)) == sizeof(err)) { if (read(execfail[0], &err, sizeof(err)) == sizeof(err)) {
close(execfail[0]); close(execfail[0]);
...@@ -152,30 +159,17 @@ pid_t pipecmdarr(int *fd_tochild, int *fd_fromchild, int *fd_errfromchild, ...@@ -152,30 +159,17 @@ pid_t pipecmdarr(int *fd_tochild, int *fd_fromchild, int *fd_errfromchild,
return -1; return -1;
} }
close(execfail[0]); close(execfail[0]);
if (fd_tochild) if (fd_tochild && fd_tochild != &pipecmd_preserve)
*fd_tochild = tochild[1]; *fd_tochild = tochild[1];
if (fd_fromchild) if (fd_fromchild && fd_fromchild != &pipecmd_preserve)
*fd_fromchild = fromchild[0]; *fd_fromchild = fromchild[0];
if (fd_errfromchild) if (fd_errfromchild && fd_errfromchild != &pipecmd_preserve)
*fd_errfromchild = errfromchild[0]; *fd_errfromchild = errfromchild[0];
return childpid; return childpid;
close_execfail_fail:
close_noerr(execfail[0]);
close_noerr(execfail[1]);
close_errfromchild_fail:
if (fd_errfromchild)
close_noerr(errfromchild[0]);
close_noerr(errfromchild[1]);
close_fromchild_fail:
if (fd_fromchild)
close_noerr(fromchild[0]);
close_noerr(fromchild[1]);
close_tochild_fail:
close_noerr(tochild[0]);
if (fd_tochild)
close_noerr(tochild[1]);
fail: fail:
for (int i = 0; i < num_par_close; i++)
close_noerr(par_close[i]);
return -1; return -1;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment