From patchwork Wed Aug 17 16:47:42 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thomas Garnier X-Patchwork-Id: 9286129 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id EBBF460839 for ; Wed, 17 Aug 2016 16:48:34 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E03C0293A6 for ; Wed, 17 Aug 2016 16:48:34 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id D49F6293E0; Wed, 17 Aug 2016 16:48:34 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.1 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, RCVD_IN_DNSWL_MED, T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from mother.openwall.net (mother.openwall.net [195.42.179.200]) by mail.wl.linuxfoundation.org (Postfix) with SMTP id 02BEB293B4 for ; Wed, 17 Aug 2016 16:48:33 +0000 (UTC) Received: (qmail 11794 invoked by uid 550); 17 Aug 2016 16:48:32 -0000 Mailing-List: contact kernel-hardening-help@lists.openwall.com; run by ezmlm Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-ID: Reply-To: kernel-hardening@lists.openwall.com Delivered-To: mailing list kernel-hardening@lists.openwall.com Received: (qmail 11762 invoked from network); 17 Aug 2016 16:48:30 -0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=from:to:cc:subject:date:message-id; bh=8z/vQr0e7bHmCzrL1r/4e5suhvvuJOvpKP8ayDQ63FQ=; b=WjBdd2yJv/vPgCWktjMFRhhu1fFRG1vni/ZaOYbgaRK6iqTAIycO95X9kC+j2fqnnj eyvoBbUw4DMS7e/8/NeePGXYtSleDiAA5VrPN7W6OoawpQPXmLXM6a6+Gt78J/rN1cmp NicL3F4AoEUXO/f5EH24unCgnXiAzkxfDK3jVK8SvHHMlzg3MazEA+4MyDbgC2Bpaev5 e7hHieTWx7uaFxIOWgMKUMVdTELsWoFFcBNcRS7h+2sGJPsnD+O8WwmtJFwRMauXK30i KKzbCRUxDMOLmLiU3U7Z2RqqoiBNbD3JXDx51er4MmmpD/HvLIh+zTa/6w1e5iXynlso ZYAg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=8z/vQr0e7bHmCzrL1r/4e5suhvvuJOvpKP8ayDQ63FQ=; b=mYB6Xp/fUgh2s0yBt5QrPaFlb1Kdggbp+qmalHDO4/Na4gLwKp7McD/1cqbtzQCZLT NWl11Sp+Y71LOprgeRqq6WNUVvlNq6n3g5OfygphboWUxcHJ35I5yoNBiAVHMprtufdp WydsWaFg5Rq1z4tnQYTpwHB5Zt7rwaisjv6stwYbvzxBxDBAAVFULcFHaMAM+rZ7qe9W hTMgoJbwNuL1LJyX2uGF3EKIiyqjT3mdW6BnndgMYh52VnHCCRJPLBa60OlCo56ba+8O ZVdIa1OdRp89/97wrzbJ3dsHHp7WAWZDlPy8Cw9TC3wk6I46yvqugHw9Xy2dk9Wpuo97 dGzQ== X-Gm-Message-State: AEkoouvxXuUIe+Cgb8b1bIGCvsMks6Nn1oFwMQG/MfZQJpN5pxctOzHdMTIJgn0ylis93ub+ X-Received: by 10.67.1.35 with SMTP id bd3mr75996610pad.16.1471452498081; Wed, 17 Aug 2016 09:48:18 -0700 (PDT) From: Thomas Garnier To: kexec@lists.infradead.org Cc: horms@verge.net.au, keescook@chromium.org, kernel-hardening@lists.openwall.com, Thomas Garnier Date: Wed, 17 Aug 2016 09:47:42 -0700 Message-Id: <1471452462-42560-1-git-send-email-thgarnie@google.com> X-Mailer: git-send-email 2.8.0.rc3.226.g39d4020 Subject: [kernel-hardening] [PATCH v1] kexec/arch/i386: Add support for KASLR memory randomization X-Virus-Scanned: ClamAV using ClamSMTP 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 Signed-off-by: Thomas Garnier --- 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 */ + 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;