Commit 228117b4cd for qemu.org
commit 228117b4cd469e04eeeda93715989b3916a53c15
Author: Bin Guo <guobin@linux.alibaba.com>
Date: Thu Aug 13 17:55:00 2026 +0800
libvhost-user: accept the postcopy client base ack in vu_add_mem_reg()
In postcopy mode QEMU signals that it has collected all the postcopy client
bases by sending a VHOST_USER_ADD_MEM_REG message with a u64 payload of 0
and no file descriptor (see vhost_user_add_remove_regions()).
vu_add_mem_reg() has a case for that message, but only reaches it after
validating the fd count of a regular region, so the ack is rejected first:
VHOST_USER_ADD_MEM_REG received 0 fds - only 1 fd should be sent for
this message type
This kills the backend during memory table setup, making postcopy unusable
for any libvhost-user backend that negotiates
VHOST_USER_PROTOCOL_F_CONFIGURE_MEM_SLOTS.
Recognise the ack before validating the fd count.
Fixes: 9f4e63491b ("libvhost-user: Add vu_add_mem_reg input validation")
Signed-off-by: Bin Guo <guobin@linux.alibaba.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20260813095501.20282-2-guobin@linux.alibaba.com>
diff --git a/subprojects/libvhost-user/libvhost-user.c b/subprojects/libvhost-user/libvhost-user.c
index a74d814bb4..248550aae1 100644
--- a/subprojects/libvhost-user/libvhost-user.c
+++ b/subprojects/libvhost-user/libvhost-user.c
@@ -948,6 +948,20 @@ static bool
vu_add_mem_reg(VuDev *dev, VhostUserMsg *vmsg) {
VhostUserMemoryRegion m = vmsg->payload.memreg.region, *msg_region = &m;
+ /*
+ * If we are in postcopy mode and we receive a u64 payload with a 0 value
+ * we know all the postcopy client bases have been received, and we
+ * should start generating faults. This message carries no file
+ * descriptor, so it has to be recognised before the fd count of a real
+ * region is validated below.
+ */
+ if (dev->postcopy_listening &&
+ vmsg->size == sizeof(vmsg->payload.u64) &&
+ vmsg->payload.u64 == 0) {
+ (void)generate_faults(dev);
+ return false;
+ }
+
if (vmsg->fd_num != 1) {
vmsg_close_fds(vmsg);
vu_panic(dev, "VHOST_USER_ADD_MEM_REG received %d fds - only 1 fd "
@@ -971,18 +985,6 @@ vu_add_mem_reg(VuDev *dev, VhostUserMsg *vmsg) {
return false;
}
- /*
- * If we are in postcopy mode and we receive a u64 payload with a 0 value
- * we know all the postcopy client bases have been received, and we
- * should start generating faults.
- */
- if (dev->postcopy_listening &&
- vmsg->size == sizeof(vmsg->payload.u64) &&
- vmsg->payload.u64 == 0) {
- (void)generate_faults(dev);
- return false;
- }
-
_vu_add_mem_reg(dev, msg_region, vmsg->fds[0]);
close(vmsg->fds[0]);