Parts of this were stolen from kettenis.

Hey, wouldn't it be cool if static PIE executables took advantage of the 
RELRO information too?


Philip


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