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.