[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20190129003422.9328-14-rick.p.edgecombe@intel.com>
Date: Mon, 28 Jan 2019 16:34:15 -0800
From: Rick Edgecombe <rick.p.edgecombe@...el.com>
To: Andy Lutomirski <luto@...nel.org>, Ingo Molnar <mingo@...hat.com>
Cc: linux-kernel@...r.kernel.org, x86@...nel.org, hpa@...or.com,
Thomas Gleixner <tglx@...utronix.de>,
Borislav Petkov <bp@...en8.de>,
Nadav Amit <nadav.amit@...il.com>,
Dave Hansen <dave.hansen@...ux.intel.com>,
Peter Zijlstra <peterz@...radead.org>, linux_dti@...oud.com,
linux-integrity@...r.kernel.org,
linux-security-module@...r.kernel.org, akpm@...ux-foundation.org,
kernel-hardening@...ts.openwall.com, linux-mm@...ck.org,
will.deacon@....com, ard.biesheuvel@...aro.org,
kristen@...ux.intel.com, deneen.t.dock@...el.com,
Rick Edgecombe <rick.p.edgecombe@...el.com>
Subject: [PATCH v2 13/20] Add set_alias_ function and x86 implementation
This adds two new functions set_alias_default_noflush and
set_alias_nv_noflush for setting the alias mapping for the page to its
default valid permissions and to an invalid state that cannot be cached in
a TLB, respectively. These functions to not flush the TLB.
Note, __kernel_map_pages does something similar but flushes the TLB and
doesn't reset the permission bits to default on all architectures.
There is also an ARCH config ARCH_HAS_SET_ALIAS for specifying whether
these have an actual implementation or a default empty one.
Cc: Dave Hansen <dave.hansen@...ux.intel.com>
Cc: Andy Lutomirski <luto@...nel.org>
Cc: Peter Zijlstra <peterz@...radead.org>
Signed-off-by: Rick Edgecombe <rick.p.edgecombe@...el.com>
---
arch/Kconfig | 4 ++++
arch/x86/Kconfig | 1 +
arch/x86/include/asm/set_memory.h | 3 +++
arch/x86/mm/pageattr.c | 14 +++++++++++---
include/linux/set_memory.h | 10 ++++++++++
5 files changed, 29 insertions(+), 3 deletions(-)
diff --git a/arch/Kconfig b/arch/Kconfig
index 4cfb6de48f79..4ef9db190f2d 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -249,6 +249,10 @@ config ARCH_HAS_FORTIFY_SOURCE
config ARCH_HAS_SET_MEMORY
bool
+# Select if arch has all set_alias_nv/default() functions
+config ARCH_HAS_SET_ALIAS
+ bool
+
# Select if arch init_task must go in the __init_task_data section
config ARCH_TASK_STRUCT_ON_STACK
bool
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 26387c7bf305..42bb1df4ea94 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -66,6 +66,7 @@ config X86
select ARCH_HAS_UACCESS_FLUSHCACHE if X86_64
select ARCH_HAS_UACCESS_MCSAFE if X86_64 && X86_MCE
select ARCH_HAS_SET_MEMORY
+ select ARCH_HAS_SET_ALIAS
select ARCH_HAS_STRICT_KERNEL_RWX
select ARCH_HAS_STRICT_MODULE_RWX
select ARCH_HAS_SYNC_CORE_BEFORE_USERMODE
diff --git a/arch/x86/include/asm/set_memory.h b/arch/x86/include/asm/set_memory.h
index 07a25753e85c..2ef4e4222df1 100644
--- a/arch/x86/include/asm/set_memory.h
+++ b/arch/x86/include/asm/set_memory.h
@@ -85,6 +85,9 @@ int set_pages_nx(struct page *page, int numpages);
int set_pages_ro(struct page *page, int numpages);
int set_pages_rw(struct page *page, int numpages);
+int set_alias_nv_noflush(struct page *page);
+int set_alias_default_noflush(struct page *page);
+
extern int kernel_set_to_readonly;
void set_kernel_text_rw(void);
void set_kernel_text_ro(void);
diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c
index 4f8972311a77..3a51915a1410 100644
--- a/arch/x86/mm/pageattr.c
+++ b/arch/x86/mm/pageattr.c
@@ -2209,8 +2209,6 @@ int set_pages_rw(struct page *page, int numpages)
return set_memory_rw(addr, numpages);
}
-#ifdef CONFIG_DEBUG_PAGEALLOC
-
static int __set_pages_p(struct page *page, int numpages)
{
unsigned long tempaddr = (unsigned long) page_address(page);
@@ -2249,6 +2247,17 @@ static int __set_pages_np(struct page *page, int numpages)
return __change_page_attr_set_clr(&cpa, 0);
}
+int set_alias_nv_noflush(struct page *page)
+{
+ return __set_pages_np(page, 1);
+}
+
+int set_alias_default_noflush(struct page *page)
+{
+ return __set_pages_p(page, 1);
+}
+
+#ifdef CONFIG_DEBUG_PAGEALLOC
void __kernel_map_pages(struct page *page, int numpages, int enable)
{
if (PageHighMem(page))
@@ -2282,7 +2291,6 @@ void __kernel_map_pages(struct page *page, int numpages, int enable)
}
#ifdef CONFIG_HIBERNATION
-
bool kernel_page_present(struct page *page)
{
unsigned int level;
diff --git a/include/linux/set_memory.h b/include/linux/set_memory.h
index 2a986d282a97..d19481ac6a8f 100644
--- a/include/linux/set_memory.h
+++ b/include/linux/set_memory.h
@@ -10,6 +10,16 @@
#ifdef CONFIG_ARCH_HAS_SET_MEMORY
#include <asm/set_memory.h>
+#ifndef CONFIG_ARCH_HAS_SET_ALIAS
+static inline int set_alias_nv_noflush(struct page *page)
+{
+ return 0;
+}
+static inline int set_alias_default_noflush(struct page *page)
+{
+ return 0;
+}
+#endif
#else
static inline int set_memory_ro(unsigned long addr, int numpages) { return 0; }
static inline int set_memory_rw(unsigned long addr, int numpages) { return 0; }
--
2.17.1
Powered by blists - more mailing lists