Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

arm64: add support for building vmlinux as a relocatable PIE binary

This implements CONFIG_RELOCATABLE, which links the final vmlinux
image with a dynamic relocation section, allowing the early boot code
to perform a relocation to a different virtual address at runtime.

This is a prerequisite for KASLR (CONFIG_RANDOMIZE_BASE).

Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>

authored by

Ard Biesheuvel and committed by
Catalin Marinas
1e48ef7f 6c94f27a

+65
+11
arch/arm64/Kconfig
··· 787 787 select ARM64_MODULE_CMODEL_LARGE 788 788 select HAVE_MOD_ARCH_SPECIFIC 789 789 790 + config RELOCATABLE 791 + bool 792 + help 793 + This builds the kernel as a Position Independent Executable (PIE), 794 + which retains all relocation metadata required to relocate the 795 + kernel binary at runtime to a different virtual address than the 796 + address it was linked at. 797 + Since AArch64 uses the RELA relocation format, this requires a 798 + relocation pass at runtime even if the kernel is loaded at the 799 + same address it was linked at. 800 + 790 801 endmenu 791 802 792 803 menu "Boot options"
+4
arch/arm64/Makefile
··· 15 15 OBJCOPYFLAGS :=-O binary -R .note -R .note.gnu.build-id -R .comment -S 16 16 GZFLAGS :=-9 17 17 18 + ifneq ($(CONFIG_RELOCATABLE),) 19 + LDFLAGS_vmlinux += -pie 20 + endif 21 + 18 22 KBUILD_DEFCONFIG := defconfig 19 23 20 24 # Check for binutils support for specific extensions
+2
arch/arm64/include/asm/elf.h
··· 77 77 #define R_AARCH64_MOVW_PREL_G2_NC 292 78 78 #define R_AARCH64_MOVW_PREL_G3 293 79 79 80 + #define R_AARCH64_RELATIVE 1027 81 + 80 82 /* 81 83 * These are used to set parameters in the core dumps. 82 84 */
+32
arch/arm64/kernel/head.S
··· 29 29 #include <asm/asm-offsets.h> 30 30 #include <asm/cache.h> 31 31 #include <asm/cputype.h> 32 + #include <asm/elf.h> 32 33 #include <asm/kernel-pgtable.h> 33 34 #include <asm/memory.h> 34 35 #include <asm/pgtable-hwdef.h> ··· 432 431 sub x2, x2, x0 433 432 bl __pi_memset 434 433 dsb ishst // Make zero page visible to PTW 434 + 435 + #ifdef CONFIG_RELOCATABLE 436 + 437 + /* 438 + * Iterate over each entry in the relocation table, and apply the 439 + * relocations in place. 440 + */ 441 + adr_l x8, __dynsym_start // start of symbol table 442 + adr_l x9, __reloc_start // start of reloc table 443 + adr_l x10, __reloc_end // end of reloc table 444 + 445 + 0: cmp x9, x10 446 + b.hs 2f 447 + ldp x11, x12, [x9], #24 448 + ldr x13, [x9, #-8] 449 + cmp w12, #R_AARCH64_RELATIVE 450 + b.ne 1f 451 + str x13, [x11] 452 + b 0b 453 + 454 + 1: cmp w12, #R_AARCH64_ABS64 455 + b.ne 0b 456 + add x12, x12, x12, lsl #1 // symtab offset: 24x top word 457 + add x12, x8, x12, lsr #(32 - 3) // ... shifted into bottom word 458 + ldr x15, [x12, #8] // Elf64_Sym::st_value 459 + add x15, x13, x15 460 + str x15, [x11] 461 + b 0b 462 + 463 + 2: 464 + #endif 435 465 436 466 adr_l sp, initial_sp, x4 437 467 mov x4, sp
+16
arch/arm64/kernel/vmlinux.lds.S
··· 87 87 EXIT_CALL 88 88 *(.discard) 89 89 *(.discard.*) 90 + *(.interp .dynamic) 90 91 } 91 92 92 93 . = KIMAGE_VADDR + TEXT_OFFSET; ··· 149 148 } 150 149 .altinstr_replacement : { 151 150 *(.altinstr_replacement) 151 + } 152 + .rela : ALIGN(8) { 153 + __reloc_start = .; 154 + *(.rela .rela*) 155 + __reloc_end = .; 156 + } 157 + .dynsym : ALIGN(8) { 158 + __dynsym_start = .; 159 + *(.dynsym) 160 + } 161 + .dynstr : { 162 + *(.dynstr) 163 + } 164 + .hash : { 165 + *(.hash) 152 166 } 153 167 154 168 . = ALIGN(PAGE_SIZE);