vhost: catch overflow causing mmap of size 0
authorMaxime Coquelin <maxime.coquelin@redhat.com>
Thu, 16 Jan 2020 10:44:27 +0000 (11:44 +0100)
committerFerruh Yigit <ferruh.yigit@intel.com>
Wed, 5 Feb 2020 10:47:18 +0000 (11:47 +0100)
This patch catches an overflow that could happen if an
invalid region size or page alignment is provided by the
guest via the VHOST_USER_SET_MEM_TABLE request.

If the sum of the size to mmap and the alignment overflows
uint64_t, then RTE_ALIGN_CEIL(mmap_size, alignment) macro
will return 0. This value was passed as is as size argument
to mmap().

While kernel handling of mmap() syscall returns an error
if size is 0, it is better to catch it earlier and provide
a meaningful error log.

Fixes: ec09c280b839 ("vhost: fix mmap not aligned with hugepage size")
Cc: stable@dpdk.org
Reported-by: Ilja Van Sprundel <ivansprundel@ioactive.com>
Signed-off-by: Maxime Coquelin <maxime.coquelin@redhat.com>
Reviewed-by: Tiwei Bie <tiwei.bie@intel.com>
lib/librte_vhost/vhost_user.c

index c9cc4d6..9f14ea6 100644 (file)
@@ -1145,6 +1145,21 @@ vhost_user_set_mem_table(struct virtio_net **pdev, struct VhostUserMsg *msg,
                        goto err_mmap;
                }
                mmap_size = RTE_ALIGN_CEIL(mmap_size, alignment);
+               if (mmap_size == 0) {
+                       /*
+                        * It could happen if initial mmap_size + alignment
+                        * overflows the sizeof uint64, which could happen if
+                        * either mmap_size or alignment value is wrong.
+                        *
+                        * mmap() kernel implementation would return an error,
+                        * but better catch it before and provide useful info
+                        * in the logs.
+                        */
+                       VHOST_LOG_CONFIG(ERR, "mmap size (0x%" PRIx64 ") "
+                                       "or alignment (0x%" PRIx64 ") is invalid\n",
+                                       reg->size + mmap_offset, alignment);
+                       goto err_mmap;
+               }
 
                populate = (dev->dequeue_zero_copy) ? MAP_POPULATE : 0;
                mmap_addr = mmap(NULL, mmap_size, PROT_READ | PROT_WRITE,