aboutsummaryrefslogtreecommitdiff
path: root/arch/arm/include/asm/rodata.h
diff options
context:
space:
mode:
authorColin Cross <ccross@android.com>2011-08-11 17:15:24 -0700
committerArve Hjønnevåg <arve@android.com>2013-07-01 13:38:49 -0700
commitb4ef696dc1fc4f5c2a8bfa84dde2586e9a652e23 (patch)
tree8c181dd46e6aae72a04e923388adbd7cb268ec1f /arch/arm/include/asm/rodata.h
parent607503f2a789468fcd51549bed984a5153c0e4e1 (diff)
downloadlinaro-lsk-b4ef696dc1fc4f5c2a8bfa84dde2586e9a652e23.tar.gz
ARM: allow the kernel text section to be made read-only
This patch implements CONFIG_DEBUG_RODATA, allowing the kernel text section to be marked read-only in order to catch bugs that write over the kernel. This requires mapping the kernel code, plus up to 4MB, using pages instead of sections, which can increase TLB pressure. The kernel is normally mapped using 1MB section entries in the first level page table, and the first level page table is copied into every mm. This prevents marking the kernel text read-only, because the 1MB section entries are too large granularity to separate the init section, which is reused as read-write memory after init, and the kernel text section. Also, the top level page table for every process would need to be updated, which is not possible to do safely and efficiently on SMP. To solve both problems, allow alloc_init_pte to overwrite an existing section entry with a fully-populated second level page table. When CONFIG_DEBUG_RODATA is set, all the section entries that overlap the kernel text section will be replaced with page mappings. The kernel always uses a pair of 2MB-aligned 1MB sections, so up to 2MB of memory before and after the kernel may end up page mapped. When the top level page tables are copied into each process the second level page tables are not copied, leaving a single second level page table that will affect all processes on all cpus. To mark a page read-only, the second level page table is located using the pointer in the first level page table for the current process, and the supervisor RO bit is flipped atomically. Once all pages have been updated, all TLBs are flushed to ensure the changes are visible on all cpus. If CONFIG_DEBUG_RODATA is not set, the kernel will be mapped using the normal 1MB section entries. Change-Id: I94fae337f882c2e123abaf8e1082c29cd5d483c6 Signed-off-by: Colin Cross <ccross@android.com>
Diffstat (limited to 'arch/arm/include/asm/rodata.h')
-rw-r--r--arch/arm/include/asm/rodata.h32
1 files changed, 32 insertions, 0 deletions
diff --git a/arch/arm/include/asm/rodata.h b/arch/arm/include/asm/rodata.h
new file mode 100644
index 00000000000..8c8add87bbc
--- /dev/null
+++ b/arch/arm/include/asm/rodata.h
@@ -0,0 +1,32 @@
+/*
+ * arch/arm/include/asm/rodata.h
+ *
+ * Copyright (C) 2011 Google, Inc.
+ *
+ * Author: Colin Cross <ccross@android.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef _ASMARM_RODATA_H
+#define _ASMARM_RODATA_H
+
+#ifndef __ASSEMBLY__
+
+#ifdef CONFIG_DEBUG_RODATA
+
+int set_memory_rw(unsigned long virt, int numpages);
+int set_memory_ro(unsigned long virt, int numpages);
+
+void mark_rodata_ro(void);
+void set_kernel_text_rw(void);
+void set_kernel_text_ro(void);
+#else
+static inline void set_kernel_text_rw(void) { }
+static inline void set_kernel_text_ro(void) { }
+#endif
+
+#endif
+
+#endif