> Date: Sat, 6 Aug 2016 22:17:47 -0700
> From: Philip Guenther <[email protected]>
>
> Parts of this were stolen from kettenis.
>
> Hey, wouldn't it be cool if static PIE executables took advantage of the
> RELRO information too?
Hmm. The PLT doesn't have to be executable for static PIE
executables. So I think you could simply transition to PROT_READ like
the old code does.
> Index: lib/csu/boot.h
> ===================================================================
> RCS file: /cvs/src/lib/csu/boot.h,v
> retrieving revision 1.21
> diff -u -p -r1.21 boot.h
> --- lib/csu/boot.h 7 Aug 2016 02:44:00 -0000 1.21
> +++ lib/csu/boot.h 7 Aug 2016 03:14:52 -0000
> @@ -86,8 +86,6 @@ struct boot_dyn {
> */
> void _dl_boot_bind(const long, long *, Elf_Dyn *);
>
> -extern char __plt_start[];
> -extern char __plt_end[];
> extern char __got_start[];
> extern char __got_end[];
>
> @@ -106,6 +104,7 @@ _dl_boot_bind(const long sp, long *dl_da
> long loff;
> int prot_exec = 0;
> RELOC_TYPE *rp;
> + Elf_Phdr *phdp;
> Elf_Addr i;
>
> /*
> @@ -220,12 +219,29 @@ _dl_boot_bind(const long sp, long *dl_da
> else
> pagesize = 4096;
>
> + /* do any RWX -> RX fixups for executable PLTs and apply GNU_RELRO */
> + phdp = (Elf_Phdr *)dl_data[AUX_phdr];
> + for (i = 0; i < dl_data[AUX_phnum]; i++, phdp++) {
> + switch (phdp->p_type) {
> #if defined(__alpha__) || defined(__powerpc__) || defined(__sparc__) || \
> defined(__sparc64__)
> - start = ELF_TRUNC((Elf_Addr)__plt_start, pagesize);
> - size = ELF_ROUND((Elf_Addr)__plt_end - start, pagesize);
> - mprotect((void *)start, size, PROT_READ);
> + case PT_LOAD:
> + if ((phdp->p_flags & (PF_X | PF_W)) != (PF_X | PF_W))
> + break;
> + mprotect((void *)(phdp->p_vaddr + loff), phdp->p_memsz,
> + PROT_EXEC | (phdp->p_flags & PF_R ? PROT_READ : 0));
> + break;
> #endif
> + case PT_GNU_RELRO:
> + mprotect((void *)(phdp->p_vaddr + loff), phdp->p_memsz,
> + PROT_READ);
> + /*
> + * GNU_RELRO (a) covers the GOT, and (b) comes after
> + * all LOAD sections, so if we found it then we're done
> + */
> + return;
> + }
> + }
>
> #if defined(__powerpc__)
> if (dynld.dt_proc[DT_PROC(DT_PPC_GOT)] == 0)
>
>