Received: by 2002:ac0:a5a7:0:0:0:0:0 with SMTP id m36-v6csp155222imm; Thu, 2 Aug 2018 16:00:26 -0700 (PDT) X-Google-Smtp-Source: AAOMgpfSFVfoYIwWCP0u4Ke/IJGatP69wEWxyUjgZZay9x6ZWLGUoX5GruQoR5eTTW3TaGGCkFA7 X-Received: by 2002:a63:d351:: with SMTP id u17-v6mr1229650pgi.366.1533250826143; Thu, 02 Aug 2018 16:00:26 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1533250826; cv=none; d=google.com; s=arc-20160816; b=piLXhGjKk7KfvZUog5gTWyscpy7UWWJWnhqSoR5WChubm0vIz7HGfidXrGmwZr+WZ+ YKFEEErrFq/V2ZdX06uAn8qwxNiJcHWLtE9TvbbGhVCHV7vBf3yBmHc6mJDB3Fqws9Wg wLfnz+iqhNpUB4Mpynts6cSOqp1zk1/ZqOq5NODix0LtrXvS69C1RpW5wc1fhDbym40N 3KVqjxuybC/RNCGRlmlYFM2TntrX66GF7dU+wsGIt1JRZ9QdMsJPFjCg4huubjbl+2bx BTEcaIVEyfFZqkpmFz6Cb5xMx3Uy+s+Ay2CWb3FD6TAumoMYAQpUykDAFPOyTSfnlbJW hpng== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:message-id:in-reply-to:references:date :from:cc:to:subject:arc-authentication-results; bh=Fe7uvsJ03WA/ZSjcs5bwM7LbZYMLA/FzWbq2ehn4Mlc=; b=xFEXGQIRSqjH5YEhT6t7zuQxYoS/LnEniYJogM9XnnQr2IB3PuNlcR7q7OIEi2OYmP mbPKVm65jtPTblhjr7BVrG24Ij7gZvO5iKaP+oyLioAuf5NzQPTM9Q82ScGBSGslCGev USzWQNcJ7LYRdb5OuHzk6obnrg7VnZ3YAXEhf3J+EVUTMFUsST74uaAokTeltI6BTKex fPcULM3m9bZCIBP+rpoat1DhO8ZCAQfgbLVbHFQdWZUCpN+H9KZz8RyYFF22cPUI5WsB Is+rgmntiuLM+tjmJ1s/JvNm9BTdIHDwv9oiKeozsXN31bfQHwBh4JNBQ1iMfOMn2LvP 0ZXw== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=intel.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id bi1-v6si2307482plb.399.2018.08.02.16.00.11; Thu, 02 Aug 2018 16:00:26 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=intel.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1732328AbeHCAv6 (ORCPT + 99 others); Thu, 2 Aug 2018 20:51:58 -0400 Received: from mga11.intel.com ([192.55.52.93]:40743 "EHLO mga11.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727002AbeHCAv6 (ORCPT ); Thu, 2 Aug 2018 20:51:58 -0400 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by fmsmga102.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 02 Aug 2018 15:58:40 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.51,437,1526367600"; d="scan'208";a="77872532" Received: from viggo.jf.intel.com (HELO localhost.localdomain) ([10.54.77.144]) by fmsmga001.fm.intel.com with ESMTP; 02 Aug 2018 15:58:40 -0700 Subject: [PATCH 5/7] x86/mm/init: remove freed kernel image areas from alias mapping To: linux-kernel@vger.kernel.org Cc: Dave Hansen , keescook@google.com, tglx@linutronix.de, mingo@kernel.org, aarcange@redhat.com, jgross@suse.com, jpoimboe@redhat.com, gregkh@linuxfoundation.org, peterz@infradead.org, hughd@google.com, torvalds@linux-foundation.org, bp@alien8.de, luto@kernel.org, ak@linux.intel.com From: Dave Hansen Date: Thu, 02 Aug 2018 15:58:31 -0700 References: <20180802225823.4711C55B@viggo.jf.intel.com> In-Reply-To: <20180802225823.4711C55B@viggo.jf.intel.com> Message-Id: <20180802225831.5F6A2BFC@viggo.jf.intel.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Dave Hansen The kernel image is mapped into two places in the virtual address space (addresses without KASLR, of course): 1. The kernel direct map (0xffff880000000000) 2. The "high kernel map" (0xffffffff81000000) We actually execute out of #2. If we get the address of a kernel symbol, it points to #2, but almost all physical-to-virtual translations point to #1. Parts of the "high kernel map" alias are mapped in the userspace page tables with the Global bit for performance reasons. The parts that we map to userspace do not (er, should not) have secrets. This is fine, except that some areas in the kernel image that are adjacent to the non-secret-containing areas are unused holes. We free these holes back into the normal page allocator and reuse them as normal kernel memory. The memory will, of course, get *used* via the normal map, but the alias mapping is kept. This otherwise unused alias mapping of the holes will, by default keep the Global bit, be mapped out to userspace, and be vulnerable to Meltdown. Remove the alias mapping of these pages entirely. This is likely to fracture the 2M page mapping the kernel image near these areas, but this should affect a minority of the area. The pageattr code changes *all* aliases mapping the physical pages that it operates on (by default). We only want to modify a single alias, so we need to tweak its behavior. This unmapping behavior is currently dependent on PTI being in place. Going forward, we should at least consider doing this for all configurations. Having an extra read-write alias for memory is not exactly ideal for debugging things like random memory corruption and this does undercut features like DEBUG_PAGEALLOC or future work like eXclusive Page Frame Ownership (XPFO). Before this patch: current_kernel:---[ High Kernel Mapping ]--- current_kernel-0xffffffff80000000-0xffffffff81000000 16M pmd current_kernel-0xffffffff81000000-0xffffffff81e00000 14M ro PSE GLB x pmd current_kernel-0xffffffff81e00000-0xffffffff81e11000 68K ro GLB x pte current_kernel-0xffffffff81e11000-0xffffffff82000000 1980K RW NX pte current_kernel-0xffffffff82000000-0xffffffff82600000 6M ro PSE GLB NX pmd current_kernel-0xffffffff82600000-0xffffffff82c00000 6M RW PSE NX pmd current_kernel-0xffffffff82c00000-0xffffffff82e00000 2M RW NX pte current_kernel-0xffffffff82e00000-0xffffffff83200000 4M RW PSE NX pmd current_kernel-0xffffffff83200000-0xffffffffa0000000 462M pmd current_user:---[ High Kernel Mapping ]--- current_user-0xffffffff80000000-0xffffffff81000000 16M pmd current_user-0xffffffff81000000-0xffffffff81e00000 14M ro PSE GLB x pmd current_user-0xffffffff81e00000-0xffffffff81e11000 68K ro GLB x pte current_user-0xffffffff81e11000-0xffffffff82000000 1980K RW NX pte current_user-0xffffffff82000000-0xffffffff82600000 6M ro PSE GLB NX pmd current_user-0xffffffff82600000-0xffffffffa0000000 474M pmd After this patch: current_kernel:---[ High Kernel Mapping ]--- current_kernel-0xffffffff80000000-0xffffffff81000000 16M pmd current_kernel-0xffffffff81000000-0xffffffff81e00000 14M ro PSE GLB x pmd current_kernel-0xffffffff81e00000-0xffffffff81e11000 68K ro GLB x pte current_kernel-0xffffffff81e11000-0xffffffff82000000 1980K pte current_kernel-0xffffffff82000000-0xffffffff82400000 4M ro PSE GLB NX pmd current_kernel-0xffffffff82400000-0xffffffff82488000 544K ro NX pte current_kernel-0xffffffff82488000-0xffffffff82600000 1504K pte current_kernel-0xffffffff82600000-0xffffffff82c00000 6M RW PSE NX pmd current_kernel-0xffffffff82c00000-0xffffffff82c0d000 52K RW NX pte current_kernel-0xffffffff82c0d000-0xffffffff82dc0000 1740K pte current_user:---[ High Kernel Mapping ]--- current_user-0xffffffff80000000-0xffffffff81000000 16M pmd current_user-0xffffffff81000000-0xffffffff81e00000 14M ro PSE GLB x pmd current_user-0xffffffff81e00000-0xffffffff81e11000 68K ro GLB x pte current_user-0xffffffff81e11000-0xffffffff82000000 1980K pte current_user-0xffffffff82000000-0xffffffff82400000 4M ro PSE GLB NX pmd current_user-0xffffffff82400000-0xffffffff82488000 544K ro NX pte current_user-0xffffffff82488000-0xffffffff82600000 1504K pte current_user-0xffffffff82600000-0xffffffffa0000000 474M pmd Signed-off-by: Dave Hansen Cc: Kees Cook Cc: Thomas Gleixner Cc: Ingo Molnar Cc: Andrea Arcangeli Cc: Juergen Gross Cc: Josh Poimboeuf Cc: Greg Kroah-Hartman Cc: Peter Zijlstra Cc: Hugh Dickins Cc: Linus Torvalds Cc: Borislav Petkov Cc: Andy Lutomirski Cc: Andi Kleen --- b/arch/x86/include/asm/set_memory.h | 1 + b/arch/x86/mm/init.c | 25 +++++++++++++++++++++++-- b/arch/x86/mm/pageattr.c | 13 +++++++++++++ 3 files changed, 37 insertions(+), 2 deletions(-) diff -puN arch/x86/include/asm/set_memory.h~x86-unmap-freed-areas-from-kernel-image arch/x86/include/asm/set_memory.h --- a/arch/x86/include/asm/set_memory.h~x86-unmap-freed-areas-from-kernel-image 2018-08-02 14:14:49.462483274 -0700 +++ b/arch/x86/include/asm/set_memory.h 2018-08-02 14:14:49.471483274 -0700 @@ -46,6 +46,7 @@ int set_memory_np(unsigned long addr, in int set_memory_4k(unsigned long addr, int numpages); int set_memory_encrypted(unsigned long addr, int numpages); int set_memory_decrypted(unsigned long addr, int numpages); +int set_memory_np_noalias(unsigned long addr, int numpages); int set_memory_array_uc(unsigned long *addr, int addrinarray); int set_memory_array_wc(unsigned long *addr, int addrinarray); diff -puN arch/x86/mm/init.c~x86-unmap-freed-areas-from-kernel-image arch/x86/mm/init.c --- a/arch/x86/mm/init.c~x86-unmap-freed-areas-from-kernel-image 2018-08-02 14:14:49.463483274 -0700 +++ b/arch/x86/mm/init.c 2018-08-02 14:14:49.471483274 -0700 @@ -780,8 +780,29 @@ void free_init_pages(char *what, unsigne */ void free_kernel_image_pages(void *begin, void *end) { - free_init_pages("unused kernel image", - (unsigned long)begin, (unsigned long)end); + unsigned long begin_ul = (unsigned long)begin; + unsigned long end_ul = (unsigned long)end; + unsigned long len_pages = (end_ul - begin_ul) >> PAGE_SHIFT; + + + free_init_pages("unused kernel image", begin_ul, end_ul); + + /* + * PTI maps some of the kernel into userspace. For + * performance, this includes some kernel areas that + * do not contain secrets. Those areas might be + * adjacent to the parts of the kernel image being + * freed, which may contain secrets. Remove the + * "high kernel image mapping" for these freed areas, + * ensuring they are not even potentially vulnerable + * to Meltdown regardless of the specific optimizations + * PTI is currently using. + * + * The "noalias" prevents unmapping the direct map + * alias which is needed to access the freed pages. + */ + if (cpu_feature_enabled(X86_FEATURE_PTI)) + set_memory_np_noalias(begin_ul, len_pages); } void __ref free_initmem(void) diff -puN arch/x86/mm/pageattr.c~x86-unmap-freed-areas-from-kernel-image arch/x86/mm/pageattr.c --- a/arch/x86/mm/pageattr.c~x86-unmap-freed-areas-from-kernel-image 2018-08-02 14:14:49.466483274 -0700 +++ b/arch/x86/mm/pageattr.c 2018-08-02 14:14:49.472483274 -0700 @@ -53,6 +53,7 @@ static DEFINE_SPINLOCK(cpa_lock); #define CPA_FLUSHTLB 1 #define CPA_ARRAY 2 #define CPA_PAGES_ARRAY 4 +#define CPA_NO_CHECK_ALIAS 8 /* Do not search for aliases */ #ifdef CONFIG_PROC_FS static unsigned long direct_pages_count[PG_LEVEL_NUM]; @@ -1486,6 +1487,9 @@ static int change_page_attr_set_clr(unsi /* No alias checking for _NX bit modifications */ checkalias = (pgprot_val(mask_set) | pgprot_val(mask_clr)) != _PAGE_NX; + /* Never check aliases if the caller asks for it explicitly: */ + if (checkalias && (in_flag & CPA_NO_CHECK_ALIAS)) + checkalias = 0; ret = __change_page_attr_set_clr(&cpa, checkalias); @@ -1772,6 +1776,15 @@ int set_memory_np(unsigned long addr, in return change_page_attr_clear(&addr, numpages, __pgprot(_PAGE_PRESENT), 0); } +int set_memory_np_noalias(unsigned long addr, int numpages) +{ + int cpa_flags = CPA_NO_CHECK_ALIAS; + + return change_page_attr_set_clr(&addr, numpages, __pgprot(0), + __pgprot(_PAGE_PRESENT), 0, + cpa_flags, NULL); +} + int set_memory_4k(unsigned long addr, int numpages) { return change_page_attr_set_clr(&addr, numpages, __pgprot(0), _