[libvirt] [PATCH] screenshot: don't unlink bogus file

Laine Stump laine at laine.org
Tue Aug 2 19:03:03 UTC 2011


On 08/02/2011 01:11 PM, Eric Blake wrote:
> The previous qemu patch could end up calling unlink(tmp) before
> tmp was the name of a valid file (unlinking a fileXXXXXX template
> instead), or calling unlink(tmp) twice on success (once here,
> and once at the end of the stream).  Meanwhile, vbox also suffered
> from the same leaked tmp file bug.
>

ACK.


> * src/qemu/qemu_driver.c (qemuDomainScreenshot): Don't unlink on
> success, or on invalid name.
> * src/vbox/vbox_tmpl.c (vboxDomainScreenshot): Don't leak temp file.
> ---
>
>> Meanwhile, I wonder if we have a bigger bug - that is, should
>> virFDStreamOpenInternal guarantee that the file is deleted when
>> requested, even on failure paths, so that callers need not do the
>> unlink()?  That is, on the success path, we end up unlink()ing the
>> same name twice, which is racy if the name is predictable (in the case
>> of qemuDomainScreenshot, the name is temporary and supposedly safe).
> I audited all callers, and there were only two that passed delete=true.
> Of those two, I found another bug (calling unlink() too soon).
>
> Additionally, remember that the reason we passed delete=true in the
> first place was due to libvirt_iohelper doing the unlink in a child
> process; where a race condition required that we not do the unlink in
> the parent.  But now that libvirt_iohelper receives its fd by
> inheritance, I think we can revert the delete parameter in the
> first place.  But that's invasive enough to delay to post-release.
>
> Meanwhile, I still think this is worth applying pre-release.
>
>   src/qemu/qemu_driver.c |    8 ++++----
>   src/vbox/vbox_tmpl.c   |    5 +++++
>   2 files changed, 9 insertions(+), 4 deletions(-)
>
> diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
> index 5e2c903..0297159 100644
> --- a/src/qemu/qemu_driver.c
> +++ b/src/qemu/qemu_driver.c
> @@ -2912,18 +2912,21 @@ qemuDomainScreenshot(virDomainPtr dom,
>       qemuDomainObjEnterMonitor(driver, vm);
>       if (qemuMonitorScreendump(priv->mon, tmp)<  0) {
>           qemuDomainObjExitMonitor(driver, vm);
> +        unlink(tmp);
>           goto endjob;
>       }
>       qemuDomainObjExitMonitor(driver, vm);
>
>       if (VIR_CLOSE(tmp_fd)<  0) {
>           virReportSystemError(errno, _("unable to close %s"), tmp);
> +        unlink(tmp);
>           goto endjob;
>       }
>
>       if (virFDStreamOpenFile(st, tmp, 0, 0, O_RDONLY, true)<  0) {
>           qemuReportError(VIR_ERR_OPERATION_FAILED, "%s",
>                           _("unable to open stream"));
> +        unlink(tmp);
>           goto endjob;
>       }
>
> @@ -2931,10 +2934,7 @@ qemuDomainScreenshot(virDomainPtr dom,
>
>   endjob:
>       VIR_FORCE_CLOSE(tmp_fd);
> -    if (tmp) {
> -        unlink(tmp);
> -        VIR_FREE(tmp);
> -    }
> +    VIR_FREE(tmp);
>
>       if (qemuDomainObjEndJob(driver, vm) == 0)
>           vm = NULL;
> diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c
> index a7d354e..66a0fe9 100644
> --- a/src/vbox/vbox_tmpl.c
> +++ b/src/vbox/vbox_tmpl.c
> @@ -8713,6 +8713,7 @@ vboxDomainScreenshot(virDomainPtr dom,
>                   if (NS_FAILED(rc) || !width || !height) {
>                       vboxError(VIR_ERR_OPERATION_FAILED, "%s",
>                                 _("unable to get screen resolution"));
> +                    unlink(tmp);
>                       goto endjob;
>                   }
>
> @@ -8723,6 +8724,7 @@ vboxDomainScreenshot(virDomainPtr dom,
>                   if (NS_FAILED(rc)) {
>                       vboxError(VIR_ERR_OPERATION_FAILED, "%s",
>                                 _("failed to take screenshot"));
> +                    unlink(tmp);
>                       goto endjob;
>                   }
>
> @@ -8730,17 +8732,20 @@ vboxDomainScreenshot(virDomainPtr dom,
>                                 screenDataSize)<  0) {
>                       virReportSystemError(errno, _("unable to write data "
>                                                     "to '%s'"), tmp);
> +                    unlink(tmp);
>                       goto endjob;
>                   }
>
>                   if (VIR_CLOSE(tmp_fd)<  0) {
>                       virReportSystemError(errno, _("unable to close %s"), tmp);
> +                    unlink(tmp);
>                       goto endjob;
>                   }
>
>                   if (virFDStreamOpenFile(st, tmp, 0, 0, O_RDONLY, true)<  0) {
>                       vboxError(VIR_ERR_OPERATION_FAILED, "%s",
>                                 _("unable to open stream"));
> +                    unlink(tmp);
>                       goto endjob;
>                   }
>




More information about the libvir-list mailing list