Red Hat的crash工具有个option是--kaslr
,一般解析ramdump会用,工具定义:
–kaslr offset | auto If x86, x86_64 or s390x kernel was configured with CONFIG_RANDOMIZE_BASE, the offset value is equal to the difference between the symbol values compiled into the vmlinux file and their relocated KASLR value. If set to auto, the KASLR offset value will be automatically calculated.
ok, what is CONFIG_RANDOMIZE_BASE
? 和arch有关,我们看下ARM64的定义,参考kernel 4.x。
config RANDOMIZE_BASE bool "Randomize the address of the kernel image" select ARM64_MODULE_PLTS if MODULES select RELOCATABLE help Randomizes the virtual address at which the kernel image is loaded, as a security feature that deters exploit attempts relying on knowledge of the location of kernel internals. It is the bootloader's job to provide entropy, by passing a random u64 value in /chosen/kaslr-seed at kernel entry. When booting via the UEFI stub, it will invoke the firmware's EFI_RNG_PROTOCOL implementation (if available) to supply entropy to the kernel proper. In addition, it will randomise the physical location of the kernel Image as well. If unsure, say N.
Kernel Address Space Layout Randomization (KASLR) Since the location of kernel memory is almost always instrumental in mounting a successful attack, making the location non-deterministic raises the difficulty of an exploit. (Note that this in turn makes the value of information exposures higher, since they may be used to discover desired memory locations.)
ok, 大概明了是一个安全特性,地址随机,防止被攻击。bootloader提供/chosen/kaslr-seed
:
QCOM LK:
162 163ifeq ($(ENABLE_KASLRSEED) ,1) 164 DEFINES += ENABLE_KASLRSEED_SUPPORT=1 165else 166 DEFINES += ENABLE_KASLRSEED_SUPPORT=0 167endif
2139 #if ENABLE_KASLRSEED_SUPPORT 2140 if (!scm_random((uintptr_t *)&kaslrseed, sizeof (kaslrseed))) {2141 2142 ret = fdt_appendprop_u64 (fdt, offset, (const char *)"kaslr-seed" , (uint64_t )kaslrseed);2143 if (ret)2144 dprintf(CRITICAL, "ERROR: Cannot update chosen node [kaslr-seed] - 0x%x\n" , ret);2145 else 2146 dprintf(CRITICAL, "kaslr-Seed is added to chosen node\n" );2147 } else {2148 dprintf(CRITICAL, "ERROR: Cannot generate Kaslr Seed\n" );2149 }2150 #endif
同样在UEFI下:
609 Status = GetKaslrSeed (&KaslrSeed);610 if (Status == EFI_SUCCESS) {611 612 ret = fdt_appendprop_u64 (fdt, offset, (CONST char *)"kaslr-seed" ,613 (UINT64)KaslrSeed);614 if (ret) {615 DEBUG ((EFI_D_INFO,616 "ERROR: Cannot update chosen node [kaslr-seed] - 0x%x\n" , ret));617 } else {618 DEBUG ((EFI_D_VERBOSE, "kaslr-Seed is added to chosen node\n" ));619 }620 } else {621 DEBUG ((EFI_D_INFO, "ERROR: Cannot generate Kaslr Seed - %r\n" , Status));622 }
一样一样的。
btw: arm貌似不支持CONFIG_RANDOMIZE_BASE。
内核有个参数可以直接disable:
nokaslr [KNL]
When CONFIG_RANDOMIZE_BASE is set, this disables
kernel and module base offset ASLR (Address Space
Layout Randomization).
kernel具体实现在arch/arm64/kernel/kaslr.c。
留意到高通的power code也有处理:
drivers/power/reset/msm-poweroff.c:261:
我们来看下:
#ifdef CONFIG_RANDOMIZE_BASE static void *kaslr_imem_addr;static void store_kaslr_offset (void ) { kaslr_imem_addr = map_prop_mem(KASLR_OFFSET_PROP); if (kaslr_imem_addr) { __raw_writel(0xdead4ead , kaslr_imem_addr); __raw_writel(KASLR_OFFSET_BIT_MASK & (kimage_vaddr - KIMAGE_VADDR), kaslr_imem_addr + 4 ); __raw_writel(KASLR_OFFSET_BIT_MASK & ((kimage_vaddr - KIMAGE_VADDR) >> 32 ), kaslr_imem_addr + 8 ); iounmap(kaslr_imem_addr); } }
保存这个地址到imem上:
kaslr_imem_addr --->| 0xdead4ead | kaslr_imem_addr+4 --->| (kimage_vaddr - KIMAGE_VADDR).L32 | kaslr_imem_addr+8 --->| (kimage_vaddr - KIMAGE_VADDR).H32 |
#define KASLR_OFFSET_PROP "qcom,msm-imem-kaslr_offset"
map_prop_mem()
:
static void *map_prop_mem (const char *propname) { struct device_node *np = of_find_compatible_node(NULL , NULL , propname); void *addr; if (!np) { pr_err("Unable to find DT property: %s\n" , propname); return NULL ; } addr = of_iomap(np, 0 ); if (!addr) pr_err("Unable to map memory for DT property: %s\n" , propname); return addr; }
ok,找的设备树,好嘛,dt qcom已经放到私有目录了,就不贴了, kaslr_imem_addr
地址来源设备树配置。
KIMAGE_VADDR
:
#define VA_BITS (CONFIG_ARM64_VA_BITS) #define VA_START (UL(0xffffffffffffffff) - \ (UL(1) << VA_BITS) + 1) #define PAGE_OFFSET (UL(0xffffffffffffffff) - \ (UL(1) << (VA_BITS - 1)) + 1) #define KIMAGE_VADDR (MODULES_END) #define MODULES_END (MODULES_VADDR + MODULES_VSIZE) #define MODULES_VADDR (VA_START + KASAN_SHADOW_SIZE) #define MODULES_VSIZE (SZ_128M)
可以从这些定义中找出。
kimage_vaddr
:
ENTRY(kimage_vaddr) .quad _text - TEXT_OFFSET
#define KERNEL_START _text #define KERNEL_END _end
TEXT_OFFSET
:
Say Y here if you want the image load offset (AKA TEXT_OFFSET) of the kernel to be randomized at build-time. When selected,
ifeq ($(CONFIG_ARM64_RANDOMIZE_TEXT_OFFSET) , y)TEXT_OFFSET := $(shell awk "BEGIN {srand() ; printf \"0x%06x\n\", \ int(2 * 1024 * 1024 / (2 ^ $(CONFIG_ARM64_PAGE_SHIFT) ) * \ rand()) * (2 ^ $(CONFIG_ARM64_PAGE_SHIFT) )}" )else TEXT_OFFSET := 0x00080000 //tj: here endif
留意一个接口:
static inline unsigned long kaslr_offset (void ) { return kimage_vaddr - KIMAGE_VADDR; }
panic时会dump这个kaslr_offset()
:
static int dump_kernel_offset (struct notifier_block *self, unsigned long v, void *p) { const unsigned long offset = kaslr_offset(); if (IS_ENABLED(CONFIG_RANDOMIZE_BASE) && offset > 0 ) { pr_emerg("Kernel Offset: 0x%lx from 0x%lx\n" , offset, KIMAGE_VADDR); } else { pr_emerg("Kernel Offset: disabled\n" ); } return 0 ; }
like:
505.654475: <6> Kernel Offset: 0x2c28000000 from 0xffffff8008000000
这个值也存到了QCOM的imem上,QCOM的ramparser会解析,在ramdump.py里:
def determine_kaslr_offset (self ): self.kaslr_offset = 0 if self.kaslr_addr is None : print_out_str('!!!! Kaslr addr is not provided.' ) else : kaslr_magic = self.read_u32(self.kaslr_addr, False ) if kaslr_magic != 0xdead4ead : print_out_str('!!!! Kaslr magic does not match.' ) else : self.kaslr_offset = self.read_u64(self.kaslr_addr + 4 , False ) print_out_str("The kaslr_offset extracted is: " + str (hex (self.kaslr_offset))) //tj:here
从地址self.kaslr_addr + 4
读8个字节,可不就是kaslr_offset()
嘛:]
版权声明: 本站所有文章均采用 CC BY-NC-SA 4.0 CN 许可协议。转载请注明原文链接!