[libvirt] [PATCH RESEND] command: avoid fd leak on failure
Daniel Veillard
veillard at redhat.com
Thu Oct 13 09:03:05 UTC 2011
On Wed, Oct 12, 2011 at 05:59:40PM -0600, Eric Blake wrote:
> virCommandTransferFD promises that the fd is no longer owned by
> the caller. Normally, we want the fd to remain open until the
> child runs, but in error situations, we must close it earlier.
>
> * src/util/command.c (virCommandTransferFD): Close fd now if we
> can't track it to close later.
> (virCommandKeepFD): Adjust helper to make this easier.
> ---
>
> This leak can only happen on OOM or other extreme error conditions,
> but ought to be plugged. When I originally posted this:
> https://www.redhat.com/archives/libvir-list/2011-July/msg00674.html
> DV was worried that callers might abuse things and use fd
> even after this function closed it; but I proved to myself in
> writing a (non-working) v2 that all callers were already safe,
> and that this v1 was indeed a smaller solution.
Okidoc then :-)
> src/util/command.c | 17 +++++++++++------
> 1 files changed, 11 insertions(+), 6 deletions(-)
>
> diff --git a/src/util/command.c b/src/util/command.c
> index 699ba2d..c3ce361 100644
> --- a/src/util/command.c
> +++ b/src/util/command.c
> @@ -730,23 +730,26 @@ virCommandNewArgList(const char *binary, ...)
> * closing it. FD must not be one of the three standard streams. If
> * transfer is true, then fd will be closed in the parent after a call
> * to Run/RunAsync/Free, otherwise caller is still responsible for fd.
> + * Returns true if a transferring caller should close FD now, and
> + * false if the transfer is successfully recorded.
> */
> -static void
> +static bool
> virCommandKeepFD(virCommandPtr cmd, int fd, bool transfer)
> {
> if (!cmd)
> - return;
> + return fd > STDERR_FILENO;
>
> if (fd <= STDERR_FILENO || FD_SETSIZE <= fd) {
> if (!cmd->has_error)
> cmd->has_error = -1;
> VIR_DEBUG("cannot preserve %d", fd);
> - return;
> + return fd > STDERR_FILENO;
> }
>
> FD_SET(fd, &cmd->preserve);
> if (transfer)
> FD_SET(fd, &cmd->transfer);
> + return false;
> }
>
> /**
> @@ -761,7 +764,7 @@ virCommandKeepFD(virCommandPtr cmd, int fd, bool transfer)
> void
> virCommandPreserveFD(virCommandPtr cmd, int fd)
> {
> - return virCommandKeepFD(cmd, fd, false);
> + virCommandKeepFD(cmd, fd, false);
> }
>
> /**
> @@ -771,12 +774,14 @@ virCommandPreserveFD(virCommandPtr cmd, int fd)
> *
> * Transfer the specified file descriptor
> * to the child, instead of closing it on exec.
> - * Close the fd in the parent during Run/RunAsync/Free.
> + * The parent should no longer use fd, and the parent's copy will
> + * be automatically closed no later than during Run/RunAsync/Free.
> */
> void
> virCommandTransferFD(virCommandPtr cmd, int fd)
> {
> - return virCommandKeepFD(cmd, fd, true);
> + if (virCommandKeepFD(cmd, fd, true))
> + VIR_FORCE_CLOSE(fd);
> }
ACK,
Daniel
--
Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/
daniel at veillard.com | Rpmfind RPM search engine http://rpmfind.net/
http://veillard.com/ | virtualization library http://libvirt.org/
More information about the libvir-list
mailing list