From: Peter Krempa <pkrempa@redhat.com> 'virCommand' requires that the error buffer is available while the process is running. In 'qemuMigrationSrcToLegacyFile' a stack'd variable for the buffer pointer is registered, and the command is started, but it may continue executing even after return to the caller 'qemuMigrationSrcToFile' where 'virCommandWait' is called and thus if the command generates stderr after that it can overwrite the stack variable. This happens since the function was split into multiple parts in c2518f7bc7dd4f8ab8655a12ec3a000e1eb5b232. Fix it by moving the error buffer to 'qemuMigrationSrcToFile'. It's used for a debug message so we can move it up. Fixes: c2518f7bc7dd4f8ab8655a12ec3a000e1eb5b232 Closes: https://gitlab.com/libvirt/libvirt/-/work_items/932 Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- src/qemu/qemu_migration.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index 76661de09a..5d4d8b5a32 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -7225,7 +7225,6 @@ qemuMigrationSrcToLegacyFile(virDomainObj *vm, qemuDomainObjPrivate *priv = vm->privateData; int ret = -1; int pipeFD[2] = { -1, -1 }; - char *errbuf = NULL; if (compressor && virPipe(pipeFD) < 0) return -1; @@ -7246,7 +7245,6 @@ qemuMigrationSrcToLegacyFile(virDomainObj *vm, } else { virCommandSetInputFD(compressor, pipeFD[0]); virCommandSetOutputFD(compressor, &fd); - virCommandSetErrorBuffer(compressor, &errbuf); virCommandDoAsyncIO(compressor); if (virSetCloseExec(pipeFD[1]) < 0) { virReportSystemError(errno, "%s", @@ -7269,11 +7267,6 @@ qemuMigrationSrcToLegacyFile(virDomainObj *vm, VIR_FORCE_CLOSE(pipeFD[0]); VIR_FORCE_CLOSE(pipeFD[1]); - if (errbuf) { - VIR_DEBUG("Compression binary stderr: %s", NULLSTR(errbuf)); - VIR_FREE(errbuf); - } - return ret; } @@ -7342,6 +7335,7 @@ qemuMigrationSrcToFile(virDomainObj *vm, int ret = -1; unsigned long saveMigBandwidth = priv->migMaxBandwidth; virErrorPtr orig_err = NULL; + g_autofree char *compressor_errbuf = NULL; if (qemuMigrationSetDBusVMState(vm) < 0) return -1; @@ -7367,10 +7361,12 @@ qemuMigrationSrcToFile(virDomainObj *vm, } if (migParams && - qemuMigrationParamsCapEnabled(migParams, QEMU_MIGRATION_CAP_MAPPED_RAM)) + qemuMigrationParamsCapEnabled(migParams, QEMU_MIGRATION_CAP_MAPPED_RAM)) { rc = qemuMigrationSrcToSparseFile(vm, path, fd, bypassCache, asyncJob); - else + } else { + virCommandSetErrorBuffer(compressor, &compressor_errbuf); rc = qemuMigrationSrcToLegacyFile(vm, *fd, compressor, asyncJob); + } if (rc < 0) goto cleanup; @@ -7397,6 +7393,9 @@ qemuMigrationSrcToFile(virDomainObj *vm, if (ret < 0 && !orig_err) virErrorPreserveLast(&orig_err); + if (compressor_errbuf) + VIR_DEBUG("Compression binary stderr: %s", compressor_errbuf); + /* Remove fdset passed to qemu and restore max migration bandwidth */ if (qemuDomainObjIsActive(vm)) { if (qemuDomainObjEnterMonitorAsync(vm, asyncJob) == 0) { -- 2.56.0