[patch] x86: test case for the RODATA config option

From: Arjan van de Ven
Date: Tue Jan 22 2008 - 17:44:56 EST



From: Arjan van de Ven <arjan@xxxxxxxxxxxxxxx>
Subject: x86: test case for the RODATA config option

This patch adds a test module for the DEBUG_RODATA config
option to make sure change_page_attr() did indeed make
"const" data read only.

This testcase both tests the DEBUG_RODATA code as well as
the change_page_attr() code for correct operation.

When the tests/ patch gets merged, this module should move
to the tests/ directory.

Signed-off-by: Arjan van de Ven <arjan@xxxxxxxxxxxxxxx>
---
arch/x86/Kconfig.debug | 8 +++++
arch/x86/kernel/Makefile_32 | 1
arch/x86/kernel/Makefile_64 | 2 +
arch/x86/kernel/test_rodata.c | 65 ++++++++++++++++++++++++++++++++++++++++++
arch/x86/mm/init_32.c | 3 +
arch/x86/mm/init_64.c | 3 +
6 files changed, 82 insertions(+)

Index: linux-2.6.24-rc8/arch/x86/Kconfig.debug
===================================================================
--- linux-2.6.24-rc8.orig/arch/x86/Kconfig.debug
+++ linux-2.6.24-rc8/arch/x86/Kconfig.debug
@@ -57,6 +57,14 @@ config DEBUG_RODATA
portion of the kernel code won't be covered by a 2MB TLB anymore.
If in doubt, say "N".

+config DEBUG_RODATA_TEST
+ tristate "Testcase for the DEBUG_RODATA feature"
+ depends on DEBUG_RODATA && m
+ help
+ This option enables a testcase for the DEBUG_RODATA
+ feature as well as for the change_page_attr() infrastructure.
+ If in doubt, say "N"
+
config 4KSTACKS
bool "Use 4Kb for kernel stacks instead of 8Kb"
depends on DEBUG_KERNEL
Index: linux-2.6.24-rc8/arch/x86/mm/init_32.c
===================================================================
--- linux-2.6.24-rc8.orig/arch/x86/mm/init_32.c
+++ linux-2.6.24-rc8/arch/x86/mm/init_32.c
@@ -790,6 +790,9 @@ static int noinline do_test_wp_bit(void)

#ifdef CONFIG_DEBUG_RODATA

+const int rodata_test_data;
+EXPORT_SYMBOL_GPL(rodata_test_data);
+
void mark_rodata_ro(void)
{
unsigned long start = PFN_ALIGN(_text);
Index: linux-2.6.24-rc8/arch/x86/mm/init_64.c
===================================================================
--- linux-2.6.24-rc8.orig/arch/x86/mm/init_64.c
+++ linux-2.6.24-rc8/arch/x86/mm/init_64.c
@@ -590,6 +590,9 @@ void free_initmem(void)

#ifdef CONFIG_DEBUG_RODATA

+const int rodata_test_data = 5;
+EXPORT_SYMBOL_GPL(rodata_test_data);
+
void mark_rodata_ro(void)
{
unsigned long start = (unsigned long)_stext, end;
Index: linux-2.6.24-rc8/arch/x86/kernel/Makefile_64
===================================================================
--- linux-2.6.24-rc8.orig/arch/x86/kernel/Makefile_64
+++ linux-2.6.24-rc8/arch/x86/kernel/Makefile_64
@@ -39,6 +39,8 @@ obj-$(CONFIG_AUDIT) += audit_64.o
obj-$(CONFIG_MODULES) += module_64.o
obj-$(CONFIG_PCI) += early-quirks.o

+obj-$(CONFIG_DEBUG_RODATA_TEST) += test_rodata.o
+
obj-y += topology.o
obj-y += pcspeaker.o

Index: linux-2.6.24-rc8/arch/x86/kernel/test_rodata.c
===================================================================
--- /dev/null
+++ linux-2.6.24-rc8/arch/x86/kernel/test_rodata.c
@@ -0,0 +1,65 @@
+#include <linux/module.h>
+
+
+extern int rodata_test_data;
+
+int rodata_test_init(void)
+{
+ unsigned long result;
+ /* test 1: read the value */
+ /* If this test fails, some previous testrun has clobbered the state */
+ if (!rodata_test_data) {
+ printk(KERN_ERR "rodata_test: test 1 fails (start data)\n");
+ return -ENODEV;
+ }
+
+ /* test 2: write to the variable; this should fault */
+ /*
+ * If this test fails, we managed to overwrite the data
+ *
+ * This is written in assembly to be able to catch the
+ * exception that is supposed to happen in the correct
+ * case
+ */
+
+ result = 1;
+ asm volatile(
+ "0: mov %[zero],(%[rodata_test])\n"
+ " mov %[zero], %[rslt]\n"
+ "1:\n"
+ ".section .fixup,\"ax\"\n"
+ "2: jmp 1b\n"
+ ".previous\n"
+ ".section __ex_table,\"a\"\n"
+ " .align 8\n"
+ " .quad 0b,2b\n"
+ ".previous"
+ : [rslt] "=r" (result)
+ : [rodata_test] "r" (&rodata_test_data), [zero] "r" (0UL)
+ );
+
+
+ if (!result) {
+ printk(KERN_ERR "rodata_test: test data was not read only\n");
+ return -ENODEV;
+ }
+
+ /* test 3: check the value hasn't changed */
+ /* If this test fails, we managed to overwrite the data */
+ if (!rodata_test_data) {
+ printk(KERN_ERR "rodata_test: Test 3 failes (end data)\n");
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+void rodata_test_exit(void)
+{
+}
+
+module_init(rodata_test_init);
+module_exit(rodata_test_exit);
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Testcase for the DEBUG_RODATA infrastructure");
+MODULE_AUTHOR("Arjan van de Ven <arjan@xxxxxxxxxxxxxxx>");
Index: linux-2.6.24-rc8/arch/x86/kernel/Makefile_32
===================================================================
--- linux-2.6.24-rc8.orig/arch/x86/kernel/Makefile_32
+++ linux-2.6.24-rc8/arch/x86/kernel/Makefile_32
@@ -42,6 +42,7 @@ obj-$(CONFIG_EARLY_PRINTK) += early_prin
obj-$(CONFIG_HPET_TIMER) += hpet.o
obj-$(CONFIG_K8_NB) += k8.o
obj-$(CONFIG_MGEODE_LX) += geode_32.o mfgpt_32.o
+obj-$(CONFIG_DEBUG_RODATA_TEST) += test_rodata.o

obj-$(CONFIG_VMI) += vmi_32.o vmiclock_32.o
obj-$(CONFIG_PARAVIRT) += paravirt_32.o

--
If you want to reach me at my work email, use arjan@xxxxxxxxxxxxxxx
For development, discussion and tips for power savings,
visit http://www.lesswatts.org
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/