From: Christian Brauner Date: Fri, 16 Feb 2018 19:02:44 +0000 (+0100) Subject: utils: fix lxc_p{close,open}() X-Git-Tag: lxc-3.0.0.beta1~27^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7e50ec0b5f727f3cbc99b2be9189e936857ce44e;p=thirdparty%2Flxc.git utils: fix lxc_p{close,open}() 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 --- 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);