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