Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 30 Mar 2012 19:37:03 -0700
From:      Peter Wemm <peter@wemm.org>
To:        kpneal@pobox.com
Cc:        freebsd-stable@freebsd.org, Richard Yao <ryao@cs.stonybrook.edu>
Subject:   Re: Text relocations in kernel modules
Message-ID:  <CAGE5yCphAC0_Wp3w_91B8GOfLnyNUw8pM7aAAcMeEr7E52LSyg@mail.gmail.com>
In-Reply-To: <20120331015112.GA37889@neutralgood.org>
References:  <4F75E404.8000104@cs.stonybrook.edu> <4F75EF86.6090909@cs.stonybrook.edu> <20120330190713.GG2358@deviant.kiev.zoral.com.ua> <4F760C9E.6060405@cs.stonybrook.edu> <20120330194649.GH2358@deviant.kiev.zoral.com.ua> <4F761371.7020606@cs.stonybrook.edu> <20120330203605.GI2358@deviant.kiev.zoral.com.ua> <4F76350F.8000708@cs.stonybrook.edu> <20120330224631.GJ2358@deviant.kiev.zoral.com.ua> <4F7637F3.2060502@cs.stonybrook.edu> <20120331015112.GA37889@neutralgood.org>

next in thread | previous in thread | raw e-mail | index | archive | help
On Fri, Mar 30, 2012 at 6:51 PM,  <kpneal@pobox.com> wrote:
> On Fri, Mar 30, 2012 at 06:47:15PM -0400, Richard Yao wrote:
>> On 03/30/12 18:46, Konstantin Belousov wrote:
>> > Reread what I wrote to you. Also, it pays off learning how ELF works
>> > before making conclusion from the absence of the output of readelf -d.
>> > Amd64 modules _are not_ shared objects.
>>
>> Whether or not they are shared objects is irrelevant. The fact is that
>> they have text relocations, which interfere with ASLR. Do I need to
>> produce exploit code before you take me seriously?
>
> Any time you have any reference from a single compilation's object module
> to any code or data in a different compilation you need some way for one
> object to find that code/data.
>
> Think about it: if a function call is going to branch to another function
> it needs to know the address of the target function. How can it get this
> target address? Relocations.
>
> Now, move up a bit to kernel objects which typically consist of multiple
> compilations all linked together. If a function in a kernel object wants
> to call a function in the main part of the kernel it needs the address.
> How can it get this target address? Relocations.
>
> When code is linked together into a single file it is possible to have
> compilations have patched into them the offsets to functions or data from
> other compilations. But this only works when the relative locations are
> fixed.
>
> If you want different kernel objects to get random addresses when loaded
> at run time then you _must_ have some way for the kernel object to call
> back into the main kernel. It is possible to, at the C language level,
> pass around structs holding pointers to functions and pointers to data.
> But this does the same thing as relocations and it does it less efficiently.

When a chunk of code is compiled with -fpic, function calls are
produced with a special relocation type.  When it is linked, all these
calls are gathered into an indirect PLT (procedure linkage table). In
userland, the PLT is dirtied at startup and varies depending on the
random load address.  But all the indirect calls are PC-relative to
the PLT.

eg: if the kernel bzero is at 0xc0201230, and we load a .ko file at
0xc100000 which has three "call bzero" references, then:

-fpic case:
all three calls to bzero will pc-relative "call" a slot in the PLT,
which is resolved and created at "ld -shared" time, which will be run
time relocated to "jmp 0xc0201230".
ie:  "call bzero@PLT" -> "jmp bzero" -> bzero()

non-fpic case:
each instance of the three "call bzero" will be relocated without
making an indirect bounce through the PLT, which we don't need.
ie:  "call bzero" -> bzero()
there would be three symbol lookups at .ko load time instead of one.

The big difference (besides the loss of the %ebx register) is those
extra memory hits to do a bzero(), that are paid for every single
time.  Meanwhile the non-pic case has an up-front cost of invoking
some extremely unoptimized code at load time and never has the runtime
overhead.

Linux doesn't use 'ld -shared' format.  They used something vaguely
like what we did with the old LKM system, ie: running ld incrementally
and loading the results.  That was a long time ago, but they sure
don't take the overhead of PLT/GOT/-fpic mode either.  There's just no
need.

We provoke a warning on the gentoo tools on i386 because we simply
used 'ld -shared' output as a container or transport.  We use a
different format by default on amd64, but the code is generated
exactly the same way as on i386 and has exactly the same relocations
in the same places.

-- 
Peter Wemm - peter@wemm.org; peter@FreeBSD.org; peter@yahoo-inc.com; KI6FJV
"All of this is for nothing if we don't go to the stars" - JMS/B5
"If Java had true garbage collection, most programs would delete
themselves upon execution." -- Robert Sewell



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CAGE5yCphAC0_Wp3w_91B8GOfLnyNUw8pM7aAAcMeEr7E52LSyg>