Skip to contentSkip to conversation

Allow CONFIG_DEBUG_SET_MODULE_RONX to be used on ARM

PATCH New Laura Abbott 1 participant 4 messages Jun 17, 2013

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

v2 cover Allow CONFIG_DEBUG_SET_MODULE_RONX to be used on ARM

Hi,

This is a series to allow CONFIG_DEBUG_SET_MODULE_RONX to be used on ARM. The current config description from x86 describes it best:

This option helps catch unintended modifications to loadable kernel module's text and read-only data. It also prevents execution of module data. Such protection may interfere with run-time code patching and dynamic kernel tracing - and they might also protect against certain classes of kernel exploits.

v2: Add module bounds checking per Russell, removed dsb per Catalin. Macrofied the set_memory_* functions to avoid so much code duplication.

Thanks,
Laura

---

 arch/arm/Kconfig.debug            |   11 ++++++++++
 arch/arm/include/asm/cacheflush.h |    5 ++++
 arch/arm/include/asm/pgtable.h    |    2 +
 arch/arm/mm/mmu.c                 |   38 +++++++++++++++++++++++++++++++++++++
 4 files changed, 56 insertions(+), 0 deletions(-)
#1 lore raw

PATCH v2 1/3 arm: Add definitions for pte_mkexec/pte_mknexec

Other architectures define pte_mkexec to mark a pte as executable. Add pte_mkexec for ARM to get the same functionality. Although no other architectures currently define it, also add pte_mknexec to explicitly allow a pte to be marked as non executable.

---
 arch/arm/include/asm/pgtable.h |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)
arch/arm/include/asm/pgtable.h +2 -0
index 9bcd262..135381b 100644
@@ -251,6 +251,8 @@ PTE_BIT_FUNC(mkclean,   &= ~L_PTE_DIRTY);
 PTE_BIT_FUNC(mkdirty,   |= L_PTE_DIRTY);
 PTE_BIT_FUNC(mkold,     &= ~L_PTE_YOUNG);
 PTE_BIT_FUNC(mkyoung,   |= L_PTE_YOUNG);
+PTE_BIT_FUNC(mkexec,   &= ~L_PTE_XN);
+PTE_BIT_FUNC(mknexec,   |= L_PTE_XN);
 
 static inline pte_t pte_mkspecial(pte_t pte) { return pte; }
 
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation
#2 lore raw

PATCH v2 2/3 arm: mm: Define set_memory_* functions for ARM

In reply to Laura Abbott

Other architectures define various set_memory functions to allow attributes to be changed (e.g. set_memory_x, set_memory_rw, etc.) Currently, these functions are missing on ARM. Define these in an appropriate manner for ARM.

---
 arch/arm/include/asm/cacheflush.h |    5 ++++
 arch/arm/mm/mmu.c                 |   38 +++++++++++++++++++++++++++++++++++++
 2 files changed, 43 insertions(+), 0 deletions(-)
arch/arm/include/asm/cacheflush.h +5 -0
index bff7138..55ed26b 100644
@@ -438,4 +438,9 @@ static inline void __sync_cache_range_r(volatile void *p, size_t size)
 #define sync_cache_w(ptr) __sync_cache_range_w(ptr, sizeof *(ptr))
 #define sync_cache_r(ptr) __sync_cache_range_r(ptr, sizeof *(ptr))
 
+int set_memory_ro(unsigned long addr, int numpages);
+int set_memory_rw(unsigned long addr, int numpages);
+int set_memory_x(unsigned long addr, int numpages);
+int set_memory_nx(unsigned long addr, int numpages);
+
 #endif
arch/arm/mm/mmu.c +38 -0
index e0d8565..53b0de4 100644
@@ -335,6 +335,44 @@ const struct mem_type *get_mem_type(unsigned int type)
 }
 EXPORT_SYMBOL(get_mem_type);
 
+#define PTE_SET_FN(_name, pteop) \
+static int pte_set_##_name(pte_t *ptep, pgtable_t token, unsigned long addr, \
+			void *data) \
+{ \
+	pte_t pte = pteop(*ptep); \
+\
+	set_pte_ext(ptep, pte, 0); \
+	return 0; \
+} \
+
+#define SET_MEMORY_FN(_name, callback) \
+int set_memory_##_name(unsigned long addr, int numpages) \
+{ \
+	unsigned long start = addr; \
+	unsigned long size = PAGE_SIZE*numpages; \
+	unsigned end = start + size; \
+\
+	if (start < MODULES_VADDR || start >= MODULES_END) \
+		return -EINVAL;\
+\
+	if (end < MODULES_VADDR || end >= MODULES_END) \
+		return -EINVAL; \
+\
+	apply_to_page_range(&init_mm, start, size, callback, NULL); \
+	flush_tlb_kernel_range(start, end); \
+	return 0;\
+}
+
+PTE_SET_FN(ro, pte_wrprotect)
+PTE_SET_FN(rw, pte_mkwrite)
+PTE_SET_FN(x, pte_mkexec)
+PTE_SET_FN(nx, pte_mknexec)
+
+SET_MEMORY_FN(ro, pte_set_ro)
+SET_MEMORY_FN(rw, pte_set_rw)
+SET_MEMORY_FN(x, pte_set_x)
+SET_MEMORY_FN(nx, pte_set_nx)
+
 /*
  * Adjust the PMD section entries according to the CPU in use.
  */
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation
#3 lore raw

PATCH v2 3/3 arm: add DEBUG_SET_MODULE_RONX option to Kconfig

In reply to Laura Abbott

Now that all the page setting infrastructure is in place, Add the DEBUG_SET_MODULE_RONX to the ARM debugging Kconfig. When turned on, data sections for modules will be marked as NX and read only sections will be marked as such.

---
 arch/arm/Kconfig.debug |   11 +++++++++++
 1 files changed, 11 insertions(+), 0 deletions(-)
arch/arm/Kconfig.debug +11 -0
index 1d41908..12bca63 100644
@@ -692,4 +692,15 @@ config PID_IN_CONTEXTIDR
 	  additional instructions during context switch. Say Y here only if you
 	  are planning to use hardware trace tools with this kernel.
 
+config DEBUG_SET_MODULE_RONX
+	bool "Set loadable kernel module data as NX and text as RO"
+	depends on MODULES
+	---help---
+	  This option helps catch unintended modifications to loadable
+	  kernel module's text and read-only data. It also prevents execution
+	  of module data. Such protection may interfere with run-time code
+	  patching and dynamic kernel tracing - and they might also protect
+	  against certain classes of kernel exploits.
+	  If in doubt, say "N".
+
 endmenu
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation