Add 2 test cases to validate the fix for issue #3179, where the linux-user ELF Loader incorrectly rejected binaries with .bss sections in R_X PT_LOAD segments.
test-zerobss-1.c: defines a minimal _start routine that exists immediately without accessing the .bss region. Although a .bss region is present in ELF, it is never referenced at runtime. This test validates that the loader can correctly handle and zero the fractional .bss region in an R_X segment without triggering permission violations. test-zerobss-2.c: explicitly reads from multiple .bss variables to verify they are zeroed properly. If the .bss was correctly zeroed, the exit code will be 0. rx_anonymous_bss.ld: tests require a custom linker script to create the specific ELF layout that triggers the bug. The linker script: - creates a single PT_LOAD segment with FLAGS(5) = PF_R | PF_X (read-execute) - places .text and .bss in this same segment - sets .bss to ALIGN(1) to force it into the tail of the R_X segment - results in p_filesz < p_memsz, where the gap is anonymous .bss Expected behavior: - Without the fix: Both tests fail with "PT_LOAD with non-writable bss" - With the fix: Both tests pass (exit code 0) Signed-off-by: Razvan Ghiorghe <[email protected]> --- tests/tcg/x86_64/Makefile.target | 15 ++++++++++++ tests/tcg/x86_64/rx_anonymous_bss.ld | 27 +++++++++++++++++++++ tests/tcg/x86_64/test-zerobss-1.c | 20 ++++++++++++++++ tests/tcg/x86_64/test-zerobss-2.c | 36 ++++++++++++++++++++++++++++ 4 files changed, 98 insertions(+) create mode 100644 tests/tcg/x86_64/rx_anonymous_bss.ld create mode 100644 tests/tcg/x86_64/test-zerobss-1.c create mode 100644 tests/tcg/x86_64/test-zerobss-2.c diff --git a/tests/tcg/x86_64/Makefile.target b/tests/tcg/x86_64/Makefile.target index be20fc64e8..ca375a4318 100644 --- a/tests/tcg/x86_64/Makefile.target +++ b/tests/tcg/x86_64/Makefile.target @@ -19,6 +19,9 @@ X86_64_TESTS += test-1648 X86_64_TESTS += test-2175 X86_64_TESTS += cross-modifying-code X86_64_TESTS += fma + +X86_64_TESTS += test-zerobss-1 +X86_64_TESTS += test-zerobss-2 TESTS=$(MULTIARCH_TESTS) $(X86_64_TESTS) test-x86_64 else TESTS=$(MULTIARCH_TESTS) @@ -36,5 +39,17 @@ test-x86_64: LDFLAGS+=-lm -lc test-x86_64: test-i386.c test-i386.h test-i386-shift.h test-i386-muldiv.h $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) +test-zerobss-1: $(SRC_PATH)/tests/tcg/x86_64/test-zerobss-1.c + $(CC) -nostdlib -static -fno-stack-protector -fno-pie -no-pie \ + -Wl,-T,$(SRC_PATH)/tests/tcg/x86_64/rx_anonymous_bss.ld \ + -Wl,--build-id=none \ + $< -o $@ + +test-zerobss-2: $(SRC_PATH)/tests/tcg/x86_64/test-zerobss-2.c + $(CC) -nostdlib -static -fno-stack-protector -fno-pie -no-pie \ + -Wl,-T,$(SRC_PATH)/tests/tcg/x86_64/rx_anonymous_bss.ld \ + -Wl,--build-id=none \ + $< -o $@ + %: $(SRC_PATH)/tests/tcg/x86_64/%.c $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) diff --git a/tests/tcg/x86_64/rx_anonymous_bss.ld b/tests/tcg/x86_64/rx_anonymous_bss.ld new file mode 100644 index 0000000000..3ec72fde6c --- /dev/null +++ b/tests/tcg/x86_64/rx_anonymous_bss.ld @@ -0,0 +1,27 @@ +/* Linker script to create RX PT_LOAD with anonymous .bss tail + * SPDX-License-Identifier: GPL-2.0-or-later + */ +PHDRS +{ + text PT_LOAD FLAGS(5); +} +SECTIONS +{ + . = 0x400000; + .text : { + *(.text .text.*) + _etext = .; + } :text + .bss ALIGN(1) : { + _bss_start = .; + *(.bss .bss.* COMMON) + _bss_end = .; + } :text + /DISCARD/ : { + *(.note.GNU-stack) + *(.note.gnu.property) + *(.comment) + *(.eh_frame) + } +} +ENTRY(_start) diff --git a/tests/tcg/x86_64/test-zerobss-1.c b/tests/tcg/x86_64/test-zerobss-1.c new file mode 100644 index 0000000000..809ea3cb52 --- /dev/null +++ b/tests/tcg/x86_64/test-zerobss-1.c @@ -0,0 +1,20 @@ + /* + * .bss region exists but unused + * SPDX-License-Identifier: GPL-2.0-or-later + */ +int x; +void _start(void) +{ + /* + * Exit immediately & never touched x + */ + __asm__ volatile( + "mov $60, %%rax\n" + "xor %%rdi, %%rdi\n" + "syscall\n" + : /* no out */ + : /* no in */ + : "rax", "rdi" + ); + __builtin_unreachable(); +} diff --git a/tests/tcg/x86_64/test-zerobss-2.c b/tests/tcg/x86_64/test-zerobss-2.c new file mode 100644 index 0000000000..1f4f0d9704 --- /dev/null +++ b/tests/tcg/x86_64/test-zerobss-2.c @@ -0,0 +1,36 @@ +/* + * Test case for zero_bss() with anonymous BSS in RX PT_LOAD + * + * This binary has .bss in the same PT_LOAD as .text (R_X permissions), + * but the BSS is anonymous (beyond p_filesz), not file-backed. + * Actual behavior: + * old code: Fails with "PT_LOAD with non-writable bss" + * new code: Succeeds, zeros BSS, exits with code 0 + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +/* These will be included in .bss (uninitialized anonymous memory) */ +int bss_value; +int bss_array[64]; + +void _start(void) +{ + int sum = bss_value; + int i; + + for (i = 0; i < 64; i++) { + sum += bss_array[i]; + } + /* If BSS was properly zeroed, sum should be 0 */ + /* Exit with sum as exit code */ + __asm__ volatile ( + "movl %0, %%edi\n\t" + "movl $60, %%eax\n\t" + "syscall\n\t" + : /* no out*/ + : "r" (sum) + : "rdi", "rax" + ); + + __builtin_unreachable(); +} -- 2.43.0
