Allow CONFIG_DEBUG_SET_MODULE_RONX to be used on ARM
Subsystems (2)
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(-)
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
@@ -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
PATCH v2 2/3 arm: mm: Define set_memory_* functions for ARM
In reply to Laura AbbottOther 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
@@ -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
@@ -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
PATCH v2 3/3 arm: add DEBUG_SET_MODULE_RONX option to Kconfig
In reply to Laura AbbottNow 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
@@ -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