migration/multifd: Replace assert() with error_setg() in recv paths
QPL and UADK multifd backends use assert() to validate wire-controlled fields like per-page compressed lengths and packet size consistency. These asserts will stop working with -DNDEBUG builds, so may stop working. Replace all assert() calls in the receive path with proper error_setg() so validation failures are reported gracefully rather than crashing or silently ignored. While at it, touch up an assert() in qatzip recv path too. Cc: qemu-stable <qemu-stable@nongnu.org> Cc: Yuan Liu <yuan1.liu@intel.com> Cc: Yichen Wang <yichen.wang@bytedance.com> Reviewed-by: Fabiano Rosas <farosas@suse.de> Link: https://lore.kernel.org/r/20260728210417.1925078-4-peterx@redhat.com Signed-off-by: Peter Xu <peterx@redhat.com>
Peter Xu committed
Jul 28, 2026 at 17:04 UTC
cf45083edc2b760a952836187aba7ec4139418c0
3 files changed
+44
-9
migration/multifd-qatzip.c
+4
-1
@@ -348,7 +348,10 @@ static int qatzip_recv(MultiFDRecvParams *p, Error **errp)
348
349
multifd_recv_zero_page_process(p);
350
if (!p->normal_num) {
351
- assert(in_size == 0);
351
+ if (in_size != 0) {
352
+ error_setg(errp, "multifd %u: expected empty packet", p->id);
353
+ return -1;
354
+ }
355
return 0;
356
}
357
migration/multifd-qpl.c
+20
-4
@@ -664,26 +664,42 @@ static int multifd_qpl_recv(MultiFDRecvParams *p, Error **errp)
664
}
665
multifd_recv_zero_page_process(p);
666
if (!p->normal_num) {
667
- assert(in_size == 0);
667
+ if (in_size != 0) {
668
+ error_setg(errp, "multifd %u: expected empty packet", p->id);
669
+ return -1;
670
+ }
671
return 0;
672
}
673
674
/* read compressed page lengths */
675
len = p->normal_num * sizeof(uint32_t);
673
- assert(len < in_size);
676
+ if (len >= in_size) {
677
+ error_setg(errp, "multifd %u: header len %"PRIu32
678
+ " >= packet size %"PRIu32, p->id, len, in_size);
679
+ return -1;
680
+ }
681
ret = qio_channel_read_all(p->c, (void *) qpl->zlen, len, errp);
682
if (ret != 0) {
683
return ret;
684
}
685
for (int i = 0; i < p->normal_num; i++) {
686
qpl->zlen[i] = be32_to_cpu(qpl->zlen[i]);
680
- assert(qpl->zlen[i] <= multifd_ram_page_size());
687
+ if (qpl->zlen[i] > multifd_ram_page_size()) {
688
+ error_setg(errp, "multifd %u: page %d compressed len %"
689
+ PRIu32" too large", p->id, i, qpl->zlen[i]);
690
+ return -1;
691
+ }
692
zbuf_len += qpl->zlen[i];
693
ramblock_recv_bitmap_set_offset(p->block, p->normal[i]);
694
}
695
696
/* read compressed pages */
686
- assert(in_size == len + zbuf_len);
697
+ if (in_size != len + zbuf_len) {
698
+ error_setg(errp, "multifd %u: packet size %"PRIu32
699
+ " != header %"PRIu32" + data %"PRIu32,
700
+ p->id, in_size, len, zbuf_len);
701
+ return -1;
702
+ }
703
ret = qio_channel_read_all(p->c, (void *) qpl->zbuf, zbuf_len, errp);
704
if (ret != 0) {
705
return ret;
migration/multifd-uadk.c
+20
-4
@@ -245,12 +245,19 @@ static int multifd_uadk_recv(MultiFDRecvParams *p, Error **errp)
245
246
multifd_recv_zero_page_process(p);
247
if (!p->normal_num) {
248
- assert(in_size == 0);
248
+ if (in_size != 0) {
249
+ error_setg(errp, "multifd %u: expected empty packet", p->id);
250
+ return -1;
251
+ }
252
return 0;
253
}
254
255
/* read compressed data lengths */
253
- assert(hdr_len < in_size);
256
+ if (hdr_len >= in_size) {
257
+ error_setg(errp, "multifd %u: header len %"PRIu32
258
+ " >= packet size %"PRIu32, p->id, hdr_len, in_size);
259
+ return -1;
260
+ }
261
ret = qio_channel_read_all(p->c, (void *) uadk_data->buf_hdr,
262
hdr_len, errp);
263
if (ret != 0) {
@@ -259,12 +266,21 @@ static int multifd_uadk_recv(MultiFDRecvParams *p, Error **errp)
266
267
for (int i = 0; i < p->normal_num; i++) {
268
uadk_data->buf_hdr[i] = be32_to_cpu(uadk_data->buf_hdr[i]);
269
+ if (uadk_data->buf_hdr[i] > page_size) {
270
+ error_setg(errp, "multifd %u: page %d compressed len %"PRIu32
271
+ " too large", p->id, i, uadk_data->buf_hdr[i]);
272
+ return -1;
273
+ }
274
data_len += uadk_data->buf_hdr[i];
263
- assert(uadk_data->buf_hdr[i] <= page_size);
275
}
276
277
/* read compressed data */
267
- assert(in_size == hdr_len + data_len);
278
+ if (in_size != hdr_len + data_len) {
279
+ error_setg(errp, "multifd %u: packet size %"PRIu32
280
+ " != header %"PRIu32" + data %"PRIu32,
281
+ p->id, in_size, hdr_len, data_len);
282
+ return -1;
283
+ }
284
ret = qio_channel_read_all(p->c, (void *)buf, data_len, errp);
285
if (ret != 0) {
286
return ret;