From: Michael Brown Date: Wed, 30 Jul 2025 10:11:00 +0000 (+0100) Subject: [riscv] Allow for poisoning .bss section before early initialisation X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5bda1727b4eac1bdb6a34c5c2288cd0bbf699c5b;p=thirdparty%2Fipxe.git [riscv] Allow for poisoning .bss section before early initialisation On startup, we may be running from read-only memory, and therefore cannot zero the .bss section (or write to the .data section) until we have parsed the system memory map and relocated ourselves to somewhere suitable in RAM. The code that runs during this early initialisation stage must be carefully written to avoid writing to the .data section and to avoid reading from or writing to the .bss section. Detecting code that erroneously writes to the .data or .bss sections is relatively easy since running from read-only memory (e.g. via QEMU's -pflash option) will immediately reveal the bug. Detecting code that erroneously reads from the .bss section is harder, since in a freshly powered-on machine (or in a virtual machine) there is a high probability that the contents of the memory will be zero even before we explicitly zero out the section. Add the ability to fill the .bss section with an invalid non-zero value to expose bugs in early initialisation code that erroneously relies upon variables in .bss before the section has been zeroed. We use the value 0xeb55eb55eb55eb55 ("EBSS") since this is immediately recognisable as a value in a crash dump, and will trigger a page fault if dereferenced since the address is in a non-canonical form. Poisoning the .bss can be done only when the image is known to already reside in writable memory. It will overwrite the relocation records, and so can be done only on a system where relocation is known to be unnecessary (e.g. because paging is supported). We therefore do not enable this behaviour by default, but leave it as a configurable option via the config/fault.h header. Signed-off-by: Michael Brown --- diff --git a/src/arch/riscv/prefix/libprefix.S b/src/arch/riscv/prefix/libprefix.S index 490180862..338131103 100644 --- a/src/arch/riscv/prefix/libprefix.S +++ b/src/arch/riscv/prefix/libprefix.S @@ -30,6 +30,7 @@ */ #include +#include .section ".note.GNU-stack", "", @progbits .text @@ -1268,6 +1269,51 @@ disable_paging_32_xstart: .section ".bss.disable_paging_32_xcheck", "aw", @nobits .org . + disable_paging_32_xalign - disable_paging_32_xlen +/***************************************************************************** + * + * Poison .bss section + * + ***************************************************************************** + * + * Fill the .bss section with an invalid non-zero value to expose bugs + * in early initialisation code that erroneously relies upon variables + * in .bss before the section has been zeroed. + * + * We use the value 0xeb55eb55eb55eb55 ("EBSS") since this is + * immediately recognisable as a value in a crash dump, and will + * trigger a page fault if dereferenced since the address is in a + * non-canonical form. + * + * Poisoning the .bss will overwrite the relocation records, and so + * can be done only as a debugging step on a system where relocation + * is known to be unnecessary (e.g. because paging is supported). + * + * This function does not require a valid stack pointer, but will + * destroy any existing stack contents if the stack happens to be + * placed within the original .bss section. + * + * Parameters: none + * + * Returns: none + * + */ + + .equ poison_bss_value_32, 0xeb55eb55 + .equ poison_bss_value_64, 0xeb55eb55eb55eb55 + .equ poison_bss_value, _C2 ( poison_bss_value_, __riscv_xlen ) + + .section ".prefix.poison_bss", "ax", @progbits +poison_bss: + /* Fill .bss section */ + la t0, _bss + la t1, _ebss + li t2, poison_bss_value +1: STOREN t2, (t0) + addi t0, t0, ( __riscv_xlen / 8 ) + blt t0, t1, 1b + ret + .size poison_bss, . - poison_bss + /***************************************************************************** * * Install iPXE to a suitable runtime address @@ -1328,6 +1374,11 @@ install: mv s2, ra la s3, _edata + /* Poison .bss if configured to do so */ +#if POISON_BSS + call poison_bss +#endif + /* Attempt to enable paging, if we have temporary page table space */ mv a0, a2 beqz a2, 1f diff --git a/src/config/fault.h b/src/config/fault.h index b6ee3c934..188876e03 100644 --- a/src/config/fault.h +++ b/src/config/fault.h @@ -32,6 +32,9 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); /* Experience virtual machine migration on every N watchdog checks */ #define VM_MIGRATED_RATE 0 +/* Poison .bss section before early execution */ +#define POISON_BSS 0 + #include #endif /* CONFIG_FAULT_H */