All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2] linux-user: Fix mremap() with old_size == 0
@ 2026-02-01  1:03 Razvan Ghiorghe
  2026-02-04  3:34 ` Richard Henderson
  2026-03-03 19:01 ` razvan ghiorghe
  0 siblings, 2 replies; 6+ messages in thread
From: Razvan Ghiorghe @ 2026-02-01  1:03 UTC (permalink / raw)
  To: qemu-devel, laurent, razvanghiorghe16

When old_size is zero and old_address refers to a shareable mapping,
mremap() should create a new mapping of the same pages according to the
mremap(2) man page. The MREMAP_MAYMOVE flag must be specified in this case.
Previously, QEMU's target_mremap() rejected this valid case with EFAULT during
the initial validation, before checking for the special old_size == 0 behaviour.

This patch adds proper handling for old_size == 0:
- Validates that MREMAP_MAYMOVE flag is set (required by man spec)
- Passes the call through to the host mremap()
- Creates a new mapping without invalidating the original, with both
beeing valid and sharing the same physical memory frames.

Tested with the reproducer from the issue on qemu-riscv64.
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/3105
Signed-off-by: Razvan Ghiorghe <razvanghiorghe16@gmail.com>
---
 linux-user/mmap.c | 32 ++++++++++++++++++++++++++++++++
 1 file changed, 32 insertions(+)

diff --git a/linux-user/mmap.c b/linux-user/mmap.c
index 4bcfaf7894..b1a84eb60a 100644
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -1117,6 +1117,38 @@ abi_long target_mremap(abi_ulong old_addr, abi_ulong old_size,
         errno = EINVAL;
         return -1;
     }
+
+    if (!old_size) {
+        if (!(flags & MREMAP_MAYMOVE)) {
+            errno = EINVAL;
+            return -1;
+        }
+        mmap_lock();
+        if (flags & MREMAP_FIXED) {
+            host_addr = mremap(g2h_untagged(old_addr), old_size, new_size,
+                             flags, g2h_untagged(new_addr));
+        } else {
+            host_addr = mremap(g2h_untagged(old_addr), old_size, new_size,
+                             flags);
+        }
+
+        if (host_addr == MAP_FAILED) {
+            mmap_unlock();
+            return -1;
+        }
+        new_addr = h2g(host_addr);
+        prot = page_get_flags(old_addr);
+        /*
+         * For old_size zero, there is nothing to clear at old_addr.
+         * Only set the flags for the new mapping. They both are valid.
+         */
+        page_set_flags(new_addr, new_addr + new_size - 1,
+                       prot | PAGE_VALID, PAGE_VALID);
+        shm_region_rm_complete(new_addr, new_addr + new_size - 1);
+        mmap_unlock();
+        return new_addr;
+    }
+
     if (!guest_range_valid_untagged(old_addr, old_size)) {
         errno = EFAULT;
         return -1;
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2026-03-12 20:02 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-02-01  1:03 [PATCH v2] linux-user: Fix mremap() with old_size == 0 Razvan Ghiorghe
2026-02-04  3:34 ` Richard Henderson
2026-03-03 19:01 ` razvan ghiorghe
2026-03-07 19:13   ` Helge Deller
2026-03-09 23:30     ` [PATCH v3] linux-user: fix mremap with old_size=0 for shared mappings Razvan Ghiorghe
2026-03-12 20:01       ` Helge Deller

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.