diff options
author | Kees Cook <keescook@chromium.org> | 2017-01-30 19:37:11 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2017-01-31 02:31:58 -0500 |
commit | 3ad38ceb2769f08d0abd132331a7a6130536a36c (patch) | |
tree | e7f9e2d8f0fda27f6b1df559f9131a90c4db4b84 | |
parent | 459fbe00693449fade2d1bc802791b081c94edcf (diff) |
x86/mm: Remove CONFIG_DEBUG_NX_TEST
CONFIG_DEBUG_NX_TEST has been broken since CONFIG_DEBUG_SET_MODULE_RONX=y
was added in v2.6.37 via:
84e1c6bb38eb ("x86: Add RO/NX protection for loadable kernel modules")
since the exception table was then made read-only.
Additionally, the manually constructed extables were never fixed when
relative extables were introduced in v3.5 via:
706276543b69 ("x86, extable: Switch to relative exception table entries")
However, relative extables won't work for test_nx.c, since test instruction
memory areas may be more than INT_MAX away from an executable fixup
(e.g. stack and heap too far away from executable memory with the fixup).
Since clearly no one has been using this code for a while now, and similar
tests exist in LKDTM, this should just be removed entirely.
Signed-off-by: Kees Cook <keescook@chromium.org>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Arjan van de Ven <arjan@linux.intel.com>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Jinbum Park <jinb.park7@gmail.com>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/20170131003711.GA74048@beast
Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r-- | arch/x86/Kconfig.debug | 8 | ||||
-rw-r--r-- | arch/x86/kernel/Makefile | 1 | ||||
-rw-r--r-- | arch/x86/kernel/test_nx.c | 173 |
3 files changed, 0 insertions, 182 deletions
diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug index 67eec55093a5..783099f2ac72 100644 --- a/arch/x86/Kconfig.debug +++ b/arch/x86/Kconfig.debug | |||
@@ -120,14 +120,6 @@ config DEBUG_SET_MODULE_RONX | |||
120 | against certain classes of kernel exploits. | 120 | against certain classes of kernel exploits. |
121 | If in doubt, say "N". | 121 | If in doubt, say "N". |
122 | 122 | ||
123 | config DEBUG_NX_TEST | ||
124 | tristate "Testcase for the NX non-executable stack feature" | ||
125 | depends on DEBUG_KERNEL && m | ||
126 | ---help--- | ||
127 | This option enables a testcase for the CPU NX capability | ||
128 | and the software setup of this feature. | ||
129 | If in doubt, say "N" | ||
130 | |||
131 | config DOUBLEFAULT | 123 | config DOUBLEFAULT |
132 | default y | 124 | default y |
133 | bool "Enable doublefault exception handler" if EXPERT | 125 | bool "Enable doublefault exception handler" if EXPERT |
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index 581386c7e429..bdcdb3b3a219 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile | |||
@@ -101,7 +101,6 @@ obj-$(CONFIG_APB_TIMER) += apb_timer.o | |||
101 | 101 | ||
102 | obj-$(CONFIG_AMD_NB) += amd_nb.o | 102 | obj-$(CONFIG_AMD_NB) += amd_nb.o |
103 | obj-$(CONFIG_DEBUG_RODATA_TEST) += test_rodata.o | 103 | obj-$(CONFIG_DEBUG_RODATA_TEST) += test_rodata.o |
104 | obj-$(CONFIG_DEBUG_NX_TEST) += test_nx.o | ||
105 | obj-$(CONFIG_DEBUG_NMI_SELFTEST) += nmi_selftest.o | 104 | obj-$(CONFIG_DEBUG_NMI_SELFTEST) += nmi_selftest.o |
106 | 105 | ||
107 | obj-$(CONFIG_KVM_GUEST) += kvm.o kvmclock.o | 106 | obj-$(CONFIG_KVM_GUEST) += kvm.o kvmclock.o |
diff --git a/arch/x86/kernel/test_nx.c b/arch/x86/kernel/test_nx.c deleted file mode 100644 index a3b875c9e6af..000000000000 --- a/arch/x86/kernel/test_nx.c +++ /dev/null | |||
@@ -1,173 +0,0 @@ | |||
1 | /* | ||
2 | * test_nx.c: functional test for NX functionality | ||
3 | * | ||
4 | * (C) Copyright 2008 Intel Corporation | ||
5 | * Author: Arjan van de Ven <arjan@linux.intel.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License | ||
9 | * as published by the Free Software Foundation; version 2 | ||
10 | * of the License. | ||
11 | */ | ||
12 | #include <linux/module.h> | ||
13 | #include <linux/sort.h> | ||
14 | #include <linux/slab.h> | ||
15 | |||
16 | #include <linux/uaccess.h> | ||
17 | #include <asm/asm.h> | ||
18 | |||
19 | extern int rodata_test_data; | ||
20 | |||
21 | /* | ||
22 | * This file checks 4 things: | ||
23 | * 1) Check if the stack is not executable | ||
24 | * 2) Check if kmalloc memory is not executable | ||
25 | * 3) Check if the .rodata section is not executable | ||
26 | * 4) Check if the .data section of a module is not executable | ||
27 | * | ||
28 | * To do this, the test code tries to execute memory in stack/kmalloc/etc, | ||
29 | * and then checks if the expected trap happens. | ||
30 | * | ||
31 | * Sadly, this implies having a dynamic exception handling table entry. | ||
32 | * ... which can be done (and will make Rusty cry)... but it can only | ||
33 | * be done in a stand-alone module with only 1 entry total. | ||
34 | * (otherwise we'd have to sort and that's just too messy) | ||
35 | */ | ||
36 | |||
37 | |||
38 | |||
39 | /* | ||
40 | * We want to set up an exception handling point on our stack, | ||
41 | * which means a variable value. This function is rather dirty | ||
42 | * and walks the exception table of the module, looking for a magic | ||
43 | * marker and replaces it with a specific function. | ||
44 | */ | ||
45 | static void fudze_exception_table(void *marker, void *new) | ||
46 | { | ||
47 | struct module *mod = THIS_MODULE; | ||
48 | struct exception_table_entry *extable; | ||
49 | |||
50 | /* | ||
51 | * Note: This module has only 1 exception table entry, | ||
52 | * so searching and sorting is not needed. If that changes, | ||
53 | * this would be the place to search and re-sort the exception | ||
54 | * table. | ||
55 | */ | ||
56 | if (mod->num_exentries > 1) { | ||
57 | printk(KERN_ERR "test_nx: too many exception table entries!\n"); | ||
58 | printk(KERN_ERR "test_nx: test results are not reliable.\n"); | ||
59 | return; | ||
60 | } | ||
61 | extable = (struct exception_table_entry *)mod->extable; | ||
62 | extable[0].insn = (unsigned long)new; | ||
63 | } | ||
64 | |||
65 | |||
66 | /* | ||
67 | * exception tables get their symbols translated so we need | ||
68 | * to use a fake function to put in there, which we can then | ||
69 | * replace at runtime. | ||
70 | */ | ||
71 | void foo_label(void); | ||
72 | |||
73 | /* | ||
74 | * returns 0 for not-executable, negative for executable | ||
75 | * | ||
76 | * Note: we cannot allow this function to be inlined, because | ||
77 | * that would give us more than 1 exception table entry. | ||
78 | * This in turn would break the assumptions above. | ||
79 | */ | ||
80 | static noinline int test_address(void *address) | ||
81 | { | ||
82 | unsigned long result; | ||
83 | |||
84 | /* Set up an exception table entry for our address */ | ||
85 | fudze_exception_table(&foo_label, address); | ||
86 | result = 1; | ||
87 | asm volatile( | ||
88 | "foo_label:\n" | ||
89 | "0: call *%[fake_code]\n" | ||
90 | "1:\n" | ||
91 | ".section .fixup,\"ax\"\n" | ||
92 | "2: mov %[zero], %[rslt]\n" | ||
93 | " ret\n" | ||
94 | ".previous\n" | ||
95 | _ASM_EXTABLE(0b,2b) | ||
96 | : [rslt] "=r" (result) | ||
97 | : [fake_code] "r" (address), [zero] "r" (0UL), "0" (result) | ||
98 | ); | ||
99 | /* change the exception table back for the next round */ | ||
100 | fudze_exception_table(address, &foo_label); | ||
101 | |||
102 | if (result) | ||
103 | return -ENODEV; | ||
104 | return 0; | ||
105 | } | ||
106 | |||
107 | static unsigned char test_data = 0xC3; /* 0xC3 is the opcode for "ret" */ | ||
108 | |||
109 | static int test_NX(void) | ||
110 | { | ||
111 | int ret = 0; | ||
112 | /* 0xC3 is the opcode for "ret" */ | ||
113 | char stackcode[] = {0xC3, 0x90, 0 }; | ||
114 | char *heap; | ||
115 | |||
116 | test_data = 0xC3; | ||
117 | |||
118 | printk(KERN_INFO "Testing NX protection\n"); | ||
119 | |||
120 | /* Test 1: check if the stack is not executable */ | ||
121 | if (test_address(&stackcode)) { | ||
122 | printk(KERN_ERR "test_nx: stack was executable\n"); | ||
123 | ret = -ENODEV; | ||
124 | } | ||
125 | |||
126 | |||
127 | /* Test 2: Check if the heap is executable */ | ||
128 | heap = kmalloc(64, GFP_KERNEL); | ||
129 | if (!heap) | ||
130 | return -ENOMEM; | ||
131 | heap[0] = 0xC3; /* opcode for "ret" */ | ||
132 | |||
133 | if (test_address(heap)) { | ||
134 | printk(KERN_ERR "test_nx: heap was executable\n"); | ||
135 | ret = -ENODEV; | ||
136 | } | ||
137 | kfree(heap); | ||
138 | |||
139 | /* | ||
140 | * The following 2 tests currently fail, this needs to get fixed | ||
141 | * Until then, don't run them to avoid too many people getting scared | ||
142 | * by the error message | ||
143 | */ | ||
144 | |||
145 | /* Test 3: Check if the .rodata section is executable */ | ||
146 | if (rodata_test_data != 0xC3) { | ||
147 | printk(KERN_ERR "test_nx: .rodata marker has invalid value\n"); | ||
148 | ret = -ENODEV; | ||
149 | } else if (test_address(&rodata_test_data)) { | ||
150 | printk(KERN_ERR "test_nx: .rodata section is executable\n"); | ||
151 | ret = -ENODEV; | ||
152 | } | ||
153 | |||
154 | #if 0 | ||
155 | /* Test 4: Check if the .data section of a module is executable */ | ||
156 | if (test_address(&test_data)) { | ||
157 | printk(KERN_ERR "test_nx: .data section is executable\n"); | ||
158 | ret = -ENODEV; | ||
159 | } | ||
160 | |||
161 | #endif | ||
162 | return ret; | ||
163 | } | ||
164 | |||
165 | static void test_exit(void) | ||
166 | { | ||
167 | } | ||
168 | |||
169 | module_init(test_NX); | ||
170 | module_exit(test_exit); | ||
171 | MODULE_LICENSE("GPL"); | ||
172 | MODULE_DESCRIPTION("Testcase for the NX infrastructure"); | ||
173 | MODULE_AUTHOR("Arjan van de Ven <arjan@linux.intel.com>"); | ||