public inbox for qemu-devel@nongnu.org
 help / color / mirror / Atom feed
* [PATCH 0/2] Two linux-user patches
@ 2026-03-12 20:12 Helge Deller
  2026-03-12 20:12 ` [PATCH 1/2] linux-user: Fix zero_bss for RX PT_LOAD segments Helge Deller
  2026-03-12 20:12 ` [PATCH 2/2] linux-user: fix mremap with old_size=0 for shared mappings Helge Deller
  0 siblings, 2 replies; 3+ messages in thread
From: Helge Deller @ 2026-03-12 20:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: Laurent Vivier, Helge Deller

From: Helge Deller <deller@gmx.de>

Two linux-user patches from Razvan Ghiorghe.

They were sent to the mailing lists but were lacking review.
I think they are OK, if other people want to review too, it would be good.

Helge

Razvan Ghiorghe (2):
  linux-user: Fix zero_bss for RX PT_LOAD segments
  linux-user: fix mremap with old_size=0 for shared mappings

 linux-user/elfload.c | 37 +++++++++++++++++++------------
 linux-user/mmap.c    | 52 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 75 insertions(+), 14 deletions(-)

-- 
2.53.0



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

* [PATCH 1/2] linux-user: Fix zero_bss for RX PT_LOAD segments
  2026-03-12 20:12 [PATCH 0/2] Two linux-user patches Helge Deller
@ 2026-03-12 20:12 ` Helge Deller
  2026-03-12 20:12 ` [PATCH 2/2] linux-user: fix mremap with old_size=0 for shared mappings Helge Deller
  1 sibling, 0 replies; 3+ messages in thread
From: Helge Deller @ 2026-03-12 20:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: Laurent Vivier, Helge Deller

From: Razvan Ghiorghe <razvanghiorghe16@gmail.com>

zero_bss() incorrectly assumed that any PT_LOAD containing .bss must be
writable, rejecting valid ELF binaries where .bss overlaps the tail of
an RX file-backed page.

Instead of failing, temporarily enable write access on the overlapping
page to zero the fractional bss range, then restore the original page
permissions once initialization is complete.

Resolves: https://gitlab.com/qemu-project/qemu/-/issues/3179
Signed-off-by: Razvan Ghiorghe <razvanghiorghe16@gmail.com>
Reviewed-by: Helge Deller <deller@gmx.de>
Signed-off-by: Helge Deller <deller@gmx.de>
---
 linux-user/elfload.c | 37 +++++++++++++++++++++++--------------
 1 file changed, 23 insertions(+), 14 deletions(-)

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 35471c0c9a..59b543f740 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -449,12 +449,6 @@ static bool zero_bss(abi_ulong start_bss, abi_ulong end_bss,
 {
     abi_ulong align_bss;
 
-    /* We only expect writable bss; the code segment shouldn't need this. */
-    if (!(prot & PROT_WRITE)) {
-        error_setg(errp, "PT_LOAD with non-writable bss");
-        return false;
-    }
-
     align_bss = TARGET_PAGE_ALIGN(start_bss);
     end_bss = TARGET_PAGE_ALIGN(end_bss);
 
@@ -472,20 +466,35 @@ static bool zero_bss(abi_ulong start_bss, abi_ulong end_bss,
              */
             align_bss -= TARGET_PAGE_SIZE;
         } else {
+            abi_ulong start_page_aligned = start_bss & TARGET_PAGE_MASK;
             /*
-             * The start of the bss shares a page with something.
-             * The only thing that we expect is the data section,
-             * which would already be marked writable.
-             * Overlapping the RX code segment seems malformed.
+             * The logical OR between flags and PAGE_WRITE works because
+             * in include/exec/page-protection.h they are defined as PROT_*
+             * values, matching mprotect().
+             * Temporarily enable write access to zero the fractional bss.
+             * target_mprotect() handles TB invalidation if needed.
              */
             if (!(flags & PAGE_WRITE)) {
-                error_setg(errp, "PT_LOAD with bss overlapping "
-                           "non-writable page");
-                return false;
+                if (target_mprotect(start_page_aligned,
+                                    TARGET_PAGE_SIZE,
+                                    prot | PAGE_WRITE) == -1) {
+                    error_setg_errno(errp, errno,
+                                    "Error enabling write access for bss");
+                    return false;
+                }
             }
 
-            /* The page is already mapped and writable. */
+            /* The page is already mapped and now guaranteed writable. */
             memset(g2h_untagged(start_bss), 0, align_bss - start_bss);
+
+            if (!(flags & PAGE_WRITE)) {
+                if (target_mprotect(start_page_aligned,
+                                    TARGET_PAGE_SIZE, prot) == -1) {
+                    error_setg_errno(errp, errno,
+                                    "Error restoring bss first permissions");
+                    return false;
+                }
+            }
         }
     }
 
-- 
2.53.0



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

* [PATCH 2/2] linux-user: fix mremap with old_size=0 for shared mappings
  2026-03-12 20:12 [PATCH 0/2] Two linux-user patches Helge Deller
  2026-03-12 20:12 ` [PATCH 1/2] linux-user: Fix zero_bss for RX PT_LOAD segments Helge Deller
@ 2026-03-12 20:12 ` Helge Deller
  1 sibling, 0 replies; 3+ messages in thread
From: Helge Deller @ 2026-03-12 20:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: Laurent Vivier, Helge Deller

From: Razvan Ghiorghe <razvanghiorghe16@gmail.com>

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
  being valid and sharing the same physical memory frames.
- Ensures the new mapping address falls within the valid guest address
  region before returning it to the guest.

Tested with the reproducer from the issue on qemu-riscv64, qemu-hppa,
and qemu-aarch64.

Resolves: https://gitlab.com/qemu-project/qemu/-/issues/3105
Signed-off-by: Razvan Ghiorghe <razvanghiorghe16@gmail.com>
Tested-by: Helge Deller <deller@gmx.de>
Reviewed-by: Helge Deller <deller@gmx.de>
Signed-off-by: Helge Deller <deller@gmx.de>
---
 linux-user/mmap.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 52 insertions(+)

diff --git a/linux-user/mmap.c b/linux-user/mmap.c
index 76978a56a8..b635b6a21c 100644
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -1120,6 +1120,58 @@ 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 {
+            /*
+             * We ensure that the new mapping stands in the
+             * region of guest mappable addresses.
+             */
+            abi_ulong mmap_start;
+
+            mmap_start = mmap_find_vma(0, new_size, TARGET_PAGE_SIZE);
+
+            if (mmap_start == -1) {
+                errno = ENOMEM;
+                mmap_unlock();
+                return -1;
+            }
+
+            host_addr = mremap(g2h_untagged(old_addr), old_size, new_size,
+                             flags | MREMAP_FIXED, g2h_untagged(mmap_start));
+
+            new_addr = mmap_start;
+        }
+
+        if (host_addr == MAP_FAILED) {
+            mmap_unlock();
+            return -1;
+        }
+
+        if (flags & MREMAP_FIXED) {
+            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.53.0



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

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

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-12 20:12 [PATCH 0/2] Two linux-user patches Helge Deller
2026-03-12 20:12 ` [PATCH 1/2] linux-user: Fix zero_bss for RX PT_LOAD segments Helge Deller
2026-03-12 20:12 ` [PATCH 2/2] linux-user: fix mremap with old_size=0 for shared mappings Helge Deller

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox