Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Date: Wed, 16 Nov 2016 22:39:38 +0800
From: Gengjia Chen <chengjia4574@...il.com>
To: kernel-hardening@...ts.openwall.com
Cc: Kees Cook <keescook@...omium.org>
Subject: patches for __write_rarely section

Hello kees and everyone :

This email introduces two patches.

Patch 1 introduce the write-rarely memory section for
those kernel objects which are read only mostly
but need to be written to sometimes.

Patch 2 introduce two helper functions (mark_wrdata_rw/
mark_wrdata_ro) to make __write_rarely memory section
writable or unwritable. They play like the pax_open_kernel/
pax_close_kernel functions in grsecurity patch.Right now
this only been implemented on arm32.

These two patches were based on the work by PaxTeam and Grsecurity.
These two patched were based on https://github.com/torvalds/linux.git :
27bcd37e0240bbe33f0efe244b5aad52104115b3

By the way, I am a new recruit for kernel coding so I hope that
someone can review these patches and tell me what to do next.
Also, I am working on the implement of mark_wrdata_rw/mark_wrdata_ro
on aarch64, any advice about that would be appreciated.

==== patch 1 =====

>From 7ee1ed5a723723112167ca8603f4e2945d133b33 Mon Sep 17 00:00:00 2001
From: chengengjia <chengjia4574@...il.com>
Date: Wed, 16 Nov 2016 21:46:49 +0800
Subject: [PATCH] arch: introduce write-rarely memory section

This introduces __write_rarely section as a way
to mark those memory that read only in most case,
but also need to be written to sometimes.

Signed-off-by: chengengjia <chengjia4574@...il.com>
---
 include/asm-generic/vmlinux.lds.h | 9 +++++++++
 include/linux/cache.h             | 9 +++++++++
 2 files changed, 18 insertions(+)

diff --git a/include/asm-generic/vmlinux.lds.h
b/include/asm-generic/vmlinux.lds.h
index 3074796..684bcf2 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -263,6 +263,14 @@
 #endif

 /*
+ * Allow architectures to handle write_rarely data on their
+ * own by defining an empty WRITE_RARELY_DATA.
+ */
+#ifndef WRITE_RARELY_DATA
+#define WRITE_RARELY_DATA *(.data..write_rarely)
+#endif
+
+/*
  * Read only Data
  */
 #define RO_DATA_SECTION(align) \
@@ -271,6 +279,7 @@
  VMLINUX_SYMBOL(__start_rodata) = .; \
  *(.rodata) *(.rodata.*) \
  RO_AFTER_INIT_DATA /* Read only after init */ \
+ WRITE_RARELY_DATA /* write rarely*/ \
  *(__vermagic) /* Kernel version magic */ \
  . = ALIGN(8); \
  VMLINUX_SYMBOL(__start___tracepoints_ptrs) = .; \
diff --git a/include/linux/cache.h b/include/linux/cache.h
index 1be04f8..d2c30cd 100644
--- a/include/linux/cache.h
+++ b/include/linux/cache.h
@@ -30,6 +30,15 @@
 #define __ro_after_init
__attribute__((__section__(".data..ro_after_init")))
 #endif

+/*
+ * __write_rarely is used to mark things that are read-only mostly but
need to be
+ * written to sometimes. To write to __write_rarely variables,
mark_wrdata_rw()
+ * need to be called, after write, mark_wrdata_ro() should be called.
+ */
+#ifndef __write_rarely
+#define __write_rarely __attribute__((__section__(".data..write_rarely")))
+#endif
+
 #ifndef ____cacheline_aligned
 #define ____cacheline_aligned __attribute__((__aligned__(SMP_CACHE_BYTES)))
 #endif
-- 
1.9.1


==== patch 2 =====

>From 0472f3f14532577a1963d517da8a0edfe1d99375 Mon Sep 17 00:00:00 2001
From: chengengjia <chengjia4574@...il.com>
Date: Wed, 16 Nov 2016 22:16:43 +0800
Subject: [PATCH] arch: arm: add mark_wrdata_rw/mark_wrdata_ro functions

This introduces mark_wrdata_rw/mark_wrdata_ro to
mark __write_rarely section writable/unwritable.
Based on work by PaxTeam and Grsecurity.

Signed-off-by: chengengjia <chengjia4574@...il.com>
---
 arch/arm/include/asm/domain.h  | 14 ++++++++++++++
 arch/arm/include/asm/pgtable.h | 38 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 52 insertions(+)

diff --git a/arch/arm/include/asm/domain.h b/arch/arm/include/asm/domain.h
index 99d9f63..01f18a5 100644
--- a/arch/arm/include/asm/domain.h
+++ b/arch/arm/include/asm/domain.h
@@ -54,6 +54,10 @@
 #else
 #define DOMAIN_MANAGER 1
 #endif
+#ifdef  CONFIG_DEBUG_RODATA
+#define DOMAIN_OPENKERN 3
+#endif
+

 #define domain_mask(dom) ((3) << (2 * (dom)))
 #define domain_val(dom,type) ((type) << (2 * (dom)))
@@ -124,6 +128,16 @@ static inline void set_domain(unsigned val)
  set_domain(domain); \
  } while (0)

+#elif defined(CONFIG_DEBUG_RODATA)
+#define modify_domain(dom,type)                                 \
+        do {                                                    \
+                struct thread_info *thread = current_thread_info(); \
+                unsigned int domain = get_domain();             \
+                domain &= ~domain_mask(dom);                    \
+                domain = domain | domain_val(dom, type);        \
+                thread->cpu_domain = domain;                    \
+                set_domain(domain);                             \
+        } while (0)
 #else
 static inline void modify_domain(unsigned dom, unsigned type) { }
 #endif
diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h
index a8d656d..5e6f553 100644
--- a/arch/arm/include/asm/pgtable.h
+++ b/arch/arm/include/asm/pgtable.h
@@ -56,6 +56,44 @@
 #define pmd_ERROR(pmd) __pmd_error(__FILE__, __LINE__, pmd)
 #define pgd_ERROR(pgd) __pgd_error(__FILE__, __LINE__, pgd)

+#ifdef  CONFIG_DEBUG_RODATA
+#include <asm/domain.h>
+#include <linux/thread_info.h>
+#include <linux/preempt.h>
+
+static inline int test_domain(int domain, int domaintype)
+{
+        return ((current_thread_info()->cpu_domain) & domain_val(domain,
3))
+ == domain_val(domain, domaintype);
+}
+
+static inline unsigned long mark_wrdata_rw(void) {
+#ifdef CONFIG_ARM_LPAE
+        /* TODO */
+#else
+        preempt_disable();
+        BUG_ON(test_domain(DOMAIN_KERNEL, DOMAIN_OPENKERN));
+        modify_domain(DOMAIN_KERNEL, DOMAIN_OPENKERN);
+#endif
+        return 0;
+}
+
+static inline unsigned long mark_wrdata_ro(void) {
+#ifdef CONFIG_ARM_LPAE
+        /* TODO */
+#else
+        BUG_ON(test_domain(DOMAIN_KERNEL, DOMAIN_MANAGER));
+        modify_domain(DOMAIN_KERNEL, DOMAIN_MANAGER);
+        preempt_enable_no_resched();
+#endif
+        return 0;
+}
+#else
+static inline unsigned long mark_wrdata_rw(void) { return 0; }
+static inline unsigned long mark_wrdata_ro(void) { return 0; }
+#endif
+
+
 /*
  * This is the lowest virtual address we can permit any user space
  * mapping to be mapped at.  This is particularly important for
-- 
1.9.1


=====

Content of type "text/html" skipped

Powered by blists - more mailing lists

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.