]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[riscv] Allow for poisoning .bss section before early initialisation
authorMichael Brown <mcb30@ipxe.org>
Wed, 30 Jul 2025 10:11:00 +0000 (11:11 +0100)
committerMichael Brown <mcb30@ipxe.org>
Wed, 30 Jul 2025 11:31:15 +0000 (12:31 +0100)
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 <mcb30@ipxe.org>
src/arch/riscv/prefix/libprefix.S
src/config/fault.h

index 490180862997131a7e664ddc22a6e914c28cb04c..338131103089d0af6e40a94a16f3fcadb9c23a78 100644 (file)
@@ -30,6 +30,7 @@
  */
 
 #include <config/serial.h>
+#include <config/fault.h>
 
        .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
index b6ee3c934f717cb44dc82f406163dea7c7d0d051..188876e03680d46302a4f8f68c274ebccfb778ac 100644 (file)
@@ -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 <config/local/fault.h>
 
 #endif /* CONFIG_FAULT_H */