From dd204de80d65e1ef22e90d207a816b7ef6a2e548 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Tue, 19 Jan 2016 13:43:07 +1030 Subject: [PATCH] pipecmd: fix fd leak. Signed-off-by: Rusty Russell --- ccan/pipecmd/pipecmd.c | 2 ++ ccan/pipecmd/test/run-fdleak.c | 44 ++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 ccan/pipecmd/test/run-fdleak.c diff --git a/ccan/pipecmd/pipecmd.c b/ccan/pipecmd/pipecmd.c index 671d3919..c97fa312 100644 --- a/ccan/pipecmd/pipecmd.c +++ b/ccan/pipecmd/pipecmd.c @@ -101,10 +101,12 @@ pid_t pipecmdarr(int *fd_fromchild, int *fd_tochild, char *const *arr) close(execfail[1]); /* Child will close this without writing on successful exec. */ if (read(execfail[0], &err, sizeof(err)) == sizeof(err)) { + close(execfail[0]); waitpid(childpid, NULL, 0); errno = err; return -1; } + close(execfail[0]); if (fd_tochild) *fd_tochild = tochild[1]; if (fd_fromchild) diff --git a/ccan/pipecmd/test/run-fdleak.c b/ccan/pipecmd/test/run-fdleak.c new file mode 100644 index 00000000..9ab9d1bb --- /dev/null +++ b/ccan/pipecmd/test/run-fdleak.c @@ -0,0 +1,44 @@ +#include +/* Include the C files directly. */ +#include +#include +#include +#include +#include + +int main(int argc, char *argv[]) +{ + pid_t child; + int outfd, status; + char buf[5] = "test"; + + /* We call ourselves, to test pipe. */ + if (argc == 2) { + if (write(STDOUT_FILENO, buf, sizeof(buf)) != sizeof(buf)) + exit(1); + exit(0); + } + + /* This is how many tests you plan to run */ + plan_tests(13); + child = pipecmd(&outfd, NULL, argv[0], "out", NULL); + if (!ok1(child > 0)) + exit(1); + ok1(read(outfd, buf, sizeof(buf)) == sizeof(buf)); + ok1(memcmp(buf, "test", sizeof(buf)) == 0); + ok1(waitpid(child, &status, 0) == child); + ok1(WIFEXITED(status)); + ok1(WEXITSTATUS(status) == 0); + + /* No leaks! */ + ok1(close(outfd) == 0); + ok1(close(outfd) == -1 && errno == EBADF); + ok1(close(++outfd) == -1 && errno == EBADF); + ok1(close(++outfd) == -1 && errno == EBADF); + ok1(close(++outfd) == -1 && errno == EBADF); + ok1(close(++outfd) == -1 && errno == EBADF); + ok1(close(++outfd) == -1 && errno == EBADF); + + /* This exits depending on whether all tests passed */ + return exit_status(); +} -- 2.39.2