[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <1490811363-93944-5-git-send-email-keescook@chromium.org>
Date: Wed, 29 Mar 2017 11:15:56 -0700
From: Kees Cook <keescook@...omium.org>
To: kernel-hardening@...ts.openwall.com
Cc: Kees Cook <keescook@...omium.org>,
Mark Rutland <mark.rutland@....com>,
Andy Lutomirski <luto@...nel.org>,
Hoeun Ryu <hoeun.ryu@...il.com>,
PaX Team <pageexec@...email.hu>,
Emese Revfy <re.emese@...il.com>,
Russell King <linux@...linux.org.uk>, x86@...nel.org,
linux-kernel@...r.kernel.org, linux-arm-kernel@...ts.infradead.org
Subject: [RFC v2][PATCH 04/11] x86: Implement __arch_rare_write_begin/unmap()
Based on PaX's x86 pax_{open,close}_kernel() implementation, this
allows HAVE_ARCH_RARE_WRITE to work on x86.
There is missing work to sort out some header file issues where preempt.h
is missing, though it can't be included in pg_table.h unconditionally...
some other solution will be needed, perhaps an entirely separate header
file for rare_write()-related defines...
This patch is also missing paravirt support.
Signed-off-by: Kees Cook <keescook@...omium.org>
---
arch/x86/Kconfig | 1 +
arch/x86/include/asm/pgtable.h | 31 +++++++++++++++++++++++++++++++
2 files changed, 32 insertions(+)
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index cc98d5a294ee..2d1d707aa036 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -106,6 +106,7 @@ config X86
select HAVE_ARCH_KMEMCHECK
select HAVE_ARCH_MMAP_RND_BITS if MMU
select HAVE_ARCH_MMAP_RND_COMPAT_BITS if MMU && COMPAT
+ select HAVE_ARCH_RARE_WRITE
select HAVE_ARCH_SECCOMP_FILTER
select HAVE_ARCH_TRACEHOOK
select HAVE_ARCH_TRANSPARENT_HUGEPAGE
diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h
index 1cfb36b8c024..2e6bf661bb84 100644
--- a/arch/x86/include/asm/pgtable.h
+++ b/arch/x86/include/asm/pgtable.h
@@ -91,6 +91,37 @@ extern struct mm_struct *pgd_page_get_mm(struct page *page);
#endif /* CONFIG_PARAVIRT */
+/* TODO: Bad hack to deal with preempt macros being missing sometimes. */
+#ifndef preempt_disable
+#include <linux/preempt.h>
+#endif
+
+static __always_inline unsigned long __arch_rare_write_begin(void)
+{
+ unsigned long cr0;
+
+ preempt_disable();
+ barrier();
+ cr0 = read_cr0() ^ X86_CR0_WP;
+ BUG_ON(cr0 & X86_CR0_WP);
+ write_cr0(cr0);
+ barrier();
+ return cr0 ^ X86_CR0_WP;
+}
+
+static __always_inline unsigned long __arch_rare_write_end(void)
+{
+ unsigned long cr0;
+
+ barrier();
+ cr0 = read_cr0() ^ X86_CR0_WP;
+ BUG_ON(!(cr0 & X86_CR0_WP));
+ write_cr0(cr0);
+ barrier();
+ preempt_enable_no_resched();
+ return cr0 ^ X86_CR0_WP;
+}
+
/*
* The following only work if pte_present() is true.
* Undefined behaviour if not..
--
2.7.4
Powered by blists - more mailing lists