From 5bf81c8d63db0216a4d29dc87f9ce530bb791dd1 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Thu, 3 Apr 2014 19:50:31 +0300 Subject: vmstate: add VMS_MUST_EXIST Can be used to verify a required field exists or validate state in some other way. Signed-off-by: Michael S. Tsirkin Reviewed-by: Dr. David Alan Gilbert Signed-off-by: Juan Quintela --- include/migration/vmstate.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include') diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h index e7e1705..de970ab 100644 --- a/include/migration/vmstate.h +++ b/include/migration/vmstate.h @@ -100,6 +100,7 @@ enum VMStateFlags { VMS_MULTIPLY = 0x200, /* multiply "size" field by field_size */ VMS_VARRAY_UINT8 = 0x400, /* Array with size in uint8_t field*/ VMS_VARRAY_UINT32 = 0x800, /* Array with size in uint32_t field*/ + VMS_MUST_EXIST = 0x1000, /* Field must exist in input */ }; typedef struct { -- cgit v1.1 From 4082f0889ba04678fc14816c53e1b9251ea9207e Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Thu, 3 Apr 2014 19:50:35 +0300 Subject: vmstate: add VMSTATE_VALIDATE Validate state using VMS_ARRAY with num = 0 and VMS_MUST_EXIST Signed-off-by: Michael S. Tsirkin Signed-off-by: Juan Quintela --- include/migration/vmstate.h | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'include') diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h index de970ab..5b71370 100644 --- a/include/migration/vmstate.h +++ b/include/migration/vmstate.h @@ -204,6 +204,14 @@ extern const VMStateInfo vmstate_info_bitmap; .offset = vmstate_offset_value(_state, _field, _type), \ } +/* Validate state using a boolean predicate. */ +#define VMSTATE_VALIDATE(_name, _test) { \ + .name = (_name), \ + .field_exists = (_test), \ + .flags = VMS_ARRAY | VMS_MUST_EXIST, \ + .num = 0, /* 0 elements: no data, only run _test */ \ +} + #define VMSTATE_POINTER(_field, _state, _version, _info, _type) { \ .name = (stringify(_field)), \ .version_id = (_version), \ -- cgit v1.1 From 71f7fe48e10a8437c9d42d859389f37157f59980 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Thu, 3 Apr 2014 19:50:39 +0300 Subject: virtio-net: fix buffer overflow on invalid state load CVE-2013-4148 QEMU 1.0 integer conversion in virtio_net_load()@hw/net/virtio-net.c Deals with loading a corrupted savevm image. > n->mac_table.in_use = qemu_get_be32(f); in_use is int so it can get negative when assigned 32bit unsigned value. > /* MAC_TABLE_ENTRIES may be different from the saved image */ > if (n->mac_table.in_use <= MAC_TABLE_ENTRIES) { passing this check ^^^ > qemu_get_buffer(f, n->mac_table.macs, > n->mac_table.in_use * ETH_ALEN); with good in_use value, "n->mac_table.in_use * ETH_ALEN" can get positive and bigger than mac_table.macs. For example 0x81000000 satisfies this condition when ETH_ALEN is 6. Fix it by making the value unsigned. For consistency, change first_multi as well. Note: all call sites were audited to confirm that making them unsigned didn't cause any issues: it turns out we actually never do math on them, so it's easy to validate because both values are always <= MAC_TABLE_ENTRIES. Reviewed-by: Michael Roth Signed-off-by: Michael S. Tsirkin Reviewed-by: Laszlo Ersek Signed-off-by: Juan Quintela --- include/hw/virtio/virtio-net.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/hw/virtio/virtio-net.h b/include/hw/virtio/virtio-net.h index df60f16..4b32440 100644 --- a/include/hw/virtio/virtio-net.h +++ b/include/hw/virtio/virtio-net.h @@ -176,8 +176,8 @@ typedef struct VirtIONet { uint8_t nobcast; uint8_t vhost_started; struct { - int in_use; - int first_multi; + uint32_t in_use; + uint32_t first_multi; uint8_t multi_overflow; uint8_t uni_overflow; uint8_t *macs; -- cgit v1.1 From 3476436a44c29725efef0cabf5b3ea4e70054d57 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Thu, 3 Apr 2014 19:52:21 +0300 Subject: vmstate: s/VMSTATE_INT32_LE/VMSTATE_INT32_POSITIVE_LE/ As the macro verifies the value is positive, rename it to make the function clearer. Signed-off-by: Michael S. Tsirkin Signed-off-by: Juan Quintela --- include/migration/vmstate.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h index 5b71370..7e45048 100644 --- a/include/migration/vmstate.h +++ b/include/migration/vmstate.h @@ -601,7 +601,7 @@ extern const VMStateInfo vmstate_info_bitmap; #define VMSTATE_UINT64_EQUAL(_f, _s) \ VMSTATE_UINT64_EQUAL_V(_f, _s, 0) -#define VMSTATE_INT32_LE(_f, _s) \ +#define VMSTATE_INT32_POSITIVE_LE(_f, _s) \ VMSTATE_SINGLE(_f, _s, 0, vmstate_info_int32_le, int32_t) #define VMSTATE_UINT8_TEST(_f, _s, _t) \ -- cgit v1.1 From 548f52ea06951c20f0b91cae6cde0512ec073c83 Mon Sep 17 00:00:00 2001 From: "Dr. David Alan Gilbert" Date: Tue, 8 Apr 2014 15:29:37 +0100 Subject: Make qemu_peek_buffer loop until it gets it's data Make qemu_peek_buffer repeatedly call fill_buffer until it gets all the data it requires, or until there is an error. At the moment, qemu_peek_buffer will try one qemu_fill_buffer if there isn't enough data waiting, however the kernel is entitled to return just a few bytes, and still leave qemu_peek_buffer with less bytes than it needed. I've seen this fail in a dev world, and I think it could theoretically fail in the peeking of the subsection headers in the current world. Comment qemu_peek_byte to point out it's not guaranteed to work for non-continuous peeks Signed-off-by: Dr. David Alan Gilbert Reviewed-by: ChenLiang Signed-off-by: Juan Quintela --- include/migration/qemu-file.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'include') diff --git a/include/migration/qemu-file.h b/include/migration/qemu-file.h index a191fb6..c90f529 100644 --- a/include/migration/qemu-file.h +++ b/include/migration/qemu-file.h @@ -123,6 +123,11 @@ void qemu_put_be32(QEMUFile *f, unsigned int v); void qemu_put_be64(QEMUFile *f, uint64_t v); int qemu_peek_buffer(QEMUFile *f, uint8_t *buf, int size, size_t offset); int qemu_get_buffer(QEMUFile *f, uint8_t *buf, int size); +/* + * Note that you can only peek continuous bytes from where the current pointer + * is; you aren't guaranteed to be able to peak to +n bytes unless you've + * previously peeked +n-1. + */ int qemu_peek_byte(QEMUFile *f, int offset); int qemu_get_byte(QEMUFile *f); void qemu_file_skip(QEMUFile *f, int size); -- cgit v1.1 From 0d6ab3ab9149767eba192ec5ad659fd34e55a291 Mon Sep 17 00:00:00 2001 From: "Dr. David Alan Gilbert" Date: Wed, 19 Mar 2014 18:32:30 +0000 Subject: Provide init function for ram migration Provide ram_mig_init (like blk_mig_init) for vl.c to initialise stuff to do with ram migration (currently in arch_init.c). Signed-off-by: Dr. David Alan Gilbert Reviewed-by: Gonglei Reviewed-by: Markus Armbruster Signed-off-by: Juan Quintela --- include/migration/migration.h | 2 -- include/sysemu/arch_init.h | 1 + 2 files changed, 1 insertion(+), 2 deletions(-) (limited to 'include') diff --git a/include/migration/migration.h b/include/migration/migration.h index 3e1e6c7..31fbf17 100644 --- a/include/migration/migration.h +++ b/include/migration/migration.h @@ -113,8 +113,6 @@ void free_xbzrle_decoded_buf(void); void acct_update_position(QEMUFile *f, size_t size, bool zero); -extern SaveVMHandlers savevm_ram_handlers; - uint64_t dup_mig_bytes_transferred(void); uint64_t dup_mig_pages_transferred(void); uint64_t skipped_mig_bytes_transferred(void); diff --git a/include/sysemu/arch_init.h b/include/sysemu/arch_init.h index be71bca..182d48d 100644 --- a/include/sysemu/arch_init.h +++ b/include/sysemu/arch_init.h @@ -29,6 +29,7 @@ extern const uint32_t arch_type; void select_soundhw(const char *optarg); void do_acpitable_option(const QemuOpts *opts); void do_smbios_option(QemuOpts *opts); +void ram_mig_init(void); void cpudef_init(void); void audio_init(void); int tcg_available(void); -- cgit v1.1 From 58570ed894631904bcdbcd1e8b34479cebe2aae9 Mon Sep 17 00:00:00 2001 From: ChenLiang Date: Fri, 4 Apr 2014 17:57:55 +0800 Subject: migration: expose the bitmap_sync_count to the end expose the count that logs the times of updating the dirty bitmap to end user. Signed-off-by: ChenLiang Signed-off-by: Gonglei Reviewed-by: Eric Blake Signed-off-by: Juan Quintela --- include/migration/migration.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include') diff --git a/include/migration/migration.h b/include/migration/migration.h index 31fbf17..8d88c7d 100644 --- a/include/migration/migration.h +++ b/include/migration/migration.h @@ -61,6 +61,7 @@ struct MigrationState bool enabled_capabilities[MIGRATION_CAPABILITY_MAX]; int64_t xbzrle_cache_size; int64_t setup_time; + int64_t dirty_sync_count; }; void process_incoming_migration(QEMUFile *f); -- cgit v1.1 From 8bc3923343e91902ca541112b3bdb5448f8d288e Mon Sep 17 00:00:00 2001 From: ChenLiang Date: Fri, 4 Apr 2014 17:57:56 +0800 Subject: migration: expose xbzrle cache miss rate expose xbzrle cache miss rate Signed-off-by: ChenLiang Signed-off-by: Gonglei Reviewed-by: Eric Blake Signed-off-by: Juan Quintela --- include/migration/migration.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include') diff --git a/include/migration/migration.h b/include/migration/migration.h index 8d88c7d..3cb5ba8 100644 --- a/include/migration/migration.h +++ b/include/migration/migration.h @@ -124,6 +124,7 @@ uint64_t xbzrle_mig_bytes_transferred(void); uint64_t xbzrle_mig_pages_transferred(void); uint64_t xbzrle_mig_pages_overflow(void); uint64_t xbzrle_mig_pages_cache_miss(void); +double xbzrle_mig_cache_miss_rate(void); void ram_handle_compressed(void *host, uint8_t ch, uint64_t size); -- cgit v1.1