[PATCH v1] kexec/arch/i386: Add support for KASLR memory randomization
Baoquan He
bhe at redhat.com
Wed Aug 17 21:59:22 PDT 2016
On 08/17/16 at 09:47am, Thomas Garnier wrote:
> Multiple changes were made on KASLR (right now in linux-next). One of
> them is randomizing the virtual address of the physical mapping, vmalloc
> and vmemmap memory sections. It breaks kdump ability to read physical
> memory.
>
> This change identifies if KASLR memories randomization is used by
> checking if the page_offset_base variable exists. It search for the
> correct PAGE_OFFSET value by looking at the loaded memory section and
> find the lowest aligned on PUD (the randomization level).
>
> Related commits on linux-next:
> - 0483e1fa6e09d4948272680f691dccb1edb9677f: Base for randomization
> - 021182e52fe01c1f7b126f97fd6ba048dc4234fd: Enable for PAGE_OFFSET
Seems above two commits have been inside Linus's tree, while vmemmap
not yet.
>
> Signed-off-by: Thomas Garnier <thgarnie at google.com>
> ---
> kexec/arch/i386/crashdump-x86.c | 29 ++++++++++++++++++++++-------
> 1 file changed, 22 insertions(+), 7 deletions(-)
>
> diff --git a/kexec/arch/i386/crashdump-x86.c b/kexec/arch/i386/crashdump-x86.c
> index bbc0f35..ab833d4 100644
> --- a/kexec/arch/i386/crashdump-x86.c
> +++ b/kexec/arch/i386/crashdump-x86.c
> @@ -102,11 +102,10 @@ static int get_kernel_paddr(struct kexec_info *UNUSED(info),
> return -1;
> }
>
> -/* Retrieve kernel _stext symbol virtual address from /proc/kallsyms */
> -static unsigned long long get_kernel_stext_sym(void)
> +/* Retrieve kernel symbol virtual address from /proc/kallsyms */
> +static unsigned long long get_kernel_sym(const char *symbol)
> {
> const char *kallsyms = "/proc/kallsyms";
> - const char *stext = "_stext";
> char sym[128];
> char line[128];
> FILE *fp;
> @@ -122,13 +121,13 @@ static unsigned long long get_kernel_stext_sym(void)
> while(fgets(line, sizeof(line), fp) != NULL) {
> if (sscanf(line, "%Lx %c %s", &vaddr, &type, sym) != 3)
> continue;
> - if (strcmp(sym, stext) == 0) {
> - dbgprintf("kernel symbol %s vaddr = %16llx\n", stext, vaddr);
> + if (strcmp(sym, symbol) == 0) {
> + dbgprintf("kernel symbol %s vaddr = %16llx\n", symbol, vaddr);
> return vaddr;
> }
> }
>
> - fprintf(stderr, "Cannot get kernel %s symbol address\n", stext);
> + fprintf(stderr, "Cannot get kernel %s symbol address\n", symbol);
> return 0;
> }
>
> @@ -151,6 +150,8 @@ static int get_kernel_vaddr_and_size(struct kexec_info *UNUSED(info),
> off_t size;
> uint32_t elf_flags = 0;
> uint64_t stext_sym;
> + const unsigned long long pud_mask = ~((1 << 30) - 1);
> + unsigned long long vaddr, lowest_vaddr = 0;
>
> if (elf_info->machine != EM_X86_64)
> return 0;
> @@ -180,9 +181,23 @@ static int get_kernel_vaddr_and_size(struct kexec_info *UNUSED(info),
>
> end_phdr = &ehdr.e_phdr[ehdr.e_phnum];
>
> + /* Search for the real PAGE_OFFSET when KASLR memory randomization
> + * is enabled */
Yeah, this is necessary. That would be great if it can be put into
get_kernel_page_offset. But then it need parse kcore elf file again,
seems no better way.
> + if (get_kernel_sym("page_offset_base") != 0) {
> + for(phdr = ehdr.e_phdr; phdr != end_phdr; phdr++) {
> + if (phdr->p_type == PT_LOAD) {
> + vaddr = phdr->p_vaddr & pud_mask;
> + if (lowest_vaddr == 0 || lowest_vaddr > vaddr)
> + lowest_vaddr = vaddr;
> + }
> + }
> + if (lowest_vaddr != 0)
> + elf_info->page_offset = lowest_vaddr;
> + }
> +
> /* Traverse through the Elf headers and find the region where
> * _stext symbol is located in. That's where kernel is mapped */
> - stext_sym = get_kernel_stext_sym();
> + stext_sym = get_kernel_sym("_stext");
> for(phdr = ehdr.e_phdr; stext_sym && phdr != end_phdr; phdr++) {
> if (phdr->p_type == PT_LOAD) {
> unsigned long long saddr = phdr->p_vaddr;
> --
> 2.8.0.rc3.226.g39d4020
>
>
> _______________________________________________
> kexec mailing list
> kexec at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/kexec
More information about the kexec
mailing list