From: Peter Xu Date: Tue, 21 Oct 2025 22:04:05 +0000 (-0400) Subject: migration/cpr: Fix coverity report in cpr_exec_persist_state() X-Git-Tag: v10.2.0-rc1~22^2~28 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6a65fdee8a267436f3f18a35619c854bf255d8c1;p=thirdparty%2Fqemu.git migration/cpr: Fix coverity report in cpr_exec_persist_state() Per reported and analyzed by Peter: https://lore.kernel.org/r/CAFEAcA_mUQ2NeoguR5efrhw7XYGofnriWEA=+Dg+Ocvyam1wAw@mail.gmail.com mfd leak is a false positive, try to use a coverity annotation (which I didn't find manual myself, but still give it a shot). Fix the other one by capture error if setenv() failed. When at it, pass the error to the top (cpr_state_save()). Along the way, changing all retval to bool when errp is around. Resolves: Coverity CID 1641391 Resolves: Coverity CID 1641392 Fixes: efc6587313 ("migration: cpr-exec save and load") Reviewed-by: Fabiano Rosas Link: https://lore.kernel.org/r/20251021220407.2662288-3-peterx@redhat.com Signed-off-by: Peter Xu --- diff --git a/include/migration/cpr.h b/include/migration/cpr.h index a412d6663c..027cb98073 100644 --- a/include/migration/cpr.h +++ b/include/migration/cpr.h @@ -41,7 +41,7 @@ MigMode cpr_get_incoming_mode(void); void cpr_set_incoming_mode(MigMode mode); bool cpr_is_incoming(void); -int cpr_state_save(MigrationChannel *channel, Error **errp); +bool cpr_state_save(MigrationChannel *channel, Error **errp); int cpr_state_load(MigrationChannel *channel, Error **errp); void cpr_state_close(void); struct QIOChannel *cpr_state_ioc(void); @@ -56,7 +56,7 @@ QEMUFile *cpr_transfer_input(MigrationChannel *channel, Error **errp); void cpr_exec_init(void); QEMUFile *cpr_exec_output(Error **errp); QEMUFile *cpr_exec_input(Error **errp); -void cpr_exec_persist_state(QEMUFile *f); +bool cpr_exec_persist_state(QEMUFile *f, Error **errp); bool cpr_exec_has_state(void); void cpr_exec_unpersist_state(void); void cpr_exec_unpreserve_fds(void); diff --git a/migration/cpr-exec.c b/migration/cpr-exec.c index d57714bc5d..087ca94c87 100644 --- a/migration/cpr-exec.c +++ b/migration/cpr-exec.c @@ -40,16 +40,22 @@ static QEMUFile *qemu_file_new_fd_output(int fd, const char *name) return qemu_file_new_output(ioc); } -void cpr_exec_persist_state(QEMUFile *f) +bool cpr_exec_persist_state(QEMUFile *f, Error **errp) { QIOChannelFile *fioc = QIO_CHANNEL_FILE(qemu_file_get_ioc(f)); + /* coverity[leaked_storage] - mfd intentionally kept open across exec() */ int mfd = dup(fioc->fd); char val[16]; /* Remember mfd in environment for post-exec load */ qemu_clear_cloexec(mfd); snprintf(val, sizeof(val), "%d", mfd); - g_setenv(CPR_EXEC_STATE_NAME, val, 1); + if (!g_setenv(CPR_EXEC_STATE_NAME, val, 1)) { + error_setg(errp, "Setting env %s = %s failed", CPR_EXEC_STATE_NAME, val); + return false; + } + + return true; } static int cpr_exec_find_state(void) diff --git a/migration/cpr.c b/migration/cpr.c index 22dbac7c72..adee2a919a 100644 --- a/migration/cpr.c +++ b/migration/cpr.c @@ -176,7 +176,7 @@ bool cpr_is_incoming(void) return incoming_mode != MIG_MODE_NONE; } -int cpr_state_save(MigrationChannel *channel, Error **errp) +bool cpr_state_save(MigrationChannel *channel, Error **errp) { int ret; QEMUFile *f; @@ -190,10 +190,10 @@ int cpr_state_save(MigrationChannel *channel, Error **errp) } else if (mode == MIG_MODE_CPR_EXEC) { f = cpr_exec_output(errp); } else { - return 0; + return true; } if (!f) { - return -1; + return false; } qemu_put_be32(f, QEMU_CPR_FILE_MAGIC); @@ -202,11 +202,14 @@ int cpr_state_save(MigrationChannel *channel, Error **errp) ret = vmstate_save_state(f, &vmstate_cpr_state, &cpr_state, 0, errp); if (ret) { qemu_fclose(f); - return ret; + return false; } if (migrate_mode() == MIG_MODE_CPR_EXEC) { - cpr_exec_persist_state(f); + if (!cpr_exec_persist_state(f, errp)) { + qemu_fclose(f); + return false; + } } /* @@ -217,7 +220,7 @@ int cpr_state_save(MigrationChannel *channel, Error **errp) qio_channel_shutdown(qemu_file_get_ioc(f), QIO_CHANNEL_SHUTDOWN_WRITE, NULL); cpr_state_file = f; - return 0; + return true; } int cpr_state_load(MigrationChannel *channel, Error **errp) diff --git a/migration/migration.c b/migration/migration.c index a63b46bbef..c8a5712993 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -2301,7 +2301,7 @@ void qmp_migrate(const char *uri, bool has_channels, return; } - if (cpr_state_save(cpr_channel, &local_err)) { + if (!cpr_state_save(cpr_channel, &local_err)) { goto out; }