[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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.