@samitouri / QOSamiQemu / commits / 2ff529c6f6

linux-user: Fix zero_bss for RX PT_LOAD segments

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>

Razvan Ghiorghe committed Feb 2, 2026 at 02:24 UTC 2ff529c6f64b706213339d4bbce76c7788243ddb
1 file changed +23 -14
linux-user/elfload.c
+23 -14
@@ -449,12 +449,6 @@ static bool zero_bss(abi_ulong start_bss, abi_ulong end_bss,
449 {
450 abi_ulong align_bss;
451
452 - /* We only expect writable bss; the code segment shouldn't need this. */
453 - if (!(prot & PROT_WRITE)) {
454 - error_setg(errp, "PT_LOAD with non-writable bss");
455 - return false;
456 - }
457 -
452 align_bss = TARGET_PAGE_ALIGN(start_bss);
453 end_bss = TARGET_PAGE_ALIGN(end_bss);
454
@@ -472,20 +466,35 @@ static bool zero_bss(abi_ulong start_bss, abi_ulong end_bss,
466 */
467 align_bss -= TARGET_PAGE_SIZE;
468 } else {
469 + abi_ulong start_page_aligned = start_bss & TARGET_PAGE_MASK;
470 /*
476 - * The start of the bss shares a page with something.
477 - * The only thing that we expect is the data section,
478 - * which would already be marked writable.
479 - * Overlapping the RX code segment seems malformed.
471 + * The logical OR between flags and PAGE_WRITE works because
472 + * in include/exec/page-protection.h they are defined as PROT_*
473 + * values, matching mprotect().
474 + * Temporarily enable write access to zero the fractional bss.
475 + * target_mprotect() handles TB invalidation if needed.
476 */
477 if (!(flags & PAGE_WRITE)) {
482 - error_setg(errp, "PT_LOAD with bss overlapping "
483 - "non-writable page");
484 - return false;
478 + if (target_mprotect(start_page_aligned,
479 + TARGET_PAGE_SIZE,
480 + prot | PAGE_WRITE) == -1) {
481 + error_setg_errno(errp, errno,
482 + "Error enabling write access for bss");
483 + return false;
484 + }
485 }
486
487 - /* The page is already mapped and writable. */
487 + /* The page is already mapped and now guaranteed writable. */
488 memset(g2h_untagged(start_bss), 0, align_bss - start_bss);
489 +
490 + if (!(flags & PAGE_WRITE)) {
491 + if (target_mprotect(start_page_aligned,
492 + TARGET_PAGE_SIZE, prot) == -1) {
493 + error_setg_errno(errp, errno,
494 + "Error restoring bss first permissions");
495 + return false;
496 + }
497 + }
498 }
499 }
500