> Date: Sat, 6 Aug 2016 22:10:08 -0700
> From: Philip Guenther <[email protected]>
>
> 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}}}}
>
>
>