From 7e50ec0b5f727f3cbc99b2be9189e936857ce44e Mon Sep 17 00:00:00 2001 From: Christian Brauner Date: Fri, 16 Feb 2018 20:02:44 +0100 Subject: [PATCH] utils: fix lxc_p{close,open}() MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit If a file descriptor fd is opened by fdopen() and associated with a stream f will **not** have been dup()ed. This means that fclose(f) will also close the fd. So never call close(fd) after fdopen(fd) succeeded. This fixes a double close() Stéphane and I observed when debugging on aarch64 and armf. Signed-off-by: Christian Brauner --- src/lxc/utils.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/lxc/utils.c b/src/lxc/utils.c index a1fe7d4ec..afcbdf34a 100644 --- a/src/lxc/utils.c +++ b/src/lxc/utils.c @@ -509,10 +509,14 @@ struct lxc_popen_FILE *lxc_popen(const char *command) fp = malloc(sizeof(*fp)); if (!fp) goto on_error; + memset(fp, 0, sizeof(*fp)); fp->child_pid = child_pid; fp->pipe = pipe_fds[0]; + /* From now on, closing fp->f will also close fp->pipe. So only ever + * call fclose(fp->f). + */ fp->f = fdopen(pipe_fds[0], "r"); if (!fp->f) goto on_error; @@ -520,15 +524,22 @@ struct lxc_popen_FILE *lxc_popen(const char *command) return fp; on_error: - if (fp) - free(fp); - - if (pipe_fds[0] >= 0) + /* We can only close pipe_fds[0] if fdopen() didn't succeed or wasn't + * called yet. Otherwise the fd belongs to the file opened by fdopen() + * since it isn't dup()ed. + */ + if (fp && !fp->f && pipe_fds[0] >= 0) close(pipe_fds[0]); if (pipe_fds[1] >= 0) close(pipe_fds[1]); + if (fp && fp->f) + fclose(fp->f); + + if (fp) + free(fp); + return NULL; } @@ -544,7 +555,6 @@ int lxc_pclose(struct lxc_popen_FILE *fp) wait_pid = waitpid(fp->child_pid, &wstatus, 0); } while (wait_pid < 0 && errno == EINTR); - close(fp->pipe); fclose(fp->f); free(fp); -- 2.47.2