mirror of
https://github.com/qemu/qemu.git
synced 2026-04-24 07:02:58 +00:00
backends/tpm: Propagate vTPM error on migration failure
- When migration of a VM with encrypted vTPM fails on the
destination host, (e.g., due to a mismatch in secret values),
the error message displayed on the source host is generic and unhelpful.
- For example, a typical error looks like this:
"operation failed: job 'migration out' failed: Sibling indicated error 1.
operation failed: job 'migration in' failed: load of migration failed:
Input/output error"
- Such generic errors are logged using error_report(), which prints to
the console/monitor but does not make the detailed error accessible via
the QMP query-migrate command.
- This change, along with the set of changes of passing errp Error object
to the VM state loading functions, help in addressing the issue.
We use the post_load_errp hook of VMStateDescription to propagate errors
by setting Error **errp objects in case of failure in the TPM backend.
- It can then be retrieved using QMP command:
{"execute" : "query-migrate"}
Buglink: https://issues.redhat.com/browse/RHEL-82826
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
Reviewed-by: Fabiano Rosas <farosas@suse.de>
Signed-off-by: Arun Menon <armenon@redhat.com>
Tested-by: Fabiano Rosas <farosas@suse.de>
Reviewed-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Link: https://lore.kernel.org/r/20250918-propagate_tpm_error-v14-27-36f11a6fb9d3@redhat.com
Signed-off-by: Peter Xu <peterx@redhat.com>
This commit is contained in:
@@ -819,7 +819,8 @@ static int tpm_emulator_get_state_blobs(TPMEmulator *tpm_emu)
|
||||
static int tpm_emulator_set_state_blob(TPMEmulator *tpm_emu,
|
||||
uint32_t type,
|
||||
TPMSizedBuffer *tsb,
|
||||
uint32_t flags)
|
||||
uint32_t flags,
|
||||
Error **errp)
|
||||
{
|
||||
ssize_t n;
|
||||
ptm_setstate pss;
|
||||
@@ -838,17 +839,18 @@ static int tpm_emulator_set_state_blob(TPMEmulator *tpm_emu,
|
||||
/* write the header only */
|
||||
if (tpm_emulator_ctrlcmd(tpm_emu, CMD_SET_STATEBLOB, &pss,
|
||||
offsetof(ptm_setstate, u.req.data), 0, 0) < 0) {
|
||||
error_report("tpm-emulator: could not set state blob type %d : %s",
|
||||
type, strerror(errno));
|
||||
error_setg_errno(errp, errno,
|
||||
"tpm-emulator: could not set state blob type %d",
|
||||
type);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* now the body */
|
||||
n = qemu_chr_fe_write_all(&tpm_emu->ctrl_chr, tsb->buffer, tsb->size);
|
||||
if (n != tsb->size) {
|
||||
error_report("tpm-emulator: Writing the stateblob (type %d) "
|
||||
"failed; could not write %u bytes, but only %zd",
|
||||
type, tsb->size, n);
|
||||
error_setg(errp, "tpm-emulator: Writing the stateblob (type %d) "
|
||||
"failed; could not write %u bytes, but only %zd",
|
||||
type, tsb->size, n);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -856,17 +858,17 @@ static int tpm_emulator_set_state_blob(TPMEmulator *tpm_emu,
|
||||
n = qemu_chr_fe_read_all(&tpm_emu->ctrl_chr,
|
||||
(uint8_t *)&pss, sizeof(pss.u.resp));
|
||||
if (n != sizeof(pss.u.resp)) {
|
||||
error_report("tpm-emulator: Reading response from writing stateblob "
|
||||
"(type %d) failed; expected %zu bytes, got %zd", type,
|
||||
sizeof(pss.u.resp), n);
|
||||
error_setg(errp, "tpm-emulator: Reading response from writing "
|
||||
"stateblob (type %d) failed; expected %zu bytes, "
|
||||
"got %zd", type, sizeof(pss.u.resp), n);
|
||||
return -1;
|
||||
}
|
||||
|
||||
tpm_result = be32_to_cpu(pss.u.resp.tpm_result);
|
||||
if (tpm_result != 0) {
|
||||
error_report("tpm-emulator: Setting the stateblob (type %d) failed "
|
||||
"with a TPM error 0x%x %s", type, tpm_result,
|
||||
tpm_emulator_strerror(tpm_result));
|
||||
error_setg(errp, "tpm-emulator: Setting the stateblob (type %d) "
|
||||
"failed with a TPM error 0x%x %s", type, tpm_result,
|
||||
tpm_emulator_strerror(tpm_result));
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -880,7 +882,7 @@ static int tpm_emulator_set_state_blob(TPMEmulator *tpm_emu,
|
||||
*
|
||||
* Returns a negative errno code in case of error.
|
||||
*/
|
||||
static int tpm_emulator_set_state_blobs(TPMBackend *tb)
|
||||
static int tpm_emulator_set_state_blobs(TPMBackend *tb, Error **errp)
|
||||
{
|
||||
TPMEmulator *tpm_emu = TPM_EMULATOR(tb);
|
||||
TPMBlobBuffers *state_blobs = &tpm_emu->state_blobs;
|
||||
@@ -894,13 +896,13 @@ static int tpm_emulator_set_state_blobs(TPMBackend *tb)
|
||||
|
||||
if (tpm_emulator_set_state_blob(tpm_emu, PTM_BLOB_TYPE_PERMANENT,
|
||||
&state_blobs->permanent,
|
||||
state_blobs->permanent_flags) < 0 ||
|
||||
state_blobs->permanent_flags, errp) < 0 ||
|
||||
tpm_emulator_set_state_blob(tpm_emu, PTM_BLOB_TYPE_VOLATILE,
|
||||
&state_blobs->volatil,
|
||||
state_blobs->volatil_flags) < 0 ||
|
||||
state_blobs->volatil_flags, errp) < 0 ||
|
||||
tpm_emulator_set_state_blob(tpm_emu, PTM_BLOB_TYPE_SAVESTATE,
|
||||
&state_blobs->savestate,
|
||||
state_blobs->savestate_flags) < 0) {
|
||||
state_blobs->savestate_flags, errp) < 0) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
@@ -948,12 +950,12 @@ static void tpm_emulator_vm_state_change(void *opaque, bool running,
|
||||
*
|
||||
* Returns negative errno codes in case of error.
|
||||
*/
|
||||
static int tpm_emulator_post_load(void *opaque, int version_id)
|
||||
static int tpm_emulator_post_load(void *opaque, int version_id, Error **errp)
|
||||
{
|
||||
TPMBackend *tb = opaque;
|
||||
int ret;
|
||||
|
||||
ret = tpm_emulator_set_state_blobs(tb);
|
||||
ret = tpm_emulator_set_state_blobs(tb, errp);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
@@ -969,7 +971,7 @@ static const VMStateDescription vmstate_tpm_emulator = {
|
||||
.name = "tpm-emulator",
|
||||
.version_id = 0,
|
||||
.pre_save = tpm_emulator_pre_save,
|
||||
.post_load = tpm_emulator_post_load,
|
||||
.post_load_errp = tpm_emulator_post_load,
|
||||
.fields = (const VMStateField[]) {
|
||||
VMSTATE_UINT32(state_blobs.permanent_flags, TPMEmulator),
|
||||
VMSTATE_UINT32(state_blobs.permanent.size, TPMEmulator),
|
||||
|
||||
Reference in New Issue
Block a user