Linux version: v6.0
Architecture: ARMv8
This post is the continuation of Linux ARM64 KASLR Implementation(1): Kernel Image Randomization.
Implementation mechanism of linear address randomization
In the previous article, it was mentioned that in __primary_switch, the program called __pi_kaslr_early_init to obtain the random offset used by KASLR and stored the low 20 bits in register x24. Then in __primary_switched, the value of x24 was stored in memstart_offset_seed.
1 | SYM_FUNC_START_LOCAL(__primary_switched) |
memstart_offset_seed is defined in arch/arm64/kernel/kaslr.c :
1 | u16 __initdata memstart_offset_seed; |
As you can see, it is a u16, so strh is used above to leave the remaining 16 bits of its random value.
arm64_memblock_init
The initialization process will then proceed to the arm64_memblock_init function.
1 | start_kernel |
Extracting the part related to KASLR:
1 | void __init arm64_memblock_init(void) |
Why does changing memstart_addr change the address of the linear space?
Linear Address Randomization
Let’s take a look at the page table operations that actually randomize the linear space. The page table for the linear mapping is created in paging_init → map_mem :
1 | static void __init map_mem(pgd_t *pgdp) |
__map_memblock
1 | static void __init __map_memblock(pgd_t *pgdp, phys_addr_t start, |
__create_pgd_mapping is analyzed in detail in Linux ARM64 __create_pgd_mapping analysis. The key point here is that a page table mapping from the physical address range [start - end) to the virtual address range [__phys_to_virt(start) - __phys_to_virt(end)) is created here. This means that __phys_to_virt determines the virtual address of the linear mapping.
__phys_to_virt
This macro is defined in arch/arm64/include/asm/memory.h :
1 |
In the same file, PHYS_OFFSET is defined as memstart_addr (pretty much)
1 | extern s64 memstart_addr; |
So we are back to memstart_addr. In arm64_memblock_init, memstart_addr is subtracted by a random value, which leads to the randomization of PHYS_OFFSET and __phys_to_virt. Therefore, the virtual address of the linear mapping created by paging_init → map_mem → ___map_memblock → __create_pgd_mapping is also randomized.