* [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 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.