@samitouri / QOSamiQemu / commits / e3580c4eb0

migration/file: fix type mismatch and NULL deref in multifd_file_recv_data

multifd_file_recv_data() stores the return value of qio_channel_pread() (ssize_t) in a size_t variable. On I/O error the -1 return value wraps to SIZE_MAX, producing a nonsensical read size in the error message. More critically, a short read (0 <= ret < data->size) is possible when the migration file is truncated. In that case qio_channel_pread() returns a non-negative value without setting *errp. The function then calls error_prepend(errp, ...) which dereferences *errp -- a NULL pointer -- crashing QEMU. Fix both issues by switching to qio_channel_pread_all() introduced in a previous patch, which retries on short reads and treats end-of-file as an error, so the caller no longer needs to check the byte count manually. Add ERRP_GUARD() so that error_prepend() works correctly even when errp is &error_fatal or NULL. Fixes: a49d15a38d3d ("migration/multifd: Support incoming mapped-ram stream format") Suggested-by: Peter Xu <peterx@redhat.com> Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> Signed-off-by: Junjie Cao <junjie.cao@intel.com> Reviewed-by: Fabiano Rosas <farosas@suse.de> Link: https://lore.kernel.org/qemu-devel/20260413214549.926435-4-junjie.cao@intel.com Signed-off-by: Fabiano Rosas <farosas@suse.de>

Junjie Cao committed Apr 14, 2026 at 05:45 UTC e3580c4eb070d50462600cbcc5612c789267617c
1 file changed +7 -6
migration/file.c
+7 -6
@@ -256,15 +256,16 @@ int file_write_ramblock_iov(QIOChannel *ioc, const struct iovec *iov,
256
257 int multifd_file_recv_data(MultiFDRecvParams *p, Error **errp)
258 {
259 + ERRP_GUARD();
260 MultiFDRecvData *data = p->data;
260 - size_t ret;
261 + int ret;
262
262 - ret = qio_channel_pread(p->c, (char *) data->opaque,
263 - data->size, data->file_offset, errp);
264 - if (ret != data->size) {
263 + ret = qio_channel_pread_all(p->c, (char *) data->opaque,
264 + data->size, data->file_offset, errp);
265 + if (ret != 0) {
266 error_prepend(errp,
266 - "multifd recv (%u): read 0x%zx, expected 0x%zx",
267 - p->id, ret, data->size);
267 + "multifd recv (%u): ",
268 + p->id);
269 return -1;
270 }
271