From 3009edff8192991293fe9e2b50b0d90db83c4a89 Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Mon, 9 Nov 2020 17:43:55 +0000 Subject: vhost-user: fix VHOST_USER_ADD/REM_MEM_REG truncation QEMU currently truncates the mmap_offset field when sending VHOST_USER_ADD_MEM_REG and VHOST_USER_REM_MEM_REG messages. The struct layout looks like this: typedef struct VhostUserMemoryRegion { uint64_t guest_phys_addr; uint64_t memory_size; uint64_t userspace_addr; uint64_t mmap_offset; } VhostUserMemoryRegion; typedef struct VhostUserMemRegMsg { uint32_t padding; /* WARNING: there is a 32-bit hole here! */ VhostUserMemoryRegion region; } VhostUserMemRegMsg; The payload size is calculated as follows when sending the message in hw/virtio/vhost-user.c: msg->hdr.size = sizeof(msg->payload.mem_reg.padding) + sizeof(VhostUserMemoryRegion); This calculation produces an incorrect result of only 36 bytes. sizeof(VhostUserMemRegMsg) is actually 40 bytes. The consequence of this is that the final field, mmap_offset, is truncated. This breaks x86_64 TCG guests on s390 hosts. Other guest/host combinations may get lucky if either of the following holds: 1. The guest memory layout does not need mmap_offset != 0. 2. The host is little-endian and mmap_offset <= 0xffffffff so the truncation has no effect. Fix this by extending the existing 32-bit padding field to 64-bit. Now the padding reflects the actual compiler padding. This can be verified using pahole(1). Also document the layout properly in the vhost-user specification. The vhost-user spec did not document the exact layout. It would be impossible to implement the spec without looking at the QEMU source code. Existing vhost-user frontends and device backends continue to work after this fix has been applied. The only change in the wire protocol is that QEMU now sets hdr.size to 40 instead of 36. If a vhost-user implementation has a hardcoded size check for 36 bytes, then it will fail with new QEMUs. Both QEMU and DPDK/SPDK don't check the exact payload size, so they continue to work. Fixes: f1aeb14b0809e313c74244d838645ed25e85ea63 ("Transmit vhost-user memory regions individually") Cc: Raphael Norwitz Cc: Cornelia Huck Cc: Michael S. Tsirkin Cc: Christian Borntraeger Signed-off-by: Stefan Hajnoczi Message-Id: <20201109174355.1069147-1-stefanha@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Fixes: f1aeb14b0809 ("Transmit vhost-user memory regions individually") Reviewed-by: Cornelia Huck Reviewed-by: Raphael Norwitz --- contrib/libvhost-user/libvhost-user.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'contrib') diff --git a/contrib/libvhost-user/libvhost-user.h b/contrib/libvhost-user/libvhost-user.h index a1539dbb69..7d47f1364a 100644 --- a/contrib/libvhost-user/libvhost-user.h +++ b/contrib/libvhost-user/libvhost-user.h @@ -136,7 +136,7 @@ typedef struct VhostUserMemory { } VhostUserMemory; typedef struct VhostUserMemRegMsg { - uint32_t padding; + uint64_t padding; VhostUserMemoryRegion region; } VhostUserMemRegMsg; -- cgit v1.2.3 From 5fd6921cccdbc1428c888d451026ee4fd152c936 Mon Sep 17 00:00:00 2001 From: AlexChen Date: Wed, 4 Nov 2020 18:23:02 +0800 Subject: contrib/libvhost-user: Fix bad printf format specifiers We should use printf format specifier "%u" instead of "%d" for argument of type "unsigned int". Reported-by: Euler Robot Signed-off-by: Alex Chen Message-Id: <5FA28106.6000901@huawei.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- contrib/libvhost-user/libvhost-user.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'contrib') diff --git a/contrib/libvhost-user/libvhost-user.c b/contrib/libvhost-user/libvhost-user.c index bfec8a881a..5c73ffdd6b 100644 --- a/contrib/libvhost-user/libvhost-user.c +++ b/contrib/libvhost-user/libvhost-user.c @@ -701,7 +701,7 @@ vu_add_mem_reg(VuDev *dev, VhostUserMsg *vmsg) { return false; } - DPRINT("Adding region: %d\n", dev->nregions); + DPRINT("Adding region: %u\n", dev->nregions); DPRINT(" guest_phys_addr: 0x%016"PRIx64"\n", msg_region->guest_phys_addr); DPRINT(" memory_size: 0x%016"PRIx64"\n", @@ -848,7 +848,7 @@ vu_set_mem_table_exec_postcopy(VuDev *dev, VhostUserMsg *vmsg) VhostUserMemory m = vmsg->payload.memory, *memory = &m; dev->nregions = memory->nregions; - DPRINT("Nregions: %d\n", memory->nregions); + DPRINT("Nregions: %u\n", memory->nregions); for (i = 0; i < dev->nregions; i++) { void *mmap_addr; VhostUserMemoryRegion *msg_region = &memory->regions[i]; @@ -938,7 +938,7 @@ vu_set_mem_table_exec(VuDev *dev, VhostUserMsg *vmsg) return vu_set_mem_table_exec_postcopy(dev, vmsg); } - DPRINT("Nregions: %d\n", memory->nregions); + DPRINT("Nregions: %u\n", memory->nregions); for (i = 0; i < dev->nregions; i++) { void *mmap_addr; VhostUserMemoryRegion *msg_region = &memory->regions[i]; @@ -1049,8 +1049,8 @@ vu_set_vring_num_exec(VuDev *dev, VhostUserMsg *vmsg) unsigned int index = vmsg->payload.state.index; unsigned int num = vmsg->payload.state.num; - DPRINT("State.index: %d\n", index); - DPRINT("State.num: %d\n", num); + DPRINT("State.index: %u\n", index); + DPRINT("State.num: %u\n", num); dev->vq[index].vring.num = num; return false; @@ -1105,8 +1105,8 @@ vu_set_vring_base_exec(VuDev *dev, VhostUserMsg *vmsg) unsigned int index = vmsg->payload.state.index; unsigned int num = vmsg->payload.state.num; - DPRINT("State.index: %d\n", index); - DPRINT("State.num: %d\n", num); + DPRINT("State.index: %u\n", index); + DPRINT("State.num: %u\n", num); dev->vq[index].shadow_avail_idx = dev->vq[index].last_avail_idx = num; return false; @@ -1117,7 +1117,7 @@ vu_get_vring_base_exec(VuDev *dev, VhostUserMsg *vmsg) { unsigned int index = vmsg->payload.state.index; - DPRINT("State.index: %d\n", index); + DPRINT("State.index: %u\n", index); vmsg->payload.state.num = dev->vq[index].last_avail_idx; vmsg->size = sizeof(vmsg->payload.state); @@ -1478,8 +1478,8 @@ vu_set_vring_enable_exec(VuDev *dev, VhostUserMsg *vmsg) unsigned int index = vmsg->payload.state.index; unsigned int enable = vmsg->payload.state.num; - DPRINT("State.index: %d\n", index); - DPRINT("State.enable: %d\n", enable); + DPRINT("State.index: %u\n", index); + DPRINT("State.enable: %u\n", enable); if (index >= dev->max_queues) { vu_panic(dev, "Invalid vring_enable index: %u", index); @@ -1728,7 +1728,7 @@ vu_handle_vring_kick(VuDev *dev, VhostUserMsg *vmsg) return false; } - DPRINT("Got kick message: handler:%p idx:%d\n", + DPRINT("Got kick message: handler:%p idx:%u\n", dev->vq[index].handler, index); if (!dev->vq[index].started) { @@ -1772,7 +1772,7 @@ vu_process_message(VuDev *dev, VhostUserMsg *vmsg) DPRINT("Request: %s (%d)\n", vu_request_to_string(vmsg->request), vmsg->request); DPRINT("Flags: 0x%x\n", vmsg->flags); - DPRINT("Size: %d\n", vmsg->size); + DPRINT("Size: %u\n", vmsg->size); if (vmsg->fd_num) { int i; -- cgit v1.2.3 From 91010f0407a07caeacb11037bb5b493bab7ce203 Mon Sep 17 00:00:00 2001 From: AlexChen Date: Thu, 29 Oct 2020 14:03:52 +0800 Subject: vhost-user-blk/scsi: Fix broken error handling for socket call When socket() fails, it returns -1, 0 is the normal return value and should not return error. Reported-by: Euler Robot Signed-off-by: AlexChen Message-Id: <5F9A5B48.9030509@huawei.com> Reviewed-by: Raphael Norwitz Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- contrib/vhost-user-blk/vhost-user-blk.c | 2 +- contrib/vhost-user-scsi/vhost-user-scsi.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'contrib') diff --git a/contrib/vhost-user-blk/vhost-user-blk.c b/contrib/vhost-user-blk/vhost-user-blk.c index caad88637e..dc981bf945 100644 --- a/contrib/vhost-user-blk/vhost-user-blk.c +++ b/contrib/vhost-user-blk/vhost-user-blk.c @@ -476,7 +476,7 @@ static int unix_sock_new(char *unix_fn) assert(unix_fn); sock = socket(AF_UNIX, SOCK_STREAM, 0); - if (sock <= 0) { + if (sock < 0) { perror("socket"); return -1; } diff --git a/contrib/vhost-user-scsi/vhost-user-scsi.c b/contrib/vhost-user-scsi/vhost-user-scsi.c index 3c912384e9..0f9ba4b2a2 100644 --- a/contrib/vhost-user-scsi/vhost-user-scsi.c +++ b/contrib/vhost-user-scsi/vhost-user-scsi.c @@ -320,7 +320,7 @@ static int unix_sock_new(char *unix_fn) assert(unix_fn); sock = socket(AF_UNIX, SOCK_STREAM, 0); - if (sock <= 0) { + if (sock < 0) { perror("socket"); return -1; } -- cgit v1.2.3