ssd0323: fix buffer overun on invalid state load
[qemu/qmp-unstable.git] / vmstate.c
blobdbb76665d92750d8ea4f313c3ceccfcdbaa2946d
1 #include "qemu-common.h"
2 #include "migration/migration.h"
3 #include "migration/qemu-file.h"
4 #include "migration/vmstate.h"
5 #include "qemu/bitops.h"
6 #include "trace.h"
8 static void vmstate_subsection_save(QEMUFile *f, const VMStateDescription *vmsd,
9 void *opaque);
10 static int vmstate_subsection_load(QEMUFile *f, const VMStateDescription *vmsd,
11 void *opaque);
13 static int vmstate_n_elems(void *opaque, VMStateField *field)
15 int n_elems = 1;
17 if (field->flags & VMS_ARRAY) {
18 n_elems = field->num;
19 } else if (field->flags & VMS_VARRAY_INT32) {
20 n_elems = *(int32_t *)(opaque+field->num_offset);
21 } else if (field->flags & VMS_VARRAY_UINT32) {
22 n_elems = *(uint32_t *)(opaque+field->num_offset);
23 } else if (field->flags & VMS_VARRAY_UINT16) {
24 n_elems = *(uint16_t *)(opaque+field->num_offset);
25 } else if (field->flags & VMS_VARRAY_UINT8) {
26 n_elems = *(uint8_t *)(opaque+field->num_offset);
29 return n_elems;
32 static int vmstate_size(void *opaque, VMStateField *field)
34 int size = field->size;
36 if (field->flags & VMS_VBUFFER) {
37 size = *(int32_t *)(opaque+field->size_offset);
38 if (field->flags & VMS_MULTIPLY) {
39 size *= field->size;
43 return size;
46 static void *vmstate_base_addr(void *opaque, VMStateField *field)
48 void *base_addr = opaque + field->offset;
50 if (field->flags & VMS_POINTER) {
51 base_addr = *(void **)base_addr + field->start;
54 return base_addr;
57 int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd,
58 void *opaque, int version_id)
60 VMStateField *field = vmsd->fields;
61 int ret;
63 if (version_id > vmsd->version_id) {
64 return -EINVAL;
66 if (version_id < vmsd->minimum_version_id_old) {
67 return -EINVAL;
69 if (version_id < vmsd->minimum_version_id) {
70 return vmsd->load_state_old(f, opaque, version_id);
72 if (vmsd->pre_load) {
73 int ret = vmsd->pre_load(opaque);
74 if (ret) {
75 return ret;
78 while (field->name) {
79 if ((field->field_exists &&
80 field->field_exists(opaque, version_id)) ||
81 (!field->field_exists &&
82 field->version_id <= version_id)) {
83 void *base_addr = vmstate_base_addr(opaque, field);
84 int i, n_elems = vmstate_n_elems(opaque, field);
85 int size = vmstate_size(opaque, field);
87 for (i = 0; i < n_elems; i++) {
88 void *addr = base_addr + size * i;
90 if (field->flags & VMS_ARRAY_OF_POINTER) {
91 addr = *(void **)addr;
93 if (field->flags & VMS_STRUCT) {
94 ret = vmstate_load_state(f, field->vmsd, addr,
95 field->vmsd->version_id);
96 } else {
97 ret = field->info->get(f, addr, size);
100 if (ret < 0) {
101 trace_vmstate_load_field_error(field->name, ret);
102 return ret;
105 } else if (field->flags & VMS_MUST_EXIST) {
106 fprintf(stderr, "Input validation failed: %s/%s\n",
107 vmsd->name, field->name);
108 return -1;
110 field++;
112 ret = vmstate_subsection_load(f, vmsd, opaque);
113 if (ret != 0) {
114 return ret;
116 if (vmsd->post_load) {
117 return vmsd->post_load(opaque, version_id);
119 return 0;
122 void vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd,
123 void *opaque)
125 VMStateField *field = vmsd->fields;
127 if (vmsd->pre_save) {
128 vmsd->pre_save(opaque);
130 while (field->name) {
131 if (!field->field_exists ||
132 field->field_exists(opaque, vmsd->version_id)) {
133 void *base_addr = vmstate_base_addr(opaque, field);
134 int i, n_elems = vmstate_n_elems(opaque, field);
135 int size = vmstate_size(opaque, field);
137 for (i = 0; i < n_elems; i++) {
138 void *addr = base_addr + size * i;
140 if (field->flags & VMS_ARRAY_OF_POINTER) {
141 addr = *(void **)addr;
143 if (field->flags & VMS_STRUCT) {
144 vmstate_save_state(f, field->vmsd, addr);
145 } else {
146 field->info->put(f, addr, size);
149 } else {
150 if (field->flags & VMS_MUST_EXIST) {
151 fprintf(stderr, "Output state validation failed: %s/%s\n",
152 vmsd->name, field->name);
153 assert(!(field->flags & VMS_MUST_EXIST));
156 field++;
158 vmstate_subsection_save(f, vmsd, opaque);
161 static const VMStateDescription *
162 vmstate_get_subsection(const VMStateSubsection *sub, char *idstr)
164 while (sub && sub->needed) {
165 if (strcmp(idstr, sub->vmsd->name) == 0) {
166 return sub->vmsd;
168 sub++;
170 return NULL;
173 static int vmstate_subsection_load(QEMUFile *f, const VMStateDescription *vmsd,
174 void *opaque)
176 while (qemu_peek_byte(f, 0) == QEMU_VM_SUBSECTION) {
177 char idstr[256];
178 int ret;
179 uint8_t version_id, len, size;
180 const VMStateDescription *sub_vmsd;
182 len = qemu_peek_byte(f, 1);
183 if (len < strlen(vmsd->name) + 1) {
184 /* subsection name has be be "section_name/a" */
185 return 0;
187 size = qemu_peek_buffer(f, (uint8_t *)idstr, len, 2);
188 if (size != len) {
189 return 0;
191 idstr[size] = 0;
193 if (strncmp(vmsd->name, idstr, strlen(vmsd->name)) != 0) {
194 /* it don't have a valid subsection name */
195 return 0;
197 sub_vmsd = vmstate_get_subsection(vmsd->subsections, idstr);
198 if (sub_vmsd == NULL) {
199 return -ENOENT;
201 qemu_file_skip(f, 1); /* subsection */
202 qemu_file_skip(f, 1); /* len */
203 qemu_file_skip(f, len); /* idstr */
204 version_id = qemu_get_be32(f);
206 ret = vmstate_load_state(f, sub_vmsd, opaque, version_id);
207 if (ret) {
208 return ret;
211 return 0;
214 static void vmstate_subsection_save(QEMUFile *f, const VMStateDescription *vmsd,
215 void *opaque)
217 const VMStateSubsection *sub = vmsd->subsections;
219 while (sub && sub->needed) {
220 if (sub->needed(opaque)) {
221 const VMStateDescription *vmsd = sub->vmsd;
222 uint8_t len;
224 qemu_put_byte(f, QEMU_VM_SUBSECTION);
225 len = strlen(vmsd->name);
226 qemu_put_byte(f, len);
227 qemu_put_buffer(f, (uint8_t *)vmsd->name, len);
228 qemu_put_be32(f, vmsd->version_id);
229 vmstate_save_state(f, vmsd, opaque);
231 sub++;
235 /* bool */
237 static int get_bool(QEMUFile *f, void *pv, size_t size)
239 bool *v = pv;
240 *v = qemu_get_byte(f);
241 return 0;
244 static void put_bool(QEMUFile *f, void *pv, size_t size)
246 bool *v = pv;
247 qemu_put_byte(f, *v);
250 const VMStateInfo vmstate_info_bool = {
251 .name = "bool",
252 .get = get_bool,
253 .put = put_bool,
256 /* 8 bit int */
258 static int get_int8(QEMUFile *f, void *pv, size_t size)
260 int8_t *v = pv;
261 qemu_get_s8s(f, v);
262 return 0;
265 static void put_int8(QEMUFile *f, void *pv, size_t size)
267 int8_t *v = pv;
268 qemu_put_s8s(f, v);
271 const VMStateInfo vmstate_info_int8 = {
272 .name = "int8",
273 .get = get_int8,
274 .put = put_int8,
277 /* 16 bit int */
279 static int get_int16(QEMUFile *f, void *pv, size_t size)
281 int16_t *v = pv;
282 qemu_get_sbe16s(f, v);
283 return 0;
286 static void put_int16(QEMUFile *f, void *pv, size_t size)
288 int16_t *v = pv;
289 qemu_put_sbe16s(f, v);
292 const VMStateInfo vmstate_info_int16 = {
293 .name = "int16",
294 .get = get_int16,
295 .put = put_int16,
298 /* 32 bit int */
300 static int get_int32(QEMUFile *f, void *pv, size_t size)
302 int32_t *v = pv;
303 qemu_get_sbe32s(f, v);
304 return 0;
307 static void put_int32(QEMUFile *f, void *pv, size_t size)
309 int32_t *v = pv;
310 qemu_put_sbe32s(f, v);
313 const VMStateInfo vmstate_info_int32 = {
314 .name = "int32",
315 .get = get_int32,
316 .put = put_int32,
319 /* 32 bit int. See that the received value is the same than the one
320 in the field */
322 static int get_int32_equal(QEMUFile *f, void *pv, size_t size)
324 int32_t *v = pv;
325 int32_t v2;
326 qemu_get_sbe32s(f, &v2);
328 if (*v == v2) {
329 return 0;
331 return -EINVAL;
334 const VMStateInfo vmstate_info_int32_equal = {
335 .name = "int32 equal",
336 .get = get_int32_equal,
337 .put = put_int32,
340 /* 32 bit int. Check that the received value is non-negative
341 * and less than or equal to the one in the field.
344 static int get_int32_le(QEMUFile *f, void *pv, size_t size)
346 int32_t *cur = pv;
347 int32_t loaded;
348 qemu_get_sbe32s(f, &loaded);
350 if (loaded >= 0 && loaded <= *cur) {
351 *cur = loaded;
352 return 0;
354 return -EINVAL;
357 const VMStateInfo vmstate_info_int32_le = {
358 .name = "int32 le",
359 .get = get_int32_le,
360 .put = put_int32,
363 /* 64 bit int */
365 static int get_int64(QEMUFile *f, void *pv, size_t size)
367 int64_t *v = pv;
368 qemu_get_sbe64s(f, v);
369 return 0;
372 static void put_int64(QEMUFile *f, void *pv, size_t size)
374 int64_t *v = pv;
375 qemu_put_sbe64s(f, v);
378 const VMStateInfo vmstate_info_int64 = {
379 .name = "int64",
380 .get = get_int64,
381 .put = put_int64,
384 /* 8 bit unsigned int */
386 static int get_uint8(QEMUFile *f, void *pv, size_t size)
388 uint8_t *v = pv;
389 qemu_get_8s(f, v);
390 return 0;
393 static void put_uint8(QEMUFile *f, void *pv, size_t size)
395 uint8_t *v = pv;
396 qemu_put_8s(f, v);
399 const VMStateInfo vmstate_info_uint8 = {
400 .name = "uint8",
401 .get = get_uint8,
402 .put = put_uint8,
405 /* 16 bit unsigned int */
407 static int get_uint16(QEMUFile *f, void *pv, size_t size)
409 uint16_t *v = pv;
410 qemu_get_be16s(f, v);
411 return 0;
414 static void put_uint16(QEMUFile *f, void *pv, size_t size)
416 uint16_t *v = pv;
417 qemu_put_be16s(f, v);
420 const VMStateInfo vmstate_info_uint16 = {
421 .name = "uint16",
422 .get = get_uint16,
423 .put = put_uint16,
426 /* 32 bit unsigned int */
428 static int get_uint32(QEMUFile *f, void *pv, size_t size)
430 uint32_t *v = pv;
431 qemu_get_be32s(f, v);
432 return 0;
435 static void put_uint32(QEMUFile *f, void *pv, size_t size)
437 uint32_t *v = pv;
438 qemu_put_be32s(f, v);
441 const VMStateInfo vmstate_info_uint32 = {
442 .name = "uint32",
443 .get = get_uint32,
444 .put = put_uint32,
447 /* 32 bit uint. See that the received value is the same than the one
448 in the field */
450 static int get_uint32_equal(QEMUFile *f, void *pv, size_t size)
452 uint32_t *v = pv;
453 uint32_t v2;
454 qemu_get_be32s(f, &v2);
456 if (*v == v2) {
457 return 0;
459 return -EINVAL;
462 const VMStateInfo vmstate_info_uint32_equal = {
463 .name = "uint32 equal",
464 .get = get_uint32_equal,
465 .put = put_uint32,
468 /* 64 bit unsigned int */
470 static int get_uint64(QEMUFile *f, void *pv, size_t size)
472 uint64_t *v = pv;
473 qemu_get_be64s(f, v);
474 return 0;
477 static void put_uint64(QEMUFile *f, void *pv, size_t size)
479 uint64_t *v = pv;
480 qemu_put_be64s(f, v);
483 const VMStateInfo vmstate_info_uint64 = {
484 .name = "uint64",
485 .get = get_uint64,
486 .put = put_uint64,
489 /* 64 bit unsigned int. See that the received value is the same than the one
490 in the field */
492 static int get_uint64_equal(QEMUFile *f, void *pv, size_t size)
494 uint64_t *v = pv;
495 uint64_t v2;
496 qemu_get_be64s(f, &v2);
498 if (*v == v2) {
499 return 0;
501 return -EINVAL;
504 const VMStateInfo vmstate_info_uint64_equal = {
505 .name = "int64 equal",
506 .get = get_uint64_equal,
507 .put = put_uint64,
510 /* 8 bit int. See that the received value is the same than the one
511 in the field */
513 static int get_uint8_equal(QEMUFile *f, void *pv, size_t size)
515 uint8_t *v = pv;
516 uint8_t v2;
517 qemu_get_8s(f, &v2);
519 if (*v == v2) {
520 return 0;
522 return -EINVAL;
525 const VMStateInfo vmstate_info_uint8_equal = {
526 .name = "uint8 equal",
527 .get = get_uint8_equal,
528 .put = put_uint8,
531 /* 16 bit unsigned int int. See that the received value is the same than the one
532 in the field */
534 static int get_uint16_equal(QEMUFile *f, void *pv, size_t size)
536 uint16_t *v = pv;
537 uint16_t v2;
538 qemu_get_be16s(f, &v2);
540 if (*v == v2) {
541 return 0;
543 return -EINVAL;
546 const VMStateInfo vmstate_info_uint16_equal = {
547 .name = "uint16 equal",
548 .get = get_uint16_equal,
549 .put = put_uint16,
552 /* floating point */
554 static int get_float64(QEMUFile *f, void *pv, size_t size)
556 float64 *v = pv;
558 *v = make_float64(qemu_get_be64(f));
559 return 0;
562 static void put_float64(QEMUFile *f, void *pv, size_t size)
564 uint64_t *v = pv;
566 qemu_put_be64(f, float64_val(*v));
569 const VMStateInfo vmstate_info_float64 = {
570 .name = "float64",
571 .get = get_float64,
572 .put = put_float64,
575 /* uint8_t buffers */
577 static int get_buffer(QEMUFile *f, void *pv, size_t size)
579 uint8_t *v = pv;
580 qemu_get_buffer(f, v, size);
581 return 0;
584 static void put_buffer(QEMUFile *f, void *pv, size_t size)
586 uint8_t *v = pv;
587 qemu_put_buffer(f, v, size);
590 const VMStateInfo vmstate_info_buffer = {
591 .name = "buffer",
592 .get = get_buffer,
593 .put = put_buffer,
596 /* unused buffers: space that was used for some fields that are
597 not useful anymore */
599 static int get_unused_buffer(QEMUFile *f, void *pv, size_t size)
601 uint8_t buf[1024];
602 int block_len;
604 while (size > 0) {
605 block_len = MIN(sizeof(buf), size);
606 size -= block_len;
607 qemu_get_buffer(f, buf, block_len);
609 return 0;
612 static void put_unused_buffer(QEMUFile *f, void *pv, size_t size)
614 static const uint8_t buf[1024];
615 int block_len;
617 while (size > 0) {
618 block_len = MIN(sizeof(buf), size);
619 size -= block_len;
620 qemu_put_buffer(f, buf, block_len);
624 const VMStateInfo vmstate_info_unused_buffer = {
625 .name = "unused_buffer",
626 .get = get_unused_buffer,
627 .put = put_unused_buffer,
630 /* bitmaps (as defined by bitmap.h). Note that size here is the size
631 * of the bitmap in bits. The on-the-wire format of a bitmap is 64
632 * bit words with the bits in big endian order. The in-memory format
633 * is an array of 'unsigned long', which may be either 32 or 64 bits.
635 /* This is the number of 64 bit words sent over the wire */
636 #define BITS_TO_U64S(nr) DIV_ROUND_UP(nr, 64)
637 static int get_bitmap(QEMUFile *f, void *pv, size_t size)
639 unsigned long *bmp = pv;
640 int i, idx = 0;
641 for (i = 0; i < BITS_TO_U64S(size); i++) {
642 uint64_t w = qemu_get_be64(f);
643 bmp[idx++] = w;
644 if (sizeof(unsigned long) == 4 && idx < BITS_TO_LONGS(size)) {
645 bmp[idx++] = w >> 32;
648 return 0;
651 static void put_bitmap(QEMUFile *f, void *pv, size_t size)
653 unsigned long *bmp = pv;
654 int i, idx = 0;
655 for (i = 0; i < BITS_TO_U64S(size); i++) {
656 uint64_t w = bmp[idx++];
657 if (sizeof(unsigned long) == 4 && idx < BITS_TO_LONGS(size)) {
658 w |= ((uint64_t)bmp[idx++]) << 32;
660 qemu_put_be64(f, w);
664 const VMStateInfo vmstate_info_bitmap = {
665 .name = "bitmap",
666 .get = get_bitmap,
667 .put = put_bitmap,