> 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)
> 
> 

Reply via email to