This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Harden powerpc64 elf_machine_fixup_plt


On Fri, Mar 20, 2015 at 06:02:56PM -0400, Mike Frysinger wrote:
> On 20 Mar 2015 08:58, H.J. Lu wrote:
> > On Fri, Mar 20, 2015 at 8:51 AM, Carlos O'Donell wrote:
> > > Unfortunately no core developer wants to step up and fix this, and
> > > thus it remains a poorly understood and difficult to use feature.

The solutions I see are
1) Run two passes over dynamic relocations.  Who wants to be
   responsible for slowing down app startup?
2) Like (1) but on the first pass put ifunc relocations on a worklist.
3) Recursive dynamic relocation.  ie. before running an ifunc
   resolver, check that it has been relocated, and if not, resolve its
   shared library.  Probably not feasible due to loops in reloc
   dependencies.
4) Accept that you may need to write ifunc resolvers in assembly.
   They cannot use the GOT unless there is an ironclad guarantee that
   they won't be called before they themselves are relocated.

> > IFUNC is processor specific. I have some old docs for x86 IFUNC:
> 
> the relocs might be, but that doesn't mean the overall process/ABI contract is.  
> it's crazy that the same C code might work/not work depending on the CPU/C lib.

The really bad news is that it is trivial to construct a testcase that
shows current C ifunc resolvers, even in libc.so, won't work on
targets that must use the GOT to return the address of a function.

cat > hello.c <<EOF
#include <stdio.h>

extern int world (int) __attribute__ ((weak));

void
print (const char *str)
{
  puts (str);
}

int
main ()
{
  print ("Hello");
  if (world)
    return world (1);
  return 0;
}
EOF
cat > world.c <<EOF
extern void print (const char *);

int
world (int x)
{
  print ("world");
  return x;
}
EOF
gcc -o world.so -fPIC -shared -nostdlib world.c
gcc -o hello -Wl,-no-as-needed,-rpath,. hello.c -lc world.so
LD_DEBUG=reloc ./hello 2>&1 | grep relocation

The debug output will show world.so being relocated first, before
libc.so.  So if world.so happened to take the address of a libc.so
ifunc, or call a libc.so ifunc with LD_BIND_NOW=1, then the libc.so
ifunc resolver would be called *before libc.so has been relocated*.

Now the only thing I did a little unusual was to link "world.so" with
-nostdlib.  I also specified library order when linking "hello" in an
evil way that I happen to know will cause a problem.  Users can easily
do that by accident..

When you start looking at a current libm.so and libpthread.so, you'll
see ifunc again, and the chance of users getting the wrong dynamic
relocation order increases.

-- 
Alan Modra
Australia Development Lab, IBM


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]