> Date: Sat, 6 Aug 2016 22:10:08 -0700
> From: Philip Guenther <guent...@gmail.com>
> 
> Ahem.
> 
> What I mean is that with some patching, RELRO can be enabled by default on 
> several archs.  The first chunk below enables it on x86, arm, and sparc64.  
> I'm 95% positive that it would Just Work on alpha and sh (TEXT_PLT archs 
> like amd64, arm, and i386) and sparc (looks like sparc64, shock!), but 
> this is untested there.
> 
> 
> So what is RELRO anyway?  RELRO is basically a hook for marking sections 
> of memory of an object as being "Read-Only after RELocation".
> 
> We've been doing a version of this for years on OpenBSD via the 
> __{got,plt}_{start,end} symbols: ld.so would mprotect the regions between 
> those symbols after relocation, and then when relocating lazy binding it 
> would mark the necessary bits temporarily writable.  Last year we added 
> kbind() so that lazy relocations could be done securely and efficiently 
> through the kernel.
> 
> Since then, we've practically eliminated the need for the 
> __plt_{start,end} handling by treating all RWX sections as RW-until- 
> -relocation-and-RX-after-relocation.
> 
> While our design works, the GNU_RELRO design by the GNU people offers some 
> advantages:
>  - no need for symbol lookup.  The start address and length are coded
>    directly into the section instead of needing two symbol lookups
>  - covers even more than we did.  Theo and Dale had to do serious hacking
>    to get our support to cover not just the GOT but also the .ctors and 
>    .dtors segments.  Well, the GNU people hacked more and managed to make 
>    the .eh_frame, .tdata, .tbss, dynamic, .{init,preinit,fini}_array, and 
>    .jcr segments also RELRO.
>  - fewer mappings.  There are two areas, both of which need to start out
>    read-write but the first needs to switch to read-only.  The GNU people 
>    realized that if you align the data correctly in the file, you can do 
>    *one* mmap() that covers both but place the division between them on a 
>    page boundary so it can be the start of a later mprotect(), thus saving 
>    the cost of a separate mmap() call.
> 
> 
> So what's going on in this diff?
> 
> The armelf_obsd.sh chunk makes that arch order things like the others, 
> setting things up before sourcing the common elf_obsd bits that depend on 
> them, with 4KB as the normal pagesize.  If there's nothing special about 
> 16KB in our uvm/pmap layer then lowering MAXPAGESIZE may save space.

Hmm, MAXPAGESIZE might have been chosen to avoid virtual addressed
cache aliasing issues.

> While I don't have RELRO 100% working on powerpc (damn bss-plt compat) or 
> mips64 yet, these are a start...and I've been testing with them so long 
> I'm not sure things work without them.  I really don't know what *PAGESIZE 
> values are appropriate for mips BE & LE: loongson has 16KB pages, are 
> there mips64le with smaller?
> 
> As for elf.sc: "Cthulhu touches you with his tentacle: you lose 5 sanity" 
> The diff here does this:
>  - move some not-really-executable bits from the start of the inital RX
>    section to start of the first RO section
>  - move the PLT in the "executable, but initially mutable and not required
>    to be before the GOT" case from immediately before the .data segment to 
>    between the RO and RW sections.  This is used, for example, on sparc64 
>    where the sections end up in the order
>       RX      .init .text .fini
>       R       .interp .note* .hash .dyn* .rel* .rodata .eh_frame
>       RWX     .plt
>       RW      .openbsd.randomdata .jcr .dynamic .got .cdtors .data .bss
>  - move up the __got_start symbols to the start of the RW section
>  - *don't* pad before the PLT when it's a DATA_PLT in the relro area
>  - when doing RELRO, put the .ctor and .dtor sections right after
>    the .got and *right before* the RELRO RO-vs-RW boundary
> 
> Have I lost everyone?  Beuhler?  Beuhler?  oks?

Going to give this a go on hppa to see if I can spot any issues there.

Doesn't the powerpc change mean we'll be making some things writable
again until we switch relro on there?


> Index: gnu/usr.bin/binutils-2.17/ld/ldmain.c
> ===================================================================
> RCS file: /cvs/src/gnu/usr.bin/binutils-2.17/ld/ldmain.c,v
> retrieving revision 1.9
> diff -u -p -r1.9 ldmain.c
> --- gnu/usr.bin/binutils-2.17/ld/ldmain.c     21 Jun 2016 02:55:57 -0000      
> 1.9
> +++ gnu/usr.bin/binutils-2.17/ld/ldmain.c     7 Aug 2016 03:18:37 -0000
> @@ -299,7 +299,12 @@ main (int argc, char **argv)
>    link_info.new_dtags = FALSE;
>    link_info.combreloc = TRUE;
>    link_info.eh_frame_hdr = FALSE;
> +#if defined(__amd64__) || defined(__arm__) || defined(__i386__) || \
> +    defined(__sparc64__)
> +  link_info.relro = TRUE;
> +#else
>    link_info.relro = FALSE;
> +#endif
>    link_info.strip_discarded = TRUE;
>    link_info.strip = strip_none;
>    link_info.discard = discard_sec_merge;
> Index: gnu/usr.bin/binutils-2.17/ld/emulparams/armelf_obsd.sh
> ===================================================================
> RCS file: /cvs/src/gnu/usr.bin/binutils-2.17/ld/emulparams/armelf_obsd.sh,v
> retrieving revision 1.1
> diff -u -p -r1.1 armelf_obsd.sh
> --- gnu/usr.bin/binutils-2.17/ld/emulparams/armelf_obsd.sh    24 Apr 2011 
> 20:19:25 -0000      1.1
> +++ gnu/usr.bin/binutils-2.17/ld/emulparams/armelf_obsd.sh    7 Aug 2016 
> 03:18:37 -0000
> @@ -1,8 +1,10 @@
>  . ${srcdir}/emulparams/armelf.sh
> -. ${srcdir}/emulparams/elf_obsd.sh
>  
>  MAXPAGESIZE=0x8000
> +COMMONPAGESIZE=0x1000
>  TEXT_START_ADDR=0x00008000
>  TARGET2_TYPE=got-rel
>  
>  unset EMBEDDED
> +
> +. ${srcdir}/emulparams/elf_obsd.sh
> Index: gnu/usr.bin/binutils-2.17/ld/emulparams/elf32ppc_obsd.sh
> ===================================================================
> RCS file: /cvs/src/gnu/usr.bin/binutils-2.17/ld/emulparams/elf32ppc_obsd.sh,v
> retrieving revision 1.3
> diff -u -p -r1.3 elf32ppc_obsd.sh
> --- gnu/usr.bin/binutils-2.17/ld/emulparams/elf32ppc_obsd.sh  23 Aug 2015 
> 15:19:32 -0000      1.3
> +++ gnu/usr.bin/binutils-2.17/ld/emulparams/elf32ppc_obsd.sh  7 Aug 2016 
> 03:18:37 -0000
> @@ -1,7 +1,2 @@
> -. ${srcdir}/emulparams/elf32ppccommon.sh
> -# We deliberately keep the traditional OpenBSD W^X layout for both the
> -# old BSS-PLT and the new Secure-PLT ABI.
> -BSS_PLT=
> -OTHER_TEXT_SECTIONS="*(.glink)"
> -EXTRA_EM_FILE=ppc32elf
> +. ${srcdir}/emulparams/elf32ppc.sh
>  . ${srcdir}/emulparams/elf_obsd.sh
> Index: gnu/usr.bin/binutils-2.17/ld/emulparams/elf64btsmip_obsd.sh
> ===================================================================
> RCS file: 
> /cvs/src/gnu/usr.bin/binutils-2.17/ld/emulparams/elf64btsmip_obsd.sh,v
> retrieving revision 1.2
> diff -u -p -r1.2 elf64btsmip_obsd.sh
> --- gnu/usr.bin/binutils-2.17/ld/emulparams/elf64btsmip_obsd.sh       16 Jun 
> 2015 20:25:35 -0000      1.2
> +++ gnu/usr.bin/binutils-2.17/ld/emulparams/elf64btsmip_obsd.sh       7 Aug 
> 2016 03:18:37 -0000
> @@ -1,5 +1,6 @@
>  . ${srcdir}/emulparams/elf64btsmip.sh
>  MAXPAGESIZE=0x10000
> +COMMONPAGESIZE=0x1000
>  TEXT_START_ADDR="0x10000000"
>  . ${srcdir}/emulparams/elf_obsd.sh
>  # XXX causes GOT oflows
> Index: gnu/usr.bin/binutils-2.17/ld/emulparams/elf64ltsmip_obsd.sh
> ===================================================================
> RCS file: 
> /cvs/src/gnu/usr.bin/binutils-2.17/ld/emulparams/elf64ltsmip_obsd.sh,v
> retrieving revision 1.2
> diff -u -p -r1.2 elf64ltsmip_obsd.sh
> --- gnu/usr.bin/binutils-2.17/ld/emulparams/elf64ltsmip_obsd.sh       16 Jun 
> 2015 20:25:35 -0000      1.2
> +++ gnu/usr.bin/binutils-2.17/ld/emulparams/elf64ltsmip_obsd.sh       7 Aug 
> 2016 03:18:37 -0000
> @@ -1,5 +1,6 @@
>  . ${srcdir}/emulparams/elf64ltsmip.sh
>  MAXPAGESIZE=0x10000
> +COMMONPAGESIZE=0x1000
>  TEXT_START_ADDR="0x10000000"
>  . ${srcdir}/emulparams/elf_obsd.sh
>  # XXX causes GOT oflows
> Index: gnu/usr.bin/binutils-2.17/ld/scripttempl/elf.sc
> ===================================================================
> RCS file: /cvs/src/gnu/usr.bin/binutils-2.17/ld/scripttempl/elf.sc,v
> retrieving revision 1.8
> diff -u -p -r1.8 elf.sc
> --- gnu/usr.bin/binutils-2.17/ld/scripttempl/elf.sc   9 Aug 2014 04:49:47 
> -0000       1.8
> +++ gnu/usr.bin/binutils-2.17/ld/scripttempl/elf.sc   7 Aug 2016 03:18:38 
> -0000
> @@ -267,6 +267,35 @@ SECTIONS
>    ${CREATE_SHLIB-${CREATE_PIE-${RELOCATING+PROVIDE (__executable_start = 
> ${TEXT_START_ADDR}); . = ${TEXT_BASE_ADDRESS};}}}
>    ${CREATE_SHLIB+${RELOCATING+. = ${SHLIB_TEXT_START_ADDR:-0} + 
> SIZEOF_HEADERS;}}
>    ${CREATE_PIE+${RELOCATING+. = ${SHLIB_TEXT_START_ADDR:-0} + 
> SIZEOF_HEADERS;}}
> +  .init         ${RELOCATING-0} : 
> +  { 
> +    ${RELOCATING+${INIT_START}}
> +    KEEP (*(.init))
> +    ${RELOCATING+${INIT_END}}
> +  } =${NOP-0}
> +
> +  ${TEXT_PLT+${PLT}}
> +  ${TINY_READONLY_SECTION}
> +  .text         ${RELOCATING-0} :
> +  {
> +    ${RELOCATING+${TEXT_START_SYMBOLS}}
> +    *(.text .stub${RELOCATING+ .text.* .gnu.linkonce.t.*})
> +    KEEP (*(.text.*personality*))
> +    /* .gnu.warning sections are handled specially by elf32.em.  */
> +    *(.gnu.warning)
> +    ${RELOCATING+${OTHER_TEXT_SECTIONS}}
> +  } =${NOP-0}
> +  .fini         ${RELOCATING-0} :
> +  {
> +    ${RELOCATING+${FINI_START}}
> +    KEEP (*(.fini))
> +    ${RELOCATING+${FINI_END}}
> +  } =${NOP-0}
> +  ${RELOCATING+PROVIDE (__${ETEXT_NAME} = .);}
> +  ${RELOCATING+PROVIDE (_${ETEXT_NAME} = .);}
> +  ${RELOCATING+PROVIDE (${ETEXT_NAME} = .);}
> +
> +  ${PAD_RO+${PAD_RO0}}
>    ${CREATE_SHLIB-${INTERP}}
>    ${INITIAL_READONLY_SECTIONS}
>    ${TEXT_DYNAMIC+${DYNAMIC}}
> @@ -337,34 +366,6 @@ cat <<EOF
>    .rela.plt     ${RELOCATING-0} : { *(.rela.plt) }
>    ${OTHER_PLT_RELOC_SECTIONS}
>  
> -  .init         ${RELOCATING-0} : 
> -  { 
> -    ${RELOCATING+${INIT_START}}
> -    KEEP (*(.init))
> -    ${RELOCATING+${INIT_END}}
> -  } =${NOP-0}
> -
> -  ${TEXT_PLT+${PLT}}
> -  ${TINY_READONLY_SECTION}
> -  .text         ${RELOCATING-0} :
> -  {
> -    ${RELOCATING+${TEXT_START_SYMBOLS}}
> -    *(.text .stub${RELOCATING+ .text.* .gnu.linkonce.t.*})
> -    KEEP (*(.text.*personality*))
> -    /* .gnu.warning sections are handled specially by elf32.em.  */
> -    *(.gnu.warning)
> -    ${RELOCATING+${OTHER_TEXT_SECTIONS}}
> -  } =${NOP-0}
> -  .fini         ${RELOCATING-0} :
> -  {
> -    ${RELOCATING+${FINI_START}}
> -    KEEP (*(.fini))
> -    ${RELOCATING+${FINI_END}}
> -  } =${NOP-0}
> -  ${RELOCATING+PROVIDE (__${ETEXT_NAME} = .);}
> -  ${RELOCATING+PROVIDE (_${ETEXT_NAME} = .);}
> -  ${RELOCATING+PROVIDE (${ETEXT_NAME} = .);}
> -  ${PAD_RO+${PAD_RO0}}
>    ${WRITABLE_RODATA-${RODATA}}
>    .rodata1      ${RELOCATING-0} : { *(.rodata1) }
>    ${CREATE_SHLIB-${SDATA2}}
> @@ -374,11 +375,15 @@ cat <<EOF
>    .eh_frame     ${RELOCATING-0} : ONLY_IF_RO { KEEP (*(.eh_frame)) }
>    .gcc_except_table ${RELOCATING-0} : ONLY_IF_RO { *(.gcc_except_table 
> .gcc_except_table.*) }
>  
> +  ${DATA_NONEXEC_PLT-${DATA_PLT+${PLT_BEFORE_GOT-${PAD_PLT+${PAD_PLT0}}}}}
> +  ${DATA_NONEXEC_PLT-${DATA_PLT+${PLT_BEFORE_GOT-${PLT}}}}
> +
>    /* Adjust the address for the data segment.  We want to adjust up to
>       the same address within the page on the next page up.  */
>    ${CREATE_SHLIB-${CREATE_PIE-${RELOCATING+. = 
> ${DATA_ADDR-${DATA_SEGMENT_ALIGN}};}}}
>    ${CREATE_SHLIB+${RELOCATING+. = ${SHLIB_DATA_ADDR-${DATA_SEGMENT_ALIGN}};}}
>    ${CREATE_PIE+${RELOCATING+. = ${SHLIB_DATA_ADDR-${DATA_SEGMENT_ALIGN}};}}
> +  ${DATA_GOT+${RELRO_NOW+${PAD_GOT+${RELOCATING+PROVIDE_HIDDEN(__got_start = 
> .);}}}}
>  
>    /* Exception handling  */
>    .eh_frame     ${RELOCATING-0} : ONLY_IF_RW { KEEP (*(.eh_frame)) }
> @@ -419,11 +424,13 @@ cat <<EOF
>    ${RELOCATING+${DATARELRO}}
>    ${OTHER_RELRO_SECTIONS}
>    ${TEXT_DYNAMIC-${DYNAMIC}}
> -  ${DATA_GOT+${PAD_GOT+${PAD_GOT0}}}
> +  ${DATA_GOT+${RELRO_NOW-${PAD_GOT+${PAD_GOT0}}}}
>    ${DATA_GOT+${DATA_NONEXEC_PLT+${PLT}}}
>    ${DATA_GOT+${RELRO_NOW+${GOT}}}
>    ${DATA_GOT+${RELRO_NOW+${GOTPLT}}}
> -  ${DATA_GOT+${RELRO_NOW+${PAD_GOT+${PAD_GOT1}}}}
> +  ${DATA_GOT+${RELRO_NOW+${PAD_CDTOR+${RELOCATING+${CTOR}}}}}
> +  ${DATA_GOT+${RELRO_NOW+${PAD_CDTOR+${RELOCATING+${DTOR}}}}}
> +  ${DATA_GOT+${RELRO_NOW+${PAD_GOT+${RELOCATING+PROVIDE_HIDDEN(__got_end = 
> .);}}}}
>    ${DATA_GOT+${RELRO_NOW-${SEPARATE_GOTPLT+${GOT}}}}
>    /* If PAD_CDTOR, and separate .got and .got.plt sections, CTOR and DTOR
>       are relocated here to receive the same mprotect protection as .got */
> @@ -437,10 +444,6 @@ cat <<EOF
>    ${DATA_GOT+${RELRO_NOW-${SEPARATE_GOTPLT-${PAD_GOT+${PAD_GOT1}}}}}
>    ${DATA_GOT+${RELRO_NOW-${GOTPLT}}}
>  
> -  ${DATA_NONEXEC_PLT-${DATA_PLT+${PLT_BEFORE_GOT-${PAD_PLT+${PAD_PLT0}}}}}
> -  ${DATA_NONEXEC_PLT-${DATA_PLT+${PLT_BEFORE_GOT-${PLT}}}}
> -  ${DATA_NONEXEC_PLT-${DATA_PLT+${PLT_BEFORE_GOT-${PAD_PLT+${PAD_PLT1}}}}}
> -
>    .data         ${RELOCATING-0} :
>    {
>      ${RELOCATING+${DATA_START_SYMBOLS}}
> @@ -462,8 +465,6 @@ cat <<EOF
>    ${SDATA_GOT+${RELOCATING+${OTHER_GOT_SYMBOLS}}}
>    ${SDATA_GOT+${GOT}}
>  
> -  ${DATA_GOT+${RELRO_NOW+${PAD_CDTOR+${RELOCATING+${CTOR}}}}}
> -  ${DATA_GOT+${RELRO_NOW+${PAD_CDTOR+${RELOCATING+${DTOR}}}}}
>    ${DATA_GOT-${PAD_CDTOR+${RELOCATING+${CTOR}}}}
>    ${DATA_GOT-${PAD_CDTOR+${RELOCATING+${DTOR}}}}
>  
> 
> 

Reply via email to