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