mirror of
https://github.com/qemu/qemu.git
synced 2026-04-05 21:46:25 +00:00
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>
This commit is contained in:
committed by
Helge Deller
parent
1fd5ff9d76
commit
2ff529c6f6
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user