From: Yann Sionneau <yann(a)sionneau.net>
This patch fixes segfault of all user space processes (including init, which caused a
panic) on recent buildroot powerpc32 builds.
Recent buildroot toolchain enables secure PLT in powerpc gcc.
The latter will then supply -msecure-plt to gas invocations by default.
For the secure PLT to work, the r30 register needs to point to the GOT.
Old "bss plt" was just a one-instruction-wide PLT slot, pointed-to by a
R_PPC_JMP_SLOT relocation, which was written on-the-fly to contain a branch instruction to
the correct address. It therefore had to stay writable.
New secure PLT only contains read-only code which loads the branch address from the
writable GOT.
Signed-off-by: Yann Sionneau <yann(a)sionneau.net>
---
Rules.mak | 4 +++-
ldso/ldso/powerpc/dl-startup.h | 3 +++
libc/sysdeps/linux/powerpc/crt1.S | 5 ++++-
3 files changed, 10 insertions(+), 2 deletions(-)
diff --git a/Rules.mak b/Rules.mak
index 1fa09be23..0ab41e800 100644
--- a/Rules.mak
+++ b/Rules.mak
@@ -58,6 +58,7 @@ LD = $(CROSS_COMPILE)ld
NM = $(CROSS_COMPILE)nm
OBJDUMP = $(CROSS_COMPILE)objdump
STRIPTOOL = $(CROSS_COMPILE)strip
+READELF = $(CROSS_COMPILE)readelf
INSTALL = install
LN = ln
@@ -483,9 +484,10 @@ ifeq ($(TARGET_ARCH),powerpc)
PICFLAG:=-fpic
PIEFLAG_NAME:=-fpie
PPC_HAS_REL16:=$(shell printf "\t.text\n\taddis
11,30,_GLOBAL_OFFSET_TABLE_-.@ha\n" | $(CC) -c -x assembler -o /dev/null - 2>
/dev/null && echo -n y || echo -n n)
+ PPC_HAS_SECUREPLT:=$(shell tmpfile=$$(mktemp); printf '\#include
<stdio.h>\nint main(void) { puts("hello"); return 0;}' >
$${tmpfile}.c; $(CC) -x c $${tmpfile}.c -o $${tmpfile}; $(READELF) -d $${tmpfile} | grep
PPC_GOT > /dev/null && echo -n y || echo -n n; rm $${tmpfile}.c $${tmpfile})
+ CPU_CFLAGS-$(PPC_HAS_SECUREPLT) += -DPPC_HAS_SECUREPLT
CPU_CFLAGS-$(PPC_HAS_REL16)+= -DHAVE_ASM_PPC_REL16
CPU_CFLAGS-$(CONFIG_E500) += "-D__NO_MATH_INLINES"
-
endif
ifeq ($(TARGET_ARCH),bfin)
diff --git a/ldso/ldso/powerpc/dl-startup.h b/ldso/ldso/powerpc/dl-startup.h
index 8b2a517e2..7749395eb 100644
--- a/ldso/ldso/powerpc/dl-startup.h
+++ b/ldso/ldso/powerpc/dl-startup.h
@@ -25,6 +25,9 @@ __asm__(
#else
" bl _GLOBAL_OFFSET_TABLE_-4@local\n" /* Put our GOT pointer in r31, */
" mflr 31\n"
+#endif
+#ifdef PPC_HAS_SECUREPLT
+ " mr 30,31\n"
#endif
" addi 1,1,16\n" /* Restore SP */
" lwz 7,_dl_skip_args@got(31)\n" /* load EA of _dl_skip_args */
diff --git a/libc/sysdeps/linux/powerpc/crt1.S b/libc/sysdeps/linux/powerpc/crt1.S
index 27bfc5a5a..78b946ad6 100644
--- a/libc/sysdeps/linux/powerpc/crt1.S
+++ b/libc/sysdeps/linux/powerpc/crt1.S
@@ -47,7 +47,7 @@
_start:
mr r9,r1 /* Save the stack pointer and pass it to __uClibc_main */
clrrwi r1,r1,4 /* Align stack ptr to 16 bytes */
-#ifdef __PIC__
+#if defined(__PIC__) || defined(PPC_HAS_SECUREPLT)
# ifdef HAVE_ASM_PPC_REL16
bcl 20,31,1f
1: mflr r31
@@ -57,6 +57,9 @@ _start:
bl _GLOBAL_OFFSET_TABLE_-4@local
mflr r31
# endif
+#endif
+#ifdef PPC_HAS_SECUREPLT
+ mr 30,31
#endif
/* Set up the small data pointer in r13. */
#ifdef __PIC__
--
2.25.1