> Date: Tue, 18 Aug 2015 05:03:19 +0000
> From: Miod Vallat <m...@online.fr>
> 
> > I spent some time today figuting out why the binutils update broke ld
> > -Z on powerpc.  Turns out to be a fairly thorny issue.
> > 
> > The new binutils discard empty setions.  As a result the .gotpad0 and
> > .gotpad1 sections have disappeared.  And a s a consequence the
> > __got_start and __got_end symbols are now "absolute" symbols as the
> > section they referenced to is no longer there.  For example, an older
> > libc has:
> > 
> >    845: 000eeb68     0 NOTYPE  GLOBAL DEFAULT   17 __got_start
> > 
> > whereas -current has:
> > 
> >    810: 000eeb58     0 NOTYPE  GLOBAL DEFAULT  ABS __got_start
> > 
> > On powerpc, crt0.o has weak references to __got_start and __got_end.
> > When building a binary with ld -Z, these are resolved to the absolute
> > symbols from libc.  At runtime we then use these values, relocated as
> > if they were addresses within the binary itself, to change protections
> > and flush the instruction cache.  This is very likely to result in a
> > segmentation fault.
> > 
> > There is probably a linker bug here, as it doesn't make any sense for
> > the linker to pick the address of these symbols from libc and stick it
> > into the binary.  But I'm not sure about this.  And it isn't all that
> > obvious what the fix would be.  Is the bug that the symbols end up as
> > absolute?  Or is the problem that it sibsequently resolves these to
> > the values from libc.so?
> 
> Wouldn't something like that address the problem better?

Unfortunately not.  Using PROVIDE() makes the __got_start/end symbols
disappear from shared libraries.  If I use:

  GOTSTART="__got_start = .;"

I end up with the same "absolute" symbols as before.  You really have
to tie the symbols to a specific section that isn't discarded to make
them end up as "normal" symbols.  And that is difficult since we try
to make __got_start/end cover multiple sections, some of which may or
may not be present.

I still think my diff to remove code is the way to go.  As I
explained, it isn't really clear which set of symbols the references
in crt0.o will actually resolve to.  And the secure-plt work will
require changes to the code anyway to make sure we don't end up with
an executable GOT after all.

> Index: elf.sc
> ===================================================================
> RCS file: /OpenBSD/src/gnu/usr.bin/binutils-2.17/ld/scripttempl/elf.sc,v
> retrieving revision 1.8
> diff -u -p -r1.8 elf.sc
> --- elf.sc    9 Aug 2014 04:49:47 -0000       1.8
> +++ elf.sc    18 Aug 2015 05:02:41 -0000
> @@ -195,10 +195,12 @@ if test "$NO_PAD" = "y" ; then
>    PAD_RO0="${RELOCATING+${RODATA_ALIGN} + ${RODATA_ALIGN_ADD_VAL};}"
>    PAD_PLT0="${RELOCATING+. = ALIGN(${MAXPAGESIZE}) + (. & (${MAXPAGESIZE} - 
> 1));} .pltpad0 ${RELOCATING-0} : { ${RELOCATING+__plt_start = .;} }"
>    PAD_PLT1=".pltpad1 ${RELOCATING-0} : { ${RELOCATING+__plt_end = .;}} 
> ${RELOCATING+. = ALIGN(${MAXPAGESIZE}) + (. & (${MAXPAGESIZE} - 1));}"
> -  PAD_GOT0="${RELOCATING+. = ALIGN(${MAXPAGESIZE}) + (. & (${MAXPAGESIZE} - 
> 1));} .gotpad0 ${RELOCATING-0} : { ${RELOCATING+__got_start = .;} }"
> -  PAD_GOT1=".gotpad1 ${RELOCATING-0} : { ${RELOCATING+__got_end = .;}} 
> ${RELOCATING+. = ALIGN(${MAXPAGESIZE}) + (. & (${MAXPAGESIZE} - 1));}"
> +  PAD_GOT0="${RELOCATING+. = ALIGN(${MAXPAGESIZE}) + (. & (${MAXPAGESIZE} - 
> 1));}"
> +  PAD_GOT1="${RELOCATING+. = ALIGN(${MAXPAGESIZE}) + (. & (${MAXPAGESIZE} - 
> 1));}"
>    test "$NO_PAD_CDTOR" = "y" || PAD_CDTOR=
>  fi
> +GOTSTART="PROVIDE (__got_start = .);"
> +GOTEND="PROVIDE (__got_end = .);"
>  
>  CTOR=".ctors        ${CONSTRUCTING-0} : 
>    {
> @@ -420,9 +422,11 @@ cat <<EOF
>    ${OTHER_RELRO_SECTIONS}
>    ${TEXT_DYNAMIC-${DYNAMIC}}
>    ${DATA_GOT+${PAD_GOT+${PAD_GOT0}}}
> +  ${DATA_GOT+${GOTSTART}}
>    ${DATA_GOT+${DATA_NONEXEC_PLT+${PLT}}}
>    ${DATA_GOT+${RELRO_NOW+${GOT}}}
>    ${DATA_GOT+${RELRO_NOW+${GOTPLT}}}
> +  ${DATA_GOT+${RELRO_NOW+${GOTEND}}}
>    ${DATA_GOT+${RELRO_NOW+${PAD_GOT+${PAD_GOT1}}}}
>    ${DATA_GOT+${RELRO_NOW-${SEPARATE_GOTPLT+${GOT}}}}
>    /* If PAD_CDTOR, and separate .got and .got.plt sections, CTOR and DTOR
> @@ -430,11 +434,13 @@ cat <<EOF
>    
> ${DATA_GOT+${RELRO_NOW-${SEPARATE_GOTPLT+${PAD_CDTOR+${RELOCATING+${CTOR}}}}}}
>    
> ${DATA_GOT+${RELRO_NOW-${SEPARATE_GOTPLT+${PAD_CDTOR+${RELOCATING+${DTOR}}}}}}
>    ${DATA_GOT+${RELRO_NOW-${SEPARATE_GOTPLT+${PAD_GOT+${PAD_GOT1}}}}}
> +  ${DATA_GOT+${RELRO_NOW-${SEPARATE_GOTPLT+${GOTEND}}}}
>    ${RELOCATING+${DATA_SEGMENT_RELRO_END}}
>    ${DATA_GOT+${RELRO_NOW-${SEPARATE_GOTPLT-${GOT}}}}
>    
> ${DATA_GOT+${RELRO_NOW-${SEPARATE_GOTPLT-${PAD_CDTOR+${RELOCATING+${CTOR}}}}}}
>    
> ${DATA_GOT+${RELRO_NOW-${SEPARATE_GOTPLT-${PAD_CDTOR+${RELOCATING+${DTOR}}}}}}
>    ${DATA_GOT+${RELRO_NOW-${SEPARATE_GOTPLT-${PAD_GOT+${PAD_GOT1}}}}}
> +  ${DATA_GOT+${RELRO_NOW-${SEPARATE_GOTPLT-${GOTEND}}}}
>    ${DATA_GOT+${RELRO_NOW-${GOTPLT}}}
>  
>    ${DATA_NONEXEC_PLT-${DATA_PLT+${PLT_BEFORE_GOT-${PAD_PLT+${PAD_PLT0}}}}}
> @@ -458,6 +464,7 @@ cat <<EOF
>    ${DATA_NONEXEC_PLT-${DATA_PLT+${PLT_BEFORE_GOT+${PLT}}}}
>    ${DATA_NONEXEC_PLT-${DATA_PLT+${PLT_BEFORE_GOT+${PAD_PLT+${PAD_PLT1}}}}}
>    ${SDATA_GOT+${PAD_GOT+${PAD_GOT0}}}
> +  ${SDATA_GOT+${GOTSTART}}
>    ${SDATA_GOT+${DATA_NONEXEC_PLT+${PLT}}}
>    ${SDATA_GOT+${RELOCATING+${OTHER_GOT_SYMBOLS}}}
>    ${SDATA_GOT+${GOT}}
> @@ -468,6 +475,7 @@ cat <<EOF
>    ${DATA_GOT-${PAD_CDTOR+${RELOCATING+${DTOR}}}}
>  
>    ${SDATA_GOT+${OTHER_GOT_SECTIONS}}
> +  ${SDATA_GOT+${GOTEND}}
>    ${SDATA_GOT+${PAD_GOT+${PAD_GOT1}}}
>  
>    ${SDATA}
> 

Reply via email to