[PATCH 0/5] qemu: backup: Memory handling fixes

See individual patches. Peter Krempa (5): qemuBackupBegin: Don't leak 'def' on early failures qemu: backup: Initialize 'store' source properly and just once qemuBackupDiskStarted: Fix improper dereference of array qemuBackupDiskDataCleanupOne: Don't exit early when the job has started qemuBackupDiskDataCleanupOne: Free 'incrementalBitmap' src/qemu/qemu_backup.c | 35 ++++++++++++++++------------------- 1 file changed, 16 insertions(+), 19 deletions(-) -- 2.26.2

The cleanup path expects that 'def' is assigned to 'priv->backup', but that's not the case for early failures. Add a check to stop overwriting of 'def' so that it can be freed. Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- src/qemu/qemu_backup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qemu/qemu_backup.c b/src/qemu/qemu_backup.c index db8b2d8ff9..531005425b 100644 --- a/src/qemu/qemu_backup.c +++ b/src/qemu/qemu_backup.c @@ -806,7 +806,7 @@ qemuBackupBegin(virDomainObjPtr vm, ignore_value(qemuDomainObjExitMonitor(priv->driver, vm)); } - if (ret < 0 && !job_started) + if (ret < 0 && !job_started && priv->backup) def = g_steal_pointer(&priv->backup); if (ret == 0) -- 2.26.2

Two functions called in sequence both initialized the virStorageSource backing 'store' leading to a memleak. Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- src/qemu/qemu_backup.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/qemu/qemu_backup.c b/src/qemu/qemu_backup.c index 531005425b..43fe8942ad 100644 --- a/src/qemu/qemu_backup.c +++ b/src/qemu/qemu_backup.c @@ -272,9 +272,6 @@ qemuBackupDiskPrepareDataOne(virDomainObjPtr vm, dd->backingStore = dd->terminator = virStorageSourceNew(); } - if (qemuDomainStorageFileInit(priv->driver, vm, dd->store, dd->domdisk->src) < 0) - return -1; - if (qemuDomainPrepareStorageSourceBlockdev(NULL, dd->store, priv, cfg) < 0) return -1; @@ -410,7 +407,7 @@ qemuBackupDiskPrepareOneStorage(virDomainObjPtr vm, return -1; } - if (qemuDomainStorageFileInit(priv->driver, vm, dd->store, NULL) < 0) + if (qemuDomainStorageFileInit(priv->driver, vm, dd->store, dd->domdisk->src) < 0) return -1; dd->initialized = true; -- 2.26.2

The code would repeatedly mark the first disk's blockjob as started rather than accessing all the blockjobs. Fix the dereferencing operator. Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- src/qemu/qemu_backup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qemu/qemu_backup.c b/src/qemu/qemu_backup.c index 43fe8942ad..ab9cd2689f 100644 --- a/src/qemu/qemu_backup.c +++ b/src/qemu/qemu_backup.c @@ -482,7 +482,7 @@ qemuBackupDiskStarted(virDomainObjPtr vm, for (i = 0; i < ndd; i++) { dd[i].started = true; dd[i].backupdisk->state = VIR_DOMAIN_BACKUP_DISK_STATE_RUNNING; - qemuBlockJobStarted(dd->blockjob, vm); + qemuBlockJobStarted(dd[i].blockjob, vm); } } -- 2.26.2

Originally the function was cleaning up a failed job only but now there's other stuff that needs to be cleared too. Make only steps which clean up after a failed job depend on the 'started' field and execute the rest of the code always. This fixes a leak of the backup job tracking object and the blockdev-add helper data. Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- src/qemu/qemu_backup.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/src/qemu/qemu_backup.c b/src/qemu/qemu_backup.c index ab9cd2689f..3bd59402dc 100644 --- a/src/qemu/qemu_backup.c +++ b/src/qemu/qemu_backup.c @@ -124,26 +124,25 @@ qemuBackupDiskDataCleanupOne(virDomainObjPtr vm, { qemuDomainObjPrivatePtr priv = vm->privateData; - if (dd->started) - return; + if (!dd->started) { + if (dd->added) { + qemuDomainObjEnterMonitor(priv->driver, vm); + qemuBlockStorageSourceAttachRollback(priv->mon, dd->crdata->srcdata[0]); + ignore_value(qemuDomainObjExitMonitor(priv->driver, vm)); + } - if (dd->added) { - qemuDomainObjEnterMonitor(priv->driver, vm); - qemuBlockStorageSourceAttachRollback(priv->mon, dd->crdata->srcdata[0]); - ignore_value(qemuDomainObjExitMonitor(priv->driver, vm)); - } + if (dd->created) { + if (virStorageFileUnlink(dd->store) < 0) + VIR_WARN("Unable to remove just-created %s", NULLSTR(dd->store->path)); + } - if (dd->created) { - if (virStorageFileUnlink(dd->store) < 0) - VIR_WARN("Unable to remove just-created %s", NULLSTR(dd->store->path)); + if (dd->labelled) + qemuDomainStorageSourceAccessRevoke(priv->driver, vm, dd->store); } if (dd->initialized) virStorageFileDeinit(dd->store); - if (dd->labelled) - qemuDomainStorageSourceAccessRevoke(priv->driver, vm, dd->store); - if (dd->blockjob) qemuBlockJobStartupFinalize(vm, dd->blockjob); -- 2.26.2

The bitmap name used for the incremental backup would be leaked otherwise. Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- src/qemu/qemu_backup.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/qemu/qemu_backup.c b/src/qemu/qemu_backup.c index 3bd59402dc..8dc9d2504d 100644 --- a/src/qemu/qemu_backup.c +++ b/src/qemu/qemu_backup.c @@ -148,6 +148,7 @@ qemuBackupDiskDataCleanupOne(virDomainObjPtr vm, qemuBlockStorageSourceChainDataFree(dd->crdata); virObjectUnref(dd->terminator); + g_free(dd->incrementalBitmap); } -- 2.26.2

On a Tuesday in 2020, Peter Krempa wrote:
See individual patches.
Peter Krempa (5): qemuBackupBegin: Don't leak 'def' on early failures qemu: backup: Initialize 'store' source properly and just once qemuBackupDiskStarted: Fix improper dereference of array qemuBackupDiskDataCleanupOne: Don't exit early when the job has started qemuBackupDiskDataCleanupOne: Free 'incrementalBitmap'
src/qemu/qemu_backup.c | 35 ++++++++++++++++------------------- 1 file changed, 16 insertions(+), 19 deletions(-)
Reviewed-by: Ján Tomko <jtomko@redhat.com> Jano
participants (2)
-
Ján Tomko
-
Peter Krempa