Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 30 Mar 2012 19:15:49 -0700
From:      Peter Wemm <peter@wemm.org>
To:        Richard Yao <ryao@cs.stonybrook.edu>
Cc:        Konstantin Belousov <kostikbel@gmail.com>, freebsd-stable@freebsd.org
Subject:   Re: Text relocations in kernel modules
Message-ID:  <CAGE5yCpuvsVrc-%2BDTVas-W4fjuP2s%2B6PQONMOTyEbGnj2CY3ig@mail.gmail.com>
In-Reply-To: <4F7637F3.2060502@cs.stonybrook.edu>
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>

next in thread | previous in thread | raw e-mail | index | archive | help
On Fri, Mar 30, 2012 at 3:47 PM, Richard Yao <ryao@cs.stonybrook.edu> 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?
>

I am the person who wrote it and deliberately chose to cause text
relocations to be generated on i386.  It is by design, not a bug.

All of your concerns are perfectly valid if they were for userland.

For the record, our amd64 modules ALSO do this, but your tools simply
do not detect it.

Here is what happens, and here is why it is not a problem:

When you compile with -fpic on an architecture that doesn't support
PC-relative addressing adequately, the compiler generates code to do
indirect memory references via the global offset table.  This is so
that all the relocations can be collected into a single location in
order to not dirty the MAP_PRIVATE data pages.

example:
if there is an function at 0x12345, and another function in a
different .so file that wants to call it at 0x22345, then the call
instruction would have to be relocated.  The asm instructions would
look like:
0xE8FFEFFFFF  (offset is -0x10000)

If the same .so file was loaded in another user process at 0x32345,
then the relocation would be different.  An entire page would be
dirtied by the dynamic linker so that the second instance of the .so
file had 0xE8FFDFFFFF (-0x20000).  This is a waste of memory and
causes a storm of VM faults at startup.

Instead, the code is compiled with -fPIC, which causes an extra memory
reference via the global offset table.  Instead of the relocations
being spread over the text segment, the relocations are in a single
page.  The dynamic linker has to dirty one page only in order to set
up a whole host of relocations.

The cost is i386 doesn't have native pc-relative mode, so it has to
waste an entire register.  We dedicate one of the 6 general purpose
registers which costs a hefty performance hit.  This is why crypto
code tends to be compiled without -fpic, for example.

For KERNEL modules, all this changes.

In userland, there is a dynamic linker. In the kernel, there is none.
In userland, the .so files are mapped with mmap(MAP_PRIVATE), the
kernel does not use mmap and always uses a private copy.
In userland, the .so files are shared, the kernel NEVER shares them.
In userland, doing a relocation causes a copy on write fault, this
never happens to the kernel because its using private, exclusive
malloc() pages.
In userland, we make the performance tradeoff from -fpic in order to
share memory pages, the kernel never shares pages so -fpic is a waste.
In userland, ASLR has security benefits.  The kernel already does
this.. if you load a module on one machine it'll ALWAYS be at
different address space compared to another.

In FreeBSD/i386, we use 'ld -shared -o foo.ko *.o', to wrap the non
pic .o files into a container that was more convenient at the time to
parse.  There is no global-offset-table.
In FreeBSD/amd64, we use 'ld -r -o foo.ko *.o' to wrap the same
non-pic code into a less convenient form that we can feed back into
the linker if we wish.  There is no global offset table.

Both i386 and amd64 use raw relocations, regardless of where the came
from.  Text, data, anywhere.

This has nothing to do with ASLR, because they are kernel objects, not
shared libraries.

You posted:
 * QA Notice: The following files contain runtime text relocations
 *  Text relocations force the dynamic linker to perform extra
 *  work at startup, waste system resources, and may pose a security
 *  risk.  On some architectures, the code may not even function
 *  properly, if at all.
The key here is "dynamic linker".  There is no dynamic linker to
process this stuff.

This is simply a tools problem on your end.  It's not a bug.

There are no security implications, no system resources to be wasted.

And if you think there are security implications, then lets see a
proof-of-concept.

I have given you a detailed explanation of why it's not a problem.  If
you want to continue, then reply with details, not hearsay or
theories.

-- 
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?CAGE5yCpuvsVrc-%2BDTVas-W4fjuP2s%2B6PQONMOTyEbGnj2CY3ig>