[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] xen-mapcache: avoid a race on memory map while using MAP_FIXED


  • To: <qemu-devel@xxxxxxxxxx>, <xen-devel@xxxxxxxxxxxxxxxxxxxx>
  • From: Igor Druzhinin <igor.druzhinin@xxxxxxxxxx>
  • Date: Tue, 20 Apr 2021 04:35:02 +0100
  • Authentication-results: esa6.hc3370-68.iphmx.com; dkim=none (message not signed) header.i=none
  • Cc: <sstabellini@xxxxxxxxxx>, <anthony.perard@xxxxxxxxxx>, <paul@xxxxxxx>, <mst@xxxxxxxxxx>, <marcel.apfelbaum@xxxxxxxxx>, <pbonzini@xxxxxxxxxx>, <richard.henderson@xxxxxxxxxx>, <ehabkost@xxxxxxxxxx>, Igor Druzhinin <igor.druzhinin@xxxxxxxxxx>
  • Delivery-date: Tue, 20 Apr 2021 03:35:31 +0000
  • Ironport-hdrordr: A9a23:/M1IuqmuRAaPF6ULGJ/OBpfkkrzpDfPfimdD5ilNYBxZY6Wkvu izgfUW0gL1gj4NWHcm3euNIrWEXGm0z/NIyKMaVI3DYCDNvmy0IIZ+qbbz2jGIIVyZysdx94 dFN5J/Btr5EERgga/BijWQPt48zLC8n5yAqvzZyx5WIz1CS6Yl1AthDxbeL0sefnglObMcNL 6xovVKvCChf3N/VLXdOlAgU/LYr9PG0LLKCCR2ZCIP0wWFgTO25LOSKXHxsis2aD9Bzawv9m LIiWXCl8Cemsq21wPG0Cvr54lW8eGL9vJ4GMeOhsIJQw+c7jqAWYIJYdy/lQFwms6DwhIAkN 7AoxAvVv4DlE/5TyWOjjbGnyXl2DYqwXf+xVGfmmuLm72GeBsKT/BvqKgcXhzF61cxnNwU6t M740up86B5IDmFvCPh68PGXxtn/3DE0UYKoKoooFF0Fa49AYUh1LA3zQduP7orWB/e0sQBFt JjCcnNjcwmDG+yXjTikUREhOC3Um9bJGb/fmEy/va7/hJxh35Dw04R1KUk7ws93aN4cZVC6u jeW54Y741mf4sTZaJ5Mu8LXdG6PGzLWQ7NK2KfOz3cZds6B04=
  • Ironport-sdr: feFMM1VAyrKGKMq/I/3hGcUuM6DYGTxTonCWKap2CE2QC5mu7bltxyxCPER9cU60UT1pGEmhBU mdIeDTseJKrnUTUdtwd7XtwI7x9wjSOm00T5g/VUSIrH6H/su3BK3pcos1ftp/b5RIvKPT00oB R3MZ8Up4grBpW39oKUCZdI8nBf3KnOTPhaIGSZprMlXOnEHuoJQnd5POAjVjN+LkxnLaPAQsO/ SlauEB2IG5V5brf1ghYDp1ivo0XYuQhzyHxB8RVXvtmQlV21POJbwmxSD23t3DCjAoWfHhkGIS 8jw=
  • List-id: Xen developer discussion <xen-devel.lists.xenproject.org>

When we're replacing the existing mapping there is possibility of a race
on memory map with other threads doing mmap operations - the address being
unmapped/re-mapped could be occupied by another thread in between.

Linux mmap man page recommends keeping the existing mappings in place to
reserve the place and instead utilize the fact that the next mmap operation
with MAP_FIXED flag passed will implicitly destroy the existing mappings
behind the chosen address. This behavior is guaranteed by POSIX / BSD and
therefore is portable.

Note that it wouldn't make the replacement atomic for parallel accesses to
the replaced region - those might still fail with SIGBUS due to
xenforeignmemory_map not being atomic. So we're still not expecting those.

Tested-by: Anthony PERARD <anthony.perard@xxxxxxxxxx>
Signed-off-by: Igor Druzhinin <igor.druzhinin@xxxxxxxxxx>
---
 hw/i386/xen/xen-mapcache.c | 15 ++++++++++++++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/hw/i386/xen/xen-mapcache.c b/hw/i386/xen/xen-mapcache.c
index 5b120ed..e82b7dc 100644
--- a/hw/i386/xen/xen-mapcache.c
+++ b/hw/i386/xen/xen-mapcache.c
@@ -171,7 +171,20 @@ static void xen_remap_bucket(MapCacheEntry *entry,
         if (!(entry->flags & XEN_MAPCACHE_ENTRY_DUMMY)) {
             ram_block_notify_remove(entry->vaddr_base, entry->size);
         }
-        if (munmap(entry->vaddr_base, entry->size) != 0) {
+
+        /*
+         * If an entry is being replaced by another mapping and we're using
+         * MAP_FIXED flag for it - there is possibility of a race for vaddr
+         * address with another thread doing an mmap call itself
+         * (see man 2 mmap). To avoid that we skip explicit unmapping here
+         * and allow the kernel to destroy the previous mappings by replacing
+         * them in mmap call later.
+         *
+         * Non-identical replacements are not allowed therefore.
+         */
+        assert(!vaddr || (entry->vaddr_base == vaddr && entry->size == size));
+
+        if (!vaddr && munmap(entry->vaddr_base, entry->size) != 0) {
             perror("unmap fails");
             exit(-1);
         }
-- 
2.7.4




 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.