[PATCH] firmware: payload: test: Relocate GOT entries before calling C code
Alvin Chang <[email protected]>
| Newsgroups | org.infradead.lists.opensbi |
|---|---|
| Message-ID | <[email protected]> |
The test payload is linked as a PIE but, unlike fw_base.S, its startup
code never processed its own dynamic relocations. Nothing in the payload
needed a GOT so far, so this went unnoticed.
CONFIG_STACK_PROTECTOR_ALL=y changes that. GCC derives the
__stack_chk_guard reference from an artificial declaration with default
visibility, so under -fPIE it always loads the guard address through the
GOT. The linker zeroes that entry and records an R_RISCV_RELATIVE
relocation instead, which nobody applies. test_main() then reads the
canary from a NULL pointer before the first sbi_ecall_console_puts(), so
the payload hangs silently right after the OpenSBI boot banner. The other
two configurations emit no canary in the payload, leaving .rela.dyn
empty, which is why only this one breaks.
Keep .rela.dyn in the payload image and apply the R_RISCV_RELATIVE
entries at the top of _start, reusing the code from fw_base.S. The loop
is skipped when .rela.dyn is empty.
Fixes: edfbc1285dd9 ("firmware: Initial compiler built-in stack protector support")
Reported-by: Anup Patel <[email protected]>
Signed-off-by: Alvin Chang <[email protected]>
---
firmware/payloads/test.elf.ldS | 6 ++++++
firmware/payloads/test_head.S | 30 ++++++++++++++++++++++++++++++
2 files changed, 36 insertions(+)
diff --git a/firmware/payloads/test.elf.ldS b/firmware/payloads/test.elf.ldS
index 2328a1b7..6632c132 100644
--- a/firmware/payloads/test.elf.ldS
+++ b/firmware/payloads/test.elf.ldS
@@ -47,6 +47,12 @@ SECTIONS
PROVIDE(_rodata_end = .);
}
+ .rela.dyn : {
+ PROVIDE(__rela_dyn_start = .);
+ *(.rela*)
+ PROVIDE(__rela_dyn_end = .);
+ }
+
/* End of the read-only data sections */
. = ALIGN(0x1000); /* Ensure next section is page aligned */
diff --git a/firmware/payloads/test_head.S b/firmware/payloads/test_head.S
index e4fcaaca..09d0ad18 100644
--- a/firmware/payloads/test_head.S
+++ b/firmware/payloads/test_head.S
@@ -7,6 +7,7 @@
* Anup Patel <[email protected]>
*/
+#include <sbi/riscv_elf.h>
#include <sbi/riscv_encoding.h>
#define __ASM_STR(x) x
@@ -24,6 +25,13 @@
#define REG_S __REG_SEL(sd, sw)
#define REG_ADDW __REG_SEL(addw, add)
+/* Link time address of _payload_start, see test.elf.ldS */
+#ifdef FW_PAYLOAD_OFFSET
+#define PAYLOAD_LINK_START (FW_TEXT_START + FW_PAYLOAD_OFFSET)
+#else
+#define PAYLOAD_LINK_START 0
+#endif
+
.section .entry, "ax", %progbits
.align 3
.globl _start
@@ -45,6 +53,28 @@ _sc_fail:
#endif
bnez a3, _start_hang
+ /* relocate the global table content */
+ li t0, PAYLOAD_LINK_START /* link start */
+ lla t1, _payload_start /* load start */
+ sub t2, t1, t0 /* load offset */
+ lla t0, __rela_dyn_start
+ lla t1, __rela_dyn_end
+ beq t0, t1, _relocate_done
+2:
+ REG_L t5, __SIZEOF_LONG__(t0) /* t5 <-- relocation info:type */
+ li t3, R_RISCV_RELATIVE /* reloc type R_RISCV_RELATIVE */
+ bne t5, t3, 3f
+ REG_L t3, 0(t0)
+ REG_L t5, (__SIZEOF_LONG__ * 2)(t0) /* t5 <-- addend */
+ add t5, t5, t2
+ add t3, t3, t2
+ REG_S t5, 0(t3) /* store runtime address to the GOT entry */
+
+3:
+ addi t0, t0, (__SIZEOF_LONG__ * 3)
+ blt t0, t1, 2b
+_relocate_done:
+
/* Save a0 and a1 */
lla a3, _boot_a0
REG_S a0, 0(a3)
--
2.43.0
--
opensbi mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/opensbi