From 8ac0074944cc48258181d570b4f5362b09a2953c Mon Sep 17 00:00:00 2001 From: Prasad Sodagudi Date: Sat, 15 Nov 2014 22:48:10 +0530 Subject: [PATCH] arm: Add support for KERNEL_TEXT_RDONLY When using FORCE_PAGES to allocate the kernel memory into pages, provide an option to mark the the kernel text section as read only. Since the kernel text pages are always mapped in the kernel, anyone can write to the page if they have the address. Enable this option to mark the kernel text pages as read only to trigger a fault if any code attempts to write to a page that is part of the kernel text section. Change-Id: I27de98e2e82cf6dfe9370695239e1fae26ad0e97 Signed-off-by: Prasad Sodagudi --- arch/arm/Kconfig.debug | 13 +++++++++++++ arch/arm/include/asm/cacheflush.h | 6 ++++++ arch/arm/mm/init.c | 11 +++++++++++ 3 files changed, 30 insertions(+) diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug index 281298845958..c0654d7de648 100644 --- a/arch/arm/Kconfig.debug +++ b/arch/arm/Kconfig.debug @@ -98,6 +98,19 @@ config FREE_PAGES_RDONLY If unsure, say N. +config KERNEL_TEXT_RDONLY + bool "Set kernel text section pages as read only" + depends on FREE_PAGES_RDONLY + help + The kernel text pages are always mapped in the kernel. + This means that anyone can write to the page if they have + the address. Enable this option to mark the kernel text pages + as read only to trigger a fault if any code attempts to write + to a page part of the kernel text section. This may have a + performance impact. + + If unsure, say N. + # These options are only for real kernel hackers who want to get their hands dirty. config DEBUG_LL bool "Kernel low-level debugging functions (read help!)" diff --git a/arch/arm/include/asm/cacheflush.h b/arch/arm/include/asm/cacheflush.h index fceefb9bd25c..419345d872f4 100644 --- a/arch/arm/include/asm/cacheflush.h +++ b/arch/arm/include/asm/cacheflush.h @@ -463,6 +463,12 @@ 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); +#ifdef CONFIG_KERNEL_TEXT_RDONLY +void set_kernel_text_ro(void); +#else +static inline void set_kernel_text_ro(void) { } +#endif + #ifdef CONFIG_FREE_PAGES_RDONLY #define mark_addr_rdonly(a) set_memory_ro((unsigned long)a, 1); #define mark_addr_rdwrite(a) set_memory_rw((unsigned long)a, 1); diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index 9e64b24b545b..08fdf848b190 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c @@ -883,3 +883,14 @@ static int __init msm_krait_wfe_init(void) } pure_initcall(msm_krait_wfe_init); #endif + +#ifdef CONFIG_KERNEL_TEXT_RDONLY +void set_kernel_text_ro(void) +{ + unsigned long start = PFN_ALIGN(_stext); + unsigned long end = PFN_ALIGN(_etext); + + /* Set the kernel identity mapping for text RO. */ + set_memory_ro(start, (end - start) >> PAGE_SHIFT); +} +#endif