This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
Re: Harden powerpc64 elf_machine_fixup_plt
- From: Alan Modra <amodra at gmail dot com>
- To: "H.J. Lu" <hjl dot tools at gmail dot com>, Carlos O'Donell <carlos at redhat dot com>, Rich Felker <dalias at libc dot org>, GNU C Library <libc-alpha at sourceware dot org>
- Date: Mon, 23 Mar 2015 14:05:43 +1030
- Subject: Re: Harden powerpc64 elf_machine_fixup_plt
- Authentication-results: sourceware.org; auth=none
- References: <20150319235208 dot GB26234 at bubble dot grove dot modra dot org> <20150320152245 dot GJ23507 at brightrain dot aerifal dot cx> <550C421B dot 9080305 at redhat dot com> <CAMe9rOo6X_KxEeD6KdYkHsSUp2G09-7SdLGjTUKOr=s0Pt49YA at mail dot gmail dot com> <20150320220256 dot GQ11803 at vapier>
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