NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: port-alpha/57511: ld.elf_so(1) does not support secure PLT for alpha
The following reply was made to PR port-alpha/57511; it has been noted by GNATS.
From: Taylor R Campbell <riastradh%NetBSD.org@localhost>
To: rokuyama.rk%gmail.com@localhost, thorpej%NetBSD.org@localhost
Cc: gnats-bugs%NetBSD.org@localhost, netbsd-bugs%NetBSD.org@localhost
Subject: Re: port-alpha/57511: ld.elf_so(1) does not support secure PLT for alpha
Date: Thu, 17 Apr 2025 19:29:46 +0000
This is a multi-part message in MIME format.
--=_k+R2A0jPCfl/fFvU84G4E4n02s6AxFtx
The attached patch addresses PR 57511 and PR 57717 by implementing
support for secureplt in ld.elf_so on alpha and flipping it back on by
default (as upstream has it) in binutils.
I also took the liberty of leaving some more explanatory comments
about what's going on in rtld_start.S, based on examination of PLT
headers actually generated by binutils.
Missing: automatic tests of programs built with `-Wl,--secureplt',
`-Wl,--no-secureplt', and `-Wl,--no-secureplt,--traditional-format',
so we make sure all three paths remain exercised.
Review welcome! I hope my accent isn't showing through too much in
the assembly code as a non-native Alpha speaker.
--=_k+R2A0jPCfl/fFvU84G4E4n02s6AxFtx
Content-Type: text/plain; charset="ISO-8859-1"; name="pr57511-alphasecureplt"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment; filename="pr57511-alphasecureplt.patch"
# HG changeset patch
# User Taylor R Campbell <riastradh%NetBSD.org@localhost>
# Date 1744917745 0
# Thu Apr 17 19:22:25 2025 +0000
# Branch trunk
# Node ID ff8aa06d8f252223c352e0560098b25e54967e80
# Parent 438b14ea036dd2bd2e1109f5e08f7d74109e6fae
# EXP-Topic riastradh-pr57511-alphasecureplt
ld.elf_so on alpha: Add support for secureplt.
Enable secureplt by default in binutils now that ld.elf_so can handle
it.
PR port-alpha/57511: ld.elf_so(1) does not support secure PLT for alpha
PR port-alpha/57717: Alpha linker generates LOAD segments (and
generates warnings about them)
diff -r 438b14ea036d -r ff8aa06d8f25 doc/HACKS
--- a/doc/HACKS Thu Apr 17 13:43:59 2025 +0000
+++ b/doc/HACKS Thu Apr 17 19:22:25 2025 +0000
@@ -949,17 +949,6 @@ descr
kernel cannot execute /sbin/init.
kcah
=20
-hack Disable secure PLT for alpha
-cdate Fri Jul 7 08:33:25 UTC 2023
-who rin
-port alpha
-file src/external/gpl3/binutils/dist/bfd/elf64-alpha.c: 1.11
-pr port-alpha/57511
-descr
- Temporally disable secure PLT support, introduced by
- binutils 2.39 for us. We need its support to ld.elf_so(1).
-kcah
-
hack openssl: Disable ec_nistp_64_gcc_128 on aarch64eb
cdate Sat Jul 8 23:54:27 UTC 2023
who rin
diff -r 438b14ea036d -r ff8aa06d8f25 external/gpl3/binutils/dist/bfd/elf64-=
alpha.c
--- a/external/gpl3/binutils/dist/bfd/elf64-alpha.c Thu Apr 17 13:43:59 202=
5 +0000
+++ b/external/gpl3/binutils/dist/bfd/elf64-alpha.c Thu Apr 17 19:22:25 202=
5 +0000
@@ -83,7 +83,7 @@
=20
/* Set by ld emulation. Putting this into the link_info or hash structure
is simply working too hard. */
-#if defined(USE_SECUREPLT) && 0 /* XXX port-alpha/57511 */
+#if defined(USE_SECUREPLT)
bool elf64_alpha_use_secureplt =3D true;
#else
bool elf64_alpha_use_secureplt =3D false;
diff -r 438b14ea036d -r ff8aa06d8f25 libexec/ld.elf_so/arch/alpha/alpha_rel=
oc.c
--- a/libexec/ld.elf_so/arch/alpha/alpha_reloc.c Thu Apr 17 13:43:59 2025 +=
0000
+++ b/libexec/ld.elf_so/arch/alpha/alpha_reloc.c Thu Apr 17 19:22:25 2025 +=
0000
@@ -78,6 +78,7 @@
#define adbg(x) /* nothing */
#endif
=20
+void _rtld_bind_start_secureplt(void);
void _rtld_bind_start(void);
void _rtld_bind_start_old(void);
void _rtld_relocate_nonplt_self(Elf_Dyn *, Elf_Addr);
@@ -91,7 +92,19 @@ void
uint32_t word0;
=20
/*
- * The PLTGOT on the Alpha looks like this:
+ * If we're using Alpha secureplt, the PLTGOT points to the
+ * .got.plt section. Just fill in the rtld binding stub and
+ * we're done -- we're not writing to instruction memory, so no
+ * imb needed.
+ */
+ if (obj->secureplt) {
+ obj->pltgot[0] =3D (Elf_Addr) _rtld_bind_start_secureplt;
+ obj->pltgot[1] =3D (Elf_Addr) obj;
+ return;
+ }
+
+ /*
+ * The non-secureplt PLTGOT on the Alpha looks like this:
*
* PLT HEADER
* .
@@ -418,7 +431,8 @@ static inline int
*
* Note if the shared object uses the old PLT format, then
* we cannot patch up the PLT safely, and so we skip it
- * in that case[*].
+ * in that case[*]. And if the shared object has a read-only
+ * secureplt, then we also skip it.
*
* [*] Actually, if we're not doing lazy-binding, then
* we *can* (and do) patch up this PLT entry; the PLTGOT
@@ -426,6 +440,10 @@ static inline int
* so this test will fail as it would for the new PLT
* entry format.
*/
+ if (obj->secureplt) {
+ rdbg((" secureplt format"));
+ goto out;
+ }
if (obj->pltgot[2] =3D=3D (Elf_Addr) &_rtld_bind_start_old) {
rdbg((" old PLT format"));
goto out;
diff -r 438b14ea036d -r ff8aa06d8f25 libexec/ld.elf_so/arch/alpha/rtld_star=
t.S
--- a/libexec/ld.elf_so/arch/alpha/rtld_start.S Thu Apr 17 13:43:59 2025 +0=
000
+++ b/libexec/ld.elf_so/arch/alpha/rtld_start.S Thu Apr 17 19:22:25 2025 +0=
000
@@ -92,7 +92,7 @@ END(_rtld_start)
lda sp, -168(sp) ; \
stq ra, 0(sp) ; \
stq v0, 8(sp) ; \
- stq t0, 16(sp) ; \
+ stq t0, 16(sp) /* XXX t0-t7 necessary? */ ; \
stq t1, 24(sp) ; \
stq t2, 32(sp) ; \
stq t3, 40(sp) ; \
@@ -106,7 +106,7 @@ END(_rtld_start)
stq a3, 104(sp) ; \
stq a4, 112(sp) ; \
stq a5, 120(sp) ; \
- stq t8, 128(sp) ; \
+ stq t8, 128(sp) /* XXX t8-t11 necessary? */ ; \
stq t9, 136(sp) ; \
stq t10, 144(sp) ; \
stq t11, 152(sp) ; \
@@ -119,7 +119,7 @@ END(_rtld_start)
br t0, 1f ; \
1: LDGP(t0)
=20
-#define RTLD_BIND_START_EPILOGUE \
+#define RTLD_BIND_START_EPILOGUE(imb) \
/* Move the destination address into position. */ \
mov v0, pv ; \
\
@@ -157,7 +157,77 @@ 1: LDGP(t0)
jmp zero, (pv)
=20
/*
- * Lazy binding entry point, called via PLT.
+ * _rtld_bind_start_secureplt(_rtld_bind_start_secureplt@pv, obj@at,
+ * (sizeof(Elf_Rela)*index)@t11)
+ *
+ * Lazy binding entry point, called via PLT with read-only
+ * secureplt, when DT_ALPHA_PLTRO is set. The PLT itself looks
+ * something like this:
+ *
+ * _PROCEDURE_LINKAGE_TABLE_:
+ * subq pv, at, t11 // t11 :=3D pv - ent0 =3D 4*index
+ * s4subq t11, t11, t11 // t11 :=3D 12*index
+ * addq t11, t11, t11 // t11 :=3D 24*index
+ * // =3D sizeof(Elf_Rela)*index
+ * ldah at, ...(at) // at :=3D PLTGOT
+ * lda at, ...(at)
+ * ldq pv, 0(at) // pv :=3D PLTGOT[0]
+ * // =3D _rtld_bind_start_secureplt
+ * ldq at, 8(at) // at :=3D PLTGOT[1]
+ * // =3D obj
+ * jmp (pv)
+ * 0: br at, _PROCEDURE_LINKAGE_TABLE_ // at :=3D ent0
+ * ent0: br 0b // pv - ent0 =3D 0 =3D 4*index
+ * ent1: br 0b // pv - ent0 =3D 4 =3D 4*index
+ * ent2: br 0b // pv - ent0 =3D 8 =3D 4*index
+ * ...
+ */
+NESTED_NOPROFILE(_rtld_bind_start_secureplt, 0, 168, ra, 0, 0)
+
+ RTLD_BIND_START_PROLOGUE
+
+ /* Set up the arguments for _rtld_bind. */
+ mov at_reg, a0
+ mov t11, a1
+
+ CALL(_rtld_bind)
+
+ RTLD_BIND_START_EPILOGUE(/* no text writes, so no imb */)
+
+END(_rtld_bind_start_secureplt)
+
+/*
+ * _rtld_bind_start(_rtld_bind_start@pv, &PLTGOT[2]@pv,
+ * (ent0 + 4*(index + 1))@at)
+ *
+ * Lazy binding entry point, called via PLT with read/write
+ * non-secureplt, when DT_ALPHA_PLTRO is not set. The PLT itself
+ * looks something like this at program startup, with PLTGOT (an
+ * array of 64-bit Elf_Addr) pointing at _PROCEDURE_LINKAGE_TABLE_
+ * and PLTGOT[2] and PLTGOT[3] initialized by _rtld_setup_pltgot:
+ *
+ * _PROCEDURE_LINKAGE_TABLE_:
+ * br pv, .Lref // pv :=3D .Lref
+ * .Lref: ldq pv, 12(pv) // pv :=3D PLTGOT[2]
+ * =3D _rtld_bind_start
+ * unop // no-op for alignment
+ * jmp pv, (pv) // pv :=3D &PLTGOT[2]
+ * .qword (_rtld_bind_start) // PLTGOT[2]
+ * .qword (object pointer) // PLTGOT[3]
+ * ent0: br at, _PROCEDURE_LINKAGE_TABLE_
+ * unop // space for adjusted stub
+ * unop // space for adjusted stub
+ * ent1: br at, _PROCEDURE_LINKAGE_TABLE_
+ * unop
+ * unop
+ * ent2: br at, _PROCEDURE_LINKAGE_TABLE_
+ * unop
+ * unop
+ * ...
+ *
+ * Note: Distance from &PLTGOT[2] (pv) to ent[0] + 4 (at) is 20
+ * bytes, and each ent[index] + 4 (at) after that is separated by
+ * 3 instructions, i.e., 12 bytes.
*/
NESTED_NOPROFILE(_rtld_bind_start, 0, 168, ra, 0, 0)
=20
@@ -171,13 +241,37 @@ NESTED_NOPROFILE(_rtld_bind_start, 0, 16
=20
CALL(_rtld_bind)
=20
- RTLD_BIND_START_EPILOGUE
+ RTLD_BIND_START_EPILOGUE(imb)
=20
END(_rtld_bind_start)
=20
/*
- * Lazy binding entry point, called via PLT. This version is for the
- * old PLT entry format.
+ * _rtld_bind_start_old(&PLTGOT[2]@pv, (sizeof(Elf_Rela)*index)@at)
+ *
+ * Lazy binding entry point, called via PLT. This version is for
+ * the old PLT entry format, for which the PLT looks something
+ * like this at program startup, with PLTGOT (an array of 64-bit
+ * Elf_Addr) pointing at _PROCEDURE_LINKAGE_TABLE_, and PLTGOT[2]
+ * and PLTGOT[3] initialized by _rtld_setup_pltgot:
+ *
+ * _PROCEDURE_LINKAGE_TABLE_:
+ * br pv, 1f // pv :=3D .Lref
+ * .Lref: ldq pv, 12(pv) // pv :=3D PLTGOT[2]
+ * =3D _rtld_bind_start
+ * unop // no-op for alignment
+ * jmp pv, (pv) // pv :=3D &PLTGOT[2]
+ * .qword (_rtld_bind_start) // PLTGOT[2]
+ * .qword (object pointer) // PLTGOT[3]
+ * ent0: ldah at, 0 // at :=3D 24*0
+ * lda at, 0(at) // =3D sizeof(Elf_Rela)*index
+ * br _PROCEDURE_LINKAGE_TABLE_
+ * ent1: ldah at, 0 // at :=3D 24*1
+ * lda at, 24(at) // =3D sizeof(Elf_Rela)*index
+ * br _PROCEDURE_LINKAGE_TABLE_
+ * ent3: ldah at, 0 // at :=3D 24*2
+ * lda at, 48(at) // =3D sizeof(Elf_Rela)*index
+ * br _PROCEDURE_LINKAGE_TABLE_
+ * ...
*/
NESTED_NOPROFILE(_rtld_bind_start_old, 0, 168, ra, 0, 0)
=20
@@ -189,6 +283,6 @@ NESTED_NOPROFILE(_rtld_bind_start_old, 0
=20
CALL(_rtld_bind)
=20
- RTLD_BIND_START_EPILOGUE
+ RTLD_BIND_START_EPILOGUE(imb)
=20
END(_rtld_bind_start_old)
diff -r 438b14ea036d -r ff8aa06d8f25 libexec/ld.elf_so/headers.c
--- a/libexec/ld.elf_so/headers.c Thu Apr 17 13:43:59 2025 +0000
+++ b/libexec/ld.elf_so/headers.c Thu Apr 17 19:22:25 2025 +0000
@@ -347,6 +347,11 @@ void
break;
#endif
=20
+#ifdef __alpha__
+ case DT_ALPHA_PLTRO:
+ obj->secureplt =3D (dynp->d_un.d_val !=3D 0);
+ break;
+#endif
#ifdef __mips__
case DT_MIPS_LOCAL_GOTNO:
obj->local_gotno =3D dynp->d_un.d_val;
diff -r 438b14ea036d -r ff8aa06d8f25 libexec/ld.elf_so/rtld.h
--- a/libexec/ld.elf_so/rtld.h Thu Apr 17 13:43:59 2025 +0000
+++ b/libexec/ld.elf_so/rtld.h Thu Apr 17 19:22:25 2025 +0000
@@ -218,6 +218,9 @@ typedef struct Struct_Obj_Entry {
dlopen'ed */
phdr_loaded:1, /* Phdr is loaded and doesn't need to
* be freed. */
+#ifdef __alpha__
+ secureplt:1, /* True if PLT is read-only format */
+#endif
#if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II)
tls_static:1, /* True if static TLS offset
* has been allocated */
diff -r 438b14ea036d -r ff8aa06d8f25 sys/arch/alpha/include/elf_machdep.h
--- a/sys/arch/alpha/include/elf_machdep.h Thu Apr 17 13:43:59 2025 +0000
+++ b/sys/arch/alpha/include/elf_machdep.h Thu Apr 17 19:22:25 2025 +0000
@@ -74,4 +74,7 @@
=20
#define R_TYPE(name) __CONCAT(R_ALPHA_,name)
=20
+/* Alpha dynamic tags */
+#define DT_ALPHA_PLTRO 0x70000000 /* secure (read-only) PLT */
+
#endif /* _ALPHA_ELF_MACHDEP_H_ */
--=_k+R2A0jPCfl/fFvU84G4E4n02s6AxFtx--
Home |
Main Index |
Thread Index |
Old Index