Re: [RFC PATCH 0/7] Relocatable Kernel

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hello Matt,

On Mon, Oct 5, 2015 at 3:22 PM, Matt Redfearn <matt.redfearn@xxxxxxxxxx> wrote:
> Hi,
> This patch series is a prerequisite of adding KASLR support for MIPS.
> So far this supports 32/64 bit big/little endian CPUs and has been
> tested in Qemu for Malta. It has not been tested on real hardware yet.
> It is presented here as an early RFC for issues that people can forsee with
> the many platforms, memory layouts etc that it must support.
>
> Here is a description of how relocation is achieved:
> * Kernel is compiled & statically linked as normal (no position independent code).
> * The linker flag --emit-relocs is added to the linker command line, causing ld
>   to include additional ".rel" sections in the output elf
> * A tool is used to parse the ".rel" sections and create a binary table of
>   relocations. Each entry in the table is 32bits, comprised of a 24bit offset
>   and 8bit relocation type.
> * The table is appended to the kernel binary image, with some space in the
>   memory map reserved for it in the linker script
> * At boot, the kernel memcpy()s itself elsewhere in memory, then goes through
>   the table performing each relocation on the new image
> * If all goes well, control is passed to the entry point of the new kernel.
>

We (at MontaVista) also have a working KASLR implementation (albeit on
3.10.x kernel on which our distribution is based) which has been/is
being tested only on Cavium Octeon2. We used the following approach
based on a compressed image(like what x86_64 does). This makes the
whole thing dependent on SYS_SUPPORTS_ZBOOT though.

During build:

1. Statically link the kernel but generate relocations with
--emit-relocs (As you have done).
2. Use the relocs hostprog (Again, derived from x86 relocs tool) to
parse and optimize the relocations generated after vmlinux is built.
The final relocation entries are of the form  (64 bit rel_offset,8bit
rel_type). (I see you record only the offset from start of .text in
the offset field, Nice way to save some space :) ).
3. The final relocation information/table is compressed together with
vmlinux.bin to generate vmlinuz.
4. We have some logic in the relocs tool to record the size of
vmlinux.bin so that the decompressor routine can find the start of
relocation table at runtime after decompression.

At runtime:

4. The decompressor stub decompresses the vmlinux(along with the
relocation table) into a random location rather than to
VMLINUX_LOAD_ADDRESS_ULL.
5. The entropy is generated using LSBs of CP0 count register.
6. After decompression, a routine handle_relocations finds the start
of the relocation table in the decompression buffer (see 4 above) and
processes the relocations based on the link-load offset. (x86_64 goes
to the end of the buffer and works backwards using 0 as a seperator
between the relocation table and uncompressed vmlinux ).
7. Return the load offset to arch/mips/boot/compressed/head.S.
8. Based on this load offset, fixup KERNEL_ENTRY in compressed/head.S
and jump to that address.

With this approach, the only places where we needed to touch the
kernel proper code was

1. We do not relocate the entries in ex_table at bootup but resort to
fixing them up runtime (I am not proud of that code :)). My initial
plan was to use relative entries in the ex_table  (Like what x86_64
has). This will make the entries not to be relocated at bootup(will
also make them half the size). But the compiler would not let me do
that because "operation combines symbols in different segments".

2. The entries in kcrctab gets relocated during bootup so that during
module insertion a crc mismatch will arise and the module will not get
installed. Fixed this the PowerPC way using ARCH_RELOCATES_KCRCTAB and
using _text - VMLINUX_LOAD_ADDRESS as reloc_start. Maybe the relocs
tool could take care of this. (I see that you have not taken care of
this or maybe you have and I missed it).

There is one issue with our approach. As our objective was only KASLR,
the vmlinuz is linked at a constant address (and I have not made the
decompressor stub -fPIC) ignoring calc_vmlinuz_load_addr . To have a
RELOCATABLE binary, I think we will need to have a -fPIC decompressor
stub.

 I have not forward ported/tested my changes on newer kernels, so I do
not have a RFC patch set yet.

Thanks,
Silesh.




[Index of Archives]     [Linux MIPS Home]     [LKML Archive]     [Linux ARM Kernel]     [Linux ARM]     [Linux]     [Git]     [Yosemite News]     [Linux SCSI]     [Linux Hams]

  Powered by Linux