[PATCH V2 0/3] qemu: Improve opening and verifying save images

V2 of https://lists.libvirt.org/archives/list/devel@lists.libvirt.org/message/DATZ... Changes in V2: * Move unlinking corrupt save images from qemuSaveImageOpen to the only caller using that functionality * Add a function to read save image header * Correctly position file pointer of save image for QEMU Jim Fehlig (3): qemu: Move unlinking corrupt save image file to caller qemu: Decompose qemuSaveImageOpen qemu: Check for valid save image format when verifying image header src/qemu/qemu_driver.c | 46 ++++--- src/qemu/qemu_saveimage.c | 268 +++++++++++++++++++++++--------------- src/qemu/qemu_saveimage.h | 21 ++- src/qemu/qemu_snapshot.c | 9 +- 4 files changed, 207 insertions(+), 137 deletions(-) -- 2.43.0

qemuDomainObjRestore is the only caller of qemuSaveImageOpen that requests an unlink of a corrupted save image. Provide a function to check for a corrupt image and move unlinking it to qemuDomainObjRestore. Signed-off-by: Jim Fehlig <jfehlig@suse.com> --- src/qemu/qemu_driver.c | 23 ++++++++++----- src/qemu/qemu_saveimage.c | 59 +++++++++++++++++++++------------------ src/qemu/qemu_saveimage.h | 8 ++++-- src/qemu/qemu_snapshot.c | 3 +- 4 files changed, 55 insertions(+), 38 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index da714f1975..2e80ce7921 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -5777,7 +5777,7 @@ qemuDomainRestoreInternal(virConnectPtr conn, fd = qemuSaveImageOpen(driver, NULL, path, &def, &data, (flags & VIR_DOMAIN_SAVE_BYPASS_CACHE) != 0, - &wrapperFd, false, false); + &wrapperFd, false); if (fd < 0) goto cleanup; @@ -5912,7 +5912,7 @@ qemuDomainSaveImageGetXMLDesc(virConnectPtr conn, const char *path, virCheckFlags(VIR_DOMAIN_SAVE_IMAGE_XML_SECURE, NULL); fd = qemuSaveImageOpen(driver, NULL, path, &def, &data, - false, NULL, false, false); + false, NULL, false); if (fd < 0) goto cleanup; @@ -5949,7 +5949,7 @@ qemuDomainSaveImageDefineXML(virConnectPtr conn, const char *path, state = 0; fd = qemuSaveImageOpen(driver, NULL, path, &def, &data, - false, NULL, true, false); + false, NULL, true); if (fd < 0) goto cleanup; @@ -6030,7 +6030,7 @@ qemuDomainManagedSaveGetXMLDesc(virDomainPtr dom, unsigned int flags) } if ((fd = qemuSaveImageOpen(driver, priv->qemuCaps, path, &def, &data, - false, NULL, false, false)) < 0) + false, NULL, false)) < 0) goto cleanup; ret = qemuDomainDefFormatXML(driver, priv->qemuCaps, def, flags); @@ -6094,10 +6094,19 @@ qemuDomainObjRestore(virConnectPtr conn, virFileWrapperFd *wrapperFd = NULL; fd = qemuSaveImageOpen(driver, NULL, path, &def, &data, - bypass_cache, &wrapperFd, false, true); + bypass_cache, &wrapperFd, false); if (fd < 0) { - if (fd == -3) - ret = 1; + if (qemuSaveImageIsCorrupt(driver, path)) { + if (unlink(path) < 0) { + virReportSystemError(errno, + _("cannot remove corrupt file: %1$s"), + path); + ret = -1; + } else { + virResetLastError(); + ret = 1; + } + } goto cleanup; } diff --git a/src/qemu/qemu_saveimage.c b/src/qemu/qemu_saveimage.c index 69617e07eb..385ac8a649 100644 --- a/src/qemu/qemu_saveimage.c +++ b/src/qemu/qemu_saveimage.c @@ -520,6 +520,35 @@ qemuSaveImageGetCompressionProgram(const char *imageFormat, return -1; } +/** + * qemuSaveImageIsCorrupt: + * @driver: qemu driver data + * @path: path of the save image + * + * Returns true if the save image file identified by @path does not exist or + * has a corrupt header. Returns false otherwise. + */ + +bool +qemuSaveImageIsCorrupt(virQEMUDriver *driver, const char *path) +{ + g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver); + VIR_AUTOCLOSE fd = -1; + virQEMUSaveHeader header; + + if ((fd = qemuDomainOpenFile(cfg, NULL, path, O_RDONLY, NULL)) < 0) + return true; + + if (saferead(fd, &header, sizeof(header)) != sizeof(header)) + return true; + + if (memcmp(header.magic, QEMU_SAVE_MAGIC, sizeof(header.magic)) != 0 || + memcmp(header.magic, QEMU_SAVE_PARTIAL, sizeof(header.magic)) == 0) + return true; + + return false; +} + /** * qemuSaveImageOpen: @@ -531,11 +560,10 @@ qemuSaveImageGetCompressionProgram(const char *imageFormat, * @bypass_cache: bypass cache when opening the file * @wrapperFd: returns the file wrapper structure * @open_write: open the file for writing (for updates) - * @unlink_corrupt: remove the image file if it is corrupted * * Returns the opened fd of the save image file and fills the appropriate fields - * on success. On error returns -1 on most failures, -3 if corrupt image was - * unlinked (no error raised). + * on success. On error returns -1 on most failures, -3 if a corrupt image was + * detected. */ int qemuSaveImageOpen(virQEMUDriver *driver, @@ -545,8 +573,7 @@ qemuSaveImageOpen(virQEMUDriver *driver, virQEMUSaveData **ret_data, bool bypass_cache, virFileWrapperFd **wrapperFd, - bool open_write, - bool unlink_corrupt) + bool open_write) { g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver); VIR_AUTOCLOSE fd = -1; @@ -580,17 +607,6 @@ qemuSaveImageOpen(virQEMUDriver *driver, header = &data->header; if (saferead(fd, header, sizeof(*header)) != sizeof(*header)) { - if (unlink_corrupt) { - if (unlink(path) < 0) { - virReportSystemError(errno, - _("cannot remove corrupt file: %1$s"), - path); - return -1; - } else { - return -3; - } - } - virReportError(VIR_ERR_OPERATION_FAILED, "%s", _("failed to read qemu header")); return -1; @@ -598,17 +614,6 @@ qemuSaveImageOpen(virQEMUDriver *driver, if (memcmp(header->magic, QEMU_SAVE_MAGIC, sizeof(header->magic)) != 0) { if (memcmp(header->magic, QEMU_SAVE_PARTIAL, sizeof(header->magic)) == 0) { - if (unlink_corrupt) { - if (unlink(path) < 0) { - virReportSystemError(errno, - _("cannot remove corrupt file: %1$s"), - path); - return -1; - } else { - return -3; - } - } - virReportError(VIR_ERR_OPERATION_FAILED, "%s", _("save image is incomplete")); return -1; diff --git a/src/qemu/qemu_saveimage.h b/src/qemu/qemu_saveimage.h index 0e58dd14b6..dc49f8463f 100644 --- a/src/qemu/qemu_saveimage.h +++ b/src/qemu/qemu_saveimage.h @@ -69,6 +69,11 @@ qemuSaveImageStartVM(virConnectPtr conn, virDomainAsyncJob asyncJob) ATTRIBUTE_NONNULL(4) ATTRIBUTE_NONNULL(5) ATTRIBUTE_NONNULL(6); +bool +qemuSaveImageIsCorrupt(virQEMUDriver *driver, + const char *path) + ATTRIBUTE_NONNULL(2); + int qemuSaveImageOpen(virQEMUDriver *driver, virQEMUCaps *qemuCaps, @@ -77,8 +82,7 @@ qemuSaveImageOpen(virQEMUDriver *driver, virQEMUSaveData **ret_data, bool bypass_cache, virFileWrapperFd **wrapperFd, - bool open_write, - bool unlink_corrupt) + bool open_write) ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4); int diff --git a/src/qemu/qemu_snapshot.c b/src/qemu/qemu_snapshot.c index 5273348aeb..b9c3983472 100644 --- a/src/qemu/qemu_snapshot.c +++ b/src/qemu/qemu_snapshot.c @@ -2379,8 +2379,7 @@ qemuSnapshotRevertExternalPrepare(virDomainObj *vm, memdata->path = snapdef->memorysnapshotfile; memdata->fd = qemuSaveImageOpen(driver, NULL, memdata->path, &savedef, &memdata->data, - false, NULL, - false, false); + false, NULL, false); if (memdata->fd < 0) return -1; -- 2.43.0

Split the reading of libvirt's save image metadata from the opening of the fd that will be passed to QEMU. This allows improved error handling and provides more flexibility users of qemu_saveimage. Signed-off-by: Jim Fehlig <jfehlig@suse.com> --- src/qemu/qemu_driver.c | 31 +++--- src/qemu/qemu_saveimage.c | 207 +++++++++++++++++++++++--------------- src/qemu/qemu_saveimage.h | 13 ++- src/qemu/qemu_snapshot.c | 8 +- 4 files changed, 153 insertions(+), 106 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 2e80ce7921..f326937585 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -5775,7 +5775,10 @@ qemuDomainRestoreInternal(virConnectPtr conn, if (flags & VIR_DOMAIN_SAVE_RESET_NVRAM) reset_nvram = true; - fd = qemuSaveImageOpen(driver, NULL, path, &def, &data, + if (qemuSaveImageGetMetadata(driver, NULL, path, &def, &data) < 0) + goto cleanup; + + fd = qemuSaveImageOpen(driver, path, (flags & VIR_DOMAIN_SAVE_BYPASS_CACHE) != 0, &wrapperFd, false); if (fd < 0) @@ -5906,15 +5909,11 @@ qemuDomainSaveImageGetXMLDesc(virConnectPtr conn, const char *path, virQEMUDriver *driver = conn->privateData; char *ret = NULL; g_autoptr(virDomainDef) def = NULL; - int fd = -1; virQEMUSaveData *data = NULL; virCheckFlags(VIR_DOMAIN_SAVE_IMAGE_XML_SECURE, NULL); - fd = qemuSaveImageOpen(driver, NULL, path, &def, &data, - false, NULL, false); - - if (fd < 0) + if (qemuSaveImageGetMetadata(driver, NULL, path, &def, &data) < 0) goto cleanup; if (virDomainSaveImageGetXMLDescEnsureACL(conn, def) < 0) @@ -5924,7 +5923,6 @@ qemuDomainSaveImageGetXMLDesc(virConnectPtr conn, const char *path, cleanup: virQEMUSaveDataFree(data); - VIR_FORCE_CLOSE(fd); return ret; } @@ -5948,9 +5946,10 @@ qemuDomainSaveImageDefineXML(virConnectPtr conn, const char *path, else if (flags & VIR_DOMAIN_SAVE_PAUSED) state = 0; - fd = qemuSaveImageOpen(driver, NULL, path, &def, &data, - false, NULL, true); + if (qemuSaveImageGetMetadata(driver, NULL, path, &def, &data) < 0) + goto cleanup; + fd = qemuSaveImageOpen(driver, path, 0, NULL, false); if (fd < 0) goto cleanup; @@ -6007,7 +6006,6 @@ qemuDomainManagedSaveGetXMLDesc(virDomainPtr dom, unsigned int flags) g_autofree char *path = NULL; char *ret = NULL; g_autoptr(virDomainDef) def = NULL; - int fd = -1; virQEMUSaveData *data = NULL; qemuDomainObjPrivate *priv; @@ -6029,15 +6027,13 @@ qemuDomainManagedSaveGetXMLDesc(virDomainPtr dom, unsigned int flags) goto cleanup; } - if ((fd = qemuSaveImageOpen(driver, priv->qemuCaps, path, &def, &data, - false, NULL, false)) < 0) + if (qemuSaveImageGetMetadata(driver, priv->qemuCaps, path, &def, &data) < 0) goto cleanup; ret = qemuDomainDefFormatXML(driver, priv->qemuCaps, def, flags); cleanup: virQEMUSaveDataFree(data); - VIR_FORCE_CLOSE(fd); virDomainObjEndAPI(&vm); return ret; } @@ -6093,9 +6089,8 @@ qemuDomainObjRestore(virConnectPtr conn, virQEMUSaveData *data = NULL; virFileWrapperFd *wrapperFd = NULL; - fd = qemuSaveImageOpen(driver, NULL, path, &def, &data, - bypass_cache, &wrapperFd, false); - if (fd < 0) { + ret = qemuSaveImageGetMetadata(driver, NULL, path, &def, &data); + if (ret < 0) { if (qemuSaveImageIsCorrupt(driver, path)) { if (unlink(path) < 0) { virReportSystemError(errno, @@ -6110,6 +6105,10 @@ qemuDomainObjRestore(virConnectPtr conn, goto cleanup; } + fd = qemuSaveImageOpen(driver, path, bypass_cache, &wrapperFd, false); + if (fd < 0) + goto cleanup; + if (virHookPresent(VIR_HOOK_DRIVER_QEMU)) { int hookret; diff --git a/src/qemu/qemu_saveimage.c b/src/qemu/qemu_saveimage.c index 385ac8a649..8315171b78 100644 --- a/src/qemu/qemu_saveimage.c +++ b/src/qemu/qemu_saveimage.c @@ -249,6 +249,84 @@ qemuSaveImageGetCompressionCommand(virQEMUSaveFormat format) } +static int +qemuSaveImageReadHeader(int fd, virQEMUSaveData **ret_data) +{ + g_autoptr(virQEMUSaveData) data = NULL; + virQEMUSaveHeader *header; + size_t xml_len; + size_t cookie_len; + + data = g_new0(virQEMUSaveData, 1); + header = &data->header; + if (saferead(fd, header, sizeof(*header)) != sizeof(*header)) { + virReportError(VIR_ERR_OPERATION_FAILED, + "%s", _("failed to read qemu header")); + return -1; + } + + if (memcmp(header->magic, QEMU_SAVE_MAGIC, sizeof(header->magic)) != 0) { + if (memcmp(header->magic, QEMU_SAVE_PARTIAL, sizeof(header->magic)) == 0) { + virReportError(VIR_ERR_OPERATION_FAILED, "%s", + _("save image is incomplete")); + return -1; + } + + virReportError(VIR_ERR_OPERATION_FAILED, "%s", + _("image magic is incorrect")); + return -1; + } + + if (header->version > QEMU_SAVE_VERSION) { + /* convert endianness and try again */ + qemuSaveImageBswapHeader(header); + } + + if (header->version > QEMU_SAVE_VERSION) { + virReportError(VIR_ERR_OPERATION_FAILED, + _("image version is not supported (%1$d > %2$d)"), + header->version, QEMU_SAVE_VERSION); + return -1; + } + + if (header->data_len <= 0) { + virReportError(VIR_ERR_OPERATION_FAILED, + _("invalid header data length: %1$d"), header->data_len); + return -1; + } + + if (header->cookieOffset) + xml_len = header->cookieOffset; + else + xml_len = header->data_len; + + cookie_len = header->data_len - xml_len; + + data->xml = g_new0(char, xml_len); + + if (saferead(fd, data->xml, xml_len) != xml_len) { + virReportError(VIR_ERR_OPERATION_FAILED, + "%s", _("failed to read domain XML")); + return -1; + } + + if (cookie_len > 0) { + data->cookie = g_new0(char, cookie_len); + + if (saferead(fd, data->cookie, cookie_len) != cookie_len) { + virReportError(VIR_ERR_OPERATION_FAILED, "%s", + _("failed to read cookie")); + return -1; + } + } + + if (ret_data) + *ret_data = g_steal_pointer(&data); + + return 0; +} + + /** * qemuSaveImageDecompressionStart: * @data: data from memory state file @@ -520,6 +598,7 @@ qemuSaveImageGetCompressionProgram(const char *imageFormat, return -1; } + /** * qemuSaveImageIsCorrupt: * @driver: qemu driver data @@ -551,26 +630,61 @@ qemuSaveImageIsCorrupt(virQEMUDriver *driver, const char *path) /** - * qemuSaveImageOpen: + * qemuSaveImageGetMetadata: * @driver: qemu driver data * @qemuCaps: pointer to qemuCaps if the domain is running or NULL * @path: path of the save image * @ret_def: returns domain definition created from the XML stored in the image * @ret_data: returns structure filled with data from the image header + * + * Open the save image file, read libvirt's save image metadata, and populate + * the @ret_def and @ret_data structures. Returns 0 on success and -1 on failure. + */ +int +qemuSaveImageGetMetadata(virQEMUDriver *driver, + virQEMUCaps *qemuCaps, + const char *path, + virDomainDef **ret_def, + virQEMUSaveData **ret_data) +{ + g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver); + VIR_AUTOCLOSE fd = -1; + virQEMUSaveData *data; + g_autoptr(virDomainDef) def = NULL; + int rc; + + if ((fd = qemuDomainOpenFile(cfg, NULL, path, O_RDONLY, NULL)) < 0) + return -1; + + if ((rc = qemuSaveImageReadHeader(fd, ret_data)) < 0) + return rc; + + data = *ret_data; + /* Create a domain from this XML */ + if (!(def = virDomainDefParseString(data->xml, driver->xmlopt, qemuCaps, + VIR_DOMAIN_DEF_PARSE_INACTIVE | + VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE))) + return -1; + + *ret_def = g_steal_pointer(&def); + + return 0; +} + + +/** + * qemuSaveImageOpen: + * @driver: qemu driver data + * @path: path of the save image * @bypass_cache: bypass cache when opening the file * @wrapperFd: returns the file wrapper structure * @open_write: open the file for writing (for updates) * - * Returns the opened fd of the save image file and fills the appropriate fields - * on success. On error returns -1 on most failures, -3 if a corrupt image was - * detected. + * Returns the opened fd of the save image file on success, -1 on failure. */ int qemuSaveImageOpen(virQEMUDriver *driver, - virQEMUCaps *qemuCaps, const char *path, - virDomainDef **ret_def, - virQEMUSaveData **ret_data, bool bypass_cache, virFileWrapperFd **wrapperFd, bool open_write) @@ -578,12 +692,7 @@ qemuSaveImageOpen(virQEMUDriver *driver, g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver); VIR_AUTOCLOSE fd = -1; int ret = -1; - g_autoptr(virQEMUSaveData) data = NULL; - virQEMUSaveHeader *header; - g_autoptr(virDomainDef) def = NULL; int oflags = open_write ? O_RDWR : O_RDONLY; - size_t xml_len; - size_t cookie_len; if (bypass_cache) { int directFlag = virFileDirectFdFlag(); @@ -603,78 +712,10 @@ qemuSaveImageOpen(virQEMUDriver *driver, VIR_FILE_WRAPPER_BYPASS_CACHE))) return -1; - data = g_new0(virQEMUSaveData, 1); - - header = &data->header; - if (saferead(fd, header, sizeof(*header)) != sizeof(*header)) { - virReportError(VIR_ERR_OPERATION_FAILED, - "%s", _("failed to read qemu header")); + /* Read the header to position the file pointer for QEMU. Unfortunately we + * can't use lseek with virFileWrapperFD. */ + if (qemuSaveImageReadHeader(fd, NULL) < 0) return -1; - } - - if (memcmp(header->magic, QEMU_SAVE_MAGIC, sizeof(header->magic)) != 0) { - if (memcmp(header->magic, QEMU_SAVE_PARTIAL, sizeof(header->magic)) == 0) { - virReportError(VIR_ERR_OPERATION_FAILED, "%s", - _("save image is incomplete")); - return -1; - } - - virReportError(VIR_ERR_OPERATION_FAILED, "%s", - _("image magic is incorrect")); - return -1; - } - - if (header->version > QEMU_SAVE_VERSION) { - /* convert endianness and try again */ - qemuSaveImageBswapHeader(header); - } - - if (header->version > QEMU_SAVE_VERSION) { - virReportError(VIR_ERR_OPERATION_FAILED, - _("image version is not supported (%1$d > %2$d)"), - header->version, QEMU_SAVE_VERSION); - return -1; - } - - if (header->data_len <= 0) { - virReportError(VIR_ERR_OPERATION_FAILED, - _("invalid header data length: %1$d"), header->data_len); - return -1; - } - - if (header->cookieOffset) - xml_len = header->cookieOffset; - else - xml_len = header->data_len; - - cookie_len = header->data_len - xml_len; - - data->xml = g_new0(char, xml_len); - - if (saferead(fd, data->xml, xml_len) != xml_len) { - virReportError(VIR_ERR_OPERATION_FAILED, - "%s", _("failed to read domain XML")); - return -1; - } - - if (cookie_len > 0) { - data->cookie = g_new0(char, cookie_len); - - if (saferead(fd, data->cookie, cookie_len) != cookie_len) { - virReportError(VIR_ERR_OPERATION_FAILED, "%s", - _("failed to read cookie")); - return -1; - } - } - - /* Create a domain from this XML */ - if (!(def = virDomainDefParseString(data->xml, driver->xmlopt, qemuCaps, - VIR_DOMAIN_DEF_PARSE_INACTIVE | - VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE))) - return -1; - - *ret_def = g_steal_pointer(&def); - *ret_data = g_steal_pointer(&data); ret = fd; fd = -1; diff --git a/src/qemu/qemu_saveimage.h b/src/qemu/qemu_saveimage.h index dc49f8463f..53ae222467 100644 --- a/src/qemu/qemu_saveimage.h +++ b/src/qemu/qemu_saveimage.h @@ -74,16 +74,21 @@ qemuSaveImageIsCorrupt(virQEMUDriver *driver, const char *path) ATTRIBUTE_NONNULL(2); +int +qemuSaveImageGetMetadata(virQEMUDriver *driver, + virQEMUCaps *qemuCaps, + const char *path, + virDomainDef **ret_def, + virQEMUSaveData **ret_data) + ATTRIBUTE_NONNULL(4) ATTRIBUTE_NONNULL(5); + int qemuSaveImageOpen(virQEMUDriver *driver, - virQEMUCaps *qemuCaps, const char *path, - virDomainDef **ret_def, - virQEMUSaveData **ret_data, bool bypass_cache, virFileWrapperFd **wrapperFd, bool open_write) - ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4); + ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(4); int qemuSaveImageGetCompressionProgram(const char *imageFormat, diff --git a/src/qemu/qemu_snapshot.c b/src/qemu/qemu_snapshot.c index b9c3983472..7ce018b026 100644 --- a/src/qemu/qemu_snapshot.c +++ b/src/qemu/qemu_snapshot.c @@ -2377,10 +2377,12 @@ qemuSnapshotRevertExternalPrepare(virDomainObj *vm, g_autoptr(virDomainDef) savedef = NULL; memdata->path = snapdef->memorysnapshotfile; - memdata->fd = qemuSaveImageOpen(driver, NULL, memdata->path, - &savedef, &memdata->data, + if (qemuSaveImageGetMetadata(driver, NULL, memdata->path, &savedef, + &memdata->data) < 0) + return -1; + + memdata->fd = qemuSaveImageOpen(driver, memdata->path, false, NULL, false); - if (memdata->fd < 0) return -1; -- 2.43.0

When attempting to restore a saved image, the check for a valid save image format does not occur until the qemu process is about to be executed. Move the check earlier in the restore process, along with the other checks that verify a valid save image header. Signed-off-by: Jim Fehlig <jfehlig@suse.com> --- src/qemu/qemu_saveimage.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/qemu/qemu_saveimage.c b/src/qemu/qemu_saveimage.c index 8315171b78..5c889fee11 100644 --- a/src/qemu/qemu_saveimage.c +++ b/src/qemu/qemu_saveimage.c @@ -289,6 +289,12 @@ qemuSaveImageReadHeader(int fd, virQEMUSaveData **ret_data) return -1; } + if (header->format >= QEMU_SAVE_FORMAT_LAST) { + virReportError(VIR_ERR_OPERATION_FAILED, + _("unsupported save image format: %1$d"), header->format); + return -1; + } + if (header->data_len <= 0) { virReportError(VIR_ERR_OPERATION_FAILED, _("invalid header data length: %1$d"), header->data_len); -- 2.43.0

On 1/31/25 03:29, Jim Fehlig via Devel wrote:
V2 of https://lists.libvirt.org/archives/list/devel@lists.libvirt.org/message/DATZ...
Changes in V2: * Move unlinking corrupt save images from qemuSaveImageOpen to the only caller using that functionality * Add a function to read save image header * Correctly position file pointer of save image for QEMU
Jim Fehlig (3): qemu: Move unlinking corrupt save image file to caller qemu: Decompose qemuSaveImageOpen qemu: Check for valid save image format when verifying image header
src/qemu/qemu_driver.c | 46 ++++--- src/qemu/qemu_saveimage.c | 268 +++++++++++++++++++++++--------------- src/qemu/qemu_saveimage.h | 21 ++- src/qemu/qemu_snapshot.c | 9 +- 4 files changed, 207 insertions(+), 137 deletions(-)
Reviewed-by: Michal Privoznik <mprivozn@redhat.com> and merged. Michal
participants (2)
-
Jim Fehlig
-
Michal Prívozník