On Sun, 7 Aug 2016, Philip Guenther wrote:
> On Sun, Aug 7, 2016 at 4:45 AM, Mark Kettenis <[email protected]> wrote:
> >> 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.
>
> Perhaps we should make it PROT_NONE. :-)
...except that doesn't work for hppa, when I do relro with .plt and .got
together in the same section. PROT_READ it is!
Tested on hppa with the relro update in the next message...
Philip
Index: lib/csu/boot.h
===================================================================
RCS file: /data/src/openbsd/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 8 Aug 2016 03:00:53 -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);
+ defined(__sparc64__) || defined(__hppa__)
+ 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_READ);
+ 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)