Commit 5b0e9dd4 authored by Peter Lieven's avatar Peter Lieven Committed by Juan Quintela
Browse files

migration: catch unknown flag combinations in ram_load



this patch extends commit db80face by not only checking
for unknown flags, but also filtering out unknown flag
combinations.

Suggested-by: default avatarEric Blake <eblake@redhat.com>
Signed-off-by: default avatarPeter Lieven <pl@kamp.de>
Signed-off-by: default avatarJuan Quintela <quintela@redhat.com>
parent c54d1c06
Loading
Loading
Loading
Loading
+32 −30
Original line number Diff line number Diff line
@@ -1040,8 +1040,7 @@ void ram_handle_compressed(void *host, uint8_t ch, uint64_t size)

static int ram_load(QEMUFile *f, void *opaque, int version_id)
{
    ram_addr_t addr;
    int flags, ret = 0;
    int flags = 0, ret = 0;
    static uint64_t seq_iter;

    seq_iter++;
@@ -1050,21 +1049,24 @@ static int ram_load(QEMUFile *f, void *opaque, int version_id)
        ret = -EINVAL;
    }

    while (!ret) {
        addr = qemu_get_be64(f);
    while (!ret && !(flags & RAM_SAVE_FLAG_EOS)) {
        ram_addr_t addr, total_ram_bytes;
        void *host;
        uint8_t ch;

        addr = qemu_get_be64(f);
        flags = addr & ~TARGET_PAGE_MASK;
        addr &= TARGET_PAGE_MASK;

        if (flags & RAM_SAVE_FLAG_MEM_SIZE) {
        switch (flags & ~RAM_SAVE_FLAG_CONTINUE) {
        case RAM_SAVE_FLAG_MEM_SIZE:
            /* Synchronize RAM block list */
            char id[256];
            ram_addr_t length;
            ram_addr_t total_ram_bytes = addr;

            while (total_ram_bytes) {
            total_ram_bytes = addr;
            while (!ret && total_ram_bytes) {
                RAMBlock *block;
                uint8_t len;
                char id[256];
                ram_addr_t length;

                len = qemu_get_byte(f);
                qemu_get_buffer(f, (uint8_t *)id, len);
@@ -1088,16 +1090,11 @@ static int ram_load(QEMUFile *f, void *opaque, int version_id)
                                 "accept migration", id);
                    ret = -EINVAL;
                }
                if (ret) {
                    break;
                }

                total_ram_bytes -= length;
            }
        } else if (flags & RAM_SAVE_FLAG_COMPRESS) {
            void *host;
            uint8_t ch;

            break;
        case RAM_SAVE_FLAG_COMPRESS:
            host = host_from_stream_offset(f, addr, flags);
            if (!host) {
                error_report("Illegal RAM offset " RAM_ADDR_FMT, addr);
@@ -1107,9 +1104,8 @@ static int ram_load(QEMUFile *f, void *opaque, int version_id)

            ch = qemu_get_byte(f);
            ram_handle_compressed(host, ch, TARGET_PAGE_SIZE);
        } else if (flags & RAM_SAVE_FLAG_PAGE) {
            void *host;

            break;
        case RAM_SAVE_FLAG_PAGE:
            host = host_from_stream_offset(f, addr, flags);
            if (!host) {
                error_report("Illegal RAM offset " RAM_ADDR_FMT, addr);
@@ -1118,8 +1114,9 @@ static int ram_load(QEMUFile *f, void *opaque, int version_id)
            }

            qemu_get_buffer(f, host, TARGET_PAGE_SIZE);
        } else if (flags & RAM_SAVE_FLAG_XBZRLE) {
            void *host = host_from_stream_offset(f, addr, flags);
            break;
        case RAM_SAVE_FLAG_XBZRLE:
            host = host_from_stream_offset(f, addr, flags);
            if (!host) {
                error_report("Illegal RAM offset " RAM_ADDR_FMT, addr);
                ret = -EINVAL;
@@ -1132,18 +1129,23 @@ static int ram_load(QEMUFile *f, void *opaque, int version_id)
                ret = -EINVAL;
                break;
            }
        } else if (flags & RAM_SAVE_FLAG_HOOK) {
            ram_control_load_hook(f, flags);
        } else if (flags & RAM_SAVE_FLAG_EOS) {
            break;
        case RAM_SAVE_FLAG_EOS:
            /* normal exit */
            break;
        default:
            if (flags & RAM_SAVE_FLAG_HOOK) {
                ram_control_load_hook(f, flags);
            } else {
            error_report("Unknown migration flags: %#x", flags);
                error_report("Unknown combination of migration flags: %#x",
                             flags);
                ret = -EINVAL;
            break;
            }
        }
        if (!ret) {
            ret = qemu_file_get_error(f);
        }
    }

    DPRINTF("Completed load of VM with exit code %d seq iteration "
            "%" PRIu64 "\n", ret, seq_iter);