]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/4.4.30/0001-Revert-x86-mm-Expand-the-exception-table-logic-to-al.patch
4.14-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 4.4.30 / 0001-Revert-x86-mm-Expand-the-exception-table-logic-to-al.patch
CommitLineData
b10b0803
GKH
1From 38dccaa0fb05bf353c3704763067688e6ec0c3a1 Mon Sep 17 00:00:00 2001
2From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
3Date: Mon, 31 Oct 2016 10:12:45 -0600
4Subject: [PATCH 1/2] Revert "x86/mm: Expand the exception table logic to allow
5 new handling options"
6
7This reverts commit fcf5e5198b447969ed2a56ec335dae3c695a6b46 which is
8548acf19234dbda5a52d5a8e7e205af46e9da840 upstream.
9
10Cc: Tony Luck <tony.luck@intel.com>
11Cc: Borislav Petkov <bp@suse.de>
12Cc: Linus Torvalds <torvalds@linux-foundation.org>
13Cc: Peter Zijlstra <peterz@infradead.org>
14Cc: Thomas Gleixner <tglx@linutronix.de>
15Cc: Ingo Molnar <mingo@kernel.org>
16Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
17---
18 Documentation/x86/exception-tables.txt | 35 -----------
19 arch/x86/include/asm/asm.h | 40 +++++-------
20 arch/x86/include/asm/uaccess.h | 16 ++---
21 arch/x86/kernel/kprobes/core.c | 2
22 arch/x86/kernel/traps.c | 6 -
23 arch/x86/mm/extable.c | 102 +++++++++------------------------
24 arch/x86/mm/fault.c | 2
25 scripts/sortextable.c | 32 ----------
26 8 files changed, 58 insertions(+), 177 deletions(-)
27
28--- a/Documentation/x86/exception-tables.txt
29+++ b/Documentation/x86/exception-tables.txt
30@@ -290,38 +290,3 @@ Due to the way that the exception table
31 only use exceptions for code in the .text section. Any other section
32 will cause the exception table to not be sorted correctly, and the
33 exceptions will fail.
34-
35-Things changed when 64-bit support was added to x86 Linux. Rather than
36-double the size of the exception table by expanding the two entries
37-from 32-bits to 64 bits, a clever trick was used to store addresses
38-as relative offsets from the table itself. The assembly code changed
39-from:
40- .long 1b,3b
41-to:
42- .long (from) - .
43- .long (to) - .
44-
45-and the C-code that uses these values converts back to absolute addresses
46-like this:
47-
48- ex_insn_addr(const struct exception_table_entry *x)
49- {
50- return (unsigned long)&x->insn + x->insn;
51- }
52-
53-In v4.6 the exception table entry was expanded with a new field "handler".
54-This is also 32-bits wide and contains a third relative function
55-pointer which points to one of:
56-
57-1) int ex_handler_default(const struct exception_table_entry *fixup)
58- This is legacy case that just jumps to the fixup code
59-2) int ex_handler_fault(const struct exception_table_entry *fixup)
60- This case provides the fault number of the trap that occurred at
61- entry->insn. It is used to distinguish page faults from machine
62- check.
63-3) int ex_handler_ext(const struct exception_table_entry *fixup)
64- This case is used for uaccess_err ... we need to set a flag
65- in the task structure. Before the handler functions existed this
66- case was handled by adding a large offset to the fixup to tag
67- it as special.
68-More functions can easily be added.
69--- a/arch/x86/include/asm/asm.h
70+++ b/arch/x86/include/asm/asm.h
71@@ -44,22 +44,19 @@
72
73 /* Exception table entry */
74 #ifdef __ASSEMBLY__
75-# define _ASM_EXTABLE_HANDLE(from, to, handler) \
76+# define _ASM_EXTABLE(from,to) \
77 .pushsection "__ex_table","a" ; \
78- .balign 4 ; \
79+ .balign 8 ; \
80 .long (from) - . ; \
81 .long (to) - . ; \
82- .long (handler) - . ; \
83 .popsection
84
85-# define _ASM_EXTABLE(from, to) \
86- _ASM_EXTABLE_HANDLE(from, to, ex_handler_default)
87-
88-# define _ASM_EXTABLE_FAULT(from, to) \
89- _ASM_EXTABLE_HANDLE(from, to, ex_handler_fault)
90-
91-# define _ASM_EXTABLE_EX(from, to) \
92- _ASM_EXTABLE_HANDLE(from, to, ex_handler_ext)
93+# define _ASM_EXTABLE_EX(from,to) \
94+ .pushsection "__ex_table","a" ; \
95+ .balign 8 ; \
96+ .long (from) - . ; \
97+ .long (to) - . + 0x7ffffff0 ; \
98+ .popsection
99
100 # define _ASM_NOKPROBE(entry) \
101 .pushsection "_kprobe_blacklist","aw" ; \
102@@ -92,24 +89,19 @@
103 .endm
104
105 #else
106-# define _EXPAND_EXTABLE_HANDLE(x) #x
107-# define _ASM_EXTABLE_HANDLE(from, to, handler) \
108+# define _ASM_EXTABLE(from,to) \
109 " .pushsection \"__ex_table\",\"a\"\n" \
110- " .balign 4\n" \
111+ " .balign 8\n" \
112 " .long (" #from ") - .\n" \
113 " .long (" #to ") - .\n" \
114- " .long (" _EXPAND_EXTABLE_HANDLE(handler) ") - .\n" \
115 " .popsection\n"
116
117-# define _ASM_EXTABLE(from, to) \
118- _ASM_EXTABLE_HANDLE(from, to, ex_handler_default)
119-
120-# define _ASM_EXTABLE_FAULT(from, to) \
121- _ASM_EXTABLE_HANDLE(from, to, ex_handler_fault)
122-
123-# define _ASM_EXTABLE_EX(from, to) \
124- _ASM_EXTABLE_HANDLE(from, to, ex_handler_ext)
125-
126+# define _ASM_EXTABLE_EX(from,to) \
127+ " .pushsection \"__ex_table\",\"a\"\n" \
128+ " .balign 8\n" \
129+ " .long (" #from ") - .\n" \
130+ " .long (" #to ") - . + 0x7ffffff0\n" \
131+ " .popsection\n"
132 /* For C file, we already have NOKPROBE_SYMBOL macro */
133 #endif
134
135--- a/arch/x86/include/asm/uaccess.h
136+++ b/arch/x86/include/asm/uaccess.h
137@@ -90,11 +90,12 @@ static inline bool __chk_range_not_ok(un
138 likely(!__range_not_ok(addr, size, user_addr_max()))
139
140 /*
141- * The exception table consists of triples of addresses relative to the
142- * exception table entry itself. The first address is of an instruction
143- * that is allowed to fault, the second is the target at which the program
144- * should continue. The third is a handler function to deal with the fault
145- * caused by the instruction in the first field.
146+ * The exception table consists of pairs of addresses relative to the
147+ * exception table enty itself: the first is the address of an
148+ * instruction that is allowed to fault, and the second is the address
149+ * at which the program should continue. No registers are modified,
150+ * so it is entirely up to the continuation code to figure out what to
151+ * do.
152 *
153 * All the routines below use bits of fixup code that are out of line
154 * with the main instruction path. This means when everything is well,
155@@ -103,14 +104,13 @@ static inline bool __chk_range_not_ok(un
156 */
157
158 struct exception_table_entry {
159- int insn, fixup, handler;
160+ int insn, fixup;
161 };
162 /* This is not the generic standard exception_table_entry format */
163 #define ARCH_HAS_SORT_EXTABLE
164 #define ARCH_HAS_SEARCH_EXTABLE
165
166-extern int fixup_exception(struct pt_regs *regs, int trapnr);
167-extern bool ex_has_fault_handler(unsigned long ip);
168+extern int fixup_exception(struct pt_regs *regs);
169 extern int early_fixup_exception(unsigned long *ip);
170
171 /*
172--- a/arch/x86/kernel/kprobes/core.c
173+++ b/arch/x86/kernel/kprobes/core.c
174@@ -1000,7 +1000,7 @@ int kprobe_fault_handler(struct pt_regs
175 * In case the user-specified fault handler returned
176 * zero, try to fix up.
177 */
178- if (fixup_exception(regs, trapnr))
179+ if (fixup_exception(regs))
180 return 1;
181
182 /*
183--- a/arch/x86/kernel/traps.c
184+++ b/arch/x86/kernel/traps.c
185@@ -199,7 +199,7 @@ do_trap_no_signal(struct task_struct *ts
186 }
187
188 if (!user_mode(regs)) {
189- if (!fixup_exception(regs, trapnr)) {
190+ if (!fixup_exception(regs)) {
191 tsk->thread.error_code = error_code;
192 tsk->thread.trap_nr = trapnr;
193 die(str, regs, error_code);
194@@ -453,7 +453,7 @@ do_general_protection(struct pt_regs *re
195
196 tsk = current;
197 if (!user_mode(regs)) {
198- if (fixup_exception(regs, X86_TRAP_GP))
199+ if (fixup_exception(regs))
200 return;
201
202 tsk->thread.error_code = error_code;
203@@ -699,7 +699,7 @@ static void math_error(struct pt_regs *r
204 conditional_sti(regs);
205
206 if (!user_mode(regs)) {
207- if (!fixup_exception(regs, trapnr)) {
208+ if (!fixup_exception(regs)) {
209 task->thread.error_code = error_code;
210 task->thread.trap_nr = trapnr;
211 die(str, regs, error_code);
212--- a/arch/x86/mm/extable.c
213+++ b/arch/x86/mm/extable.c
214@@ -3,9 +3,6 @@
215 #include <linux/sort.h>
216 #include <asm/uaccess.h>
217
218-typedef bool (*ex_handler_t)(const struct exception_table_entry *,
219- struct pt_regs *, int);
220-
221 static inline unsigned long
222 ex_insn_addr(const struct exception_table_entry *x)
223 {
224@@ -16,56 +13,11 @@ ex_fixup_addr(const struct exception_tab
225 {
226 return (unsigned long)&x->fixup + x->fixup;
227 }
228-static inline ex_handler_t
229-ex_fixup_handler(const struct exception_table_entry *x)
230-{
231- return (ex_handler_t)((unsigned long)&x->handler + x->handler);
232-}
233-
234-bool ex_handler_default(const struct exception_table_entry *fixup,
235- struct pt_regs *regs, int trapnr)
236-{
237- regs->ip = ex_fixup_addr(fixup);
238- return true;
239-}
240-EXPORT_SYMBOL(ex_handler_default);
241-
242-bool ex_handler_fault(const struct exception_table_entry *fixup,
243- struct pt_regs *regs, int trapnr)
244-{
245- regs->ip = ex_fixup_addr(fixup);
246- regs->ax = trapnr;
247- return true;
248-}
249-EXPORT_SYMBOL_GPL(ex_handler_fault);
250-
251-bool ex_handler_ext(const struct exception_table_entry *fixup,
252- struct pt_regs *regs, int trapnr)
253-{
254- /* Special hack for uaccess_err */
255- current_thread_info()->uaccess_err = 1;
256- regs->ip = ex_fixup_addr(fixup);
257- return true;
258-}
259-EXPORT_SYMBOL(ex_handler_ext);
260
261-bool ex_has_fault_handler(unsigned long ip)
262+int fixup_exception(struct pt_regs *regs)
263 {
264- const struct exception_table_entry *e;
265- ex_handler_t handler;
266-
267- e = search_exception_tables(ip);
268- if (!e)
269- return false;
270- handler = ex_fixup_handler(e);
271-
272- return handler == ex_handler_fault;
273-}
274-
275-int fixup_exception(struct pt_regs *regs, int trapnr)
276-{
277- const struct exception_table_entry *e;
278- ex_handler_t handler;
279+ const struct exception_table_entry *fixup;
280+ unsigned long new_ip;
281
282 #ifdef CONFIG_PNPBIOS
283 if (unlikely(SEGMENT_IS_PNP_CODE(regs->cs))) {
284@@ -81,34 +33,42 @@ int fixup_exception(struct pt_regs *regs
285 }
286 #endif
287
288- e = search_exception_tables(regs->ip);
289- if (!e)
290- return 0;
291+ fixup = search_exception_tables(regs->ip);
292+ if (fixup) {
293+ new_ip = ex_fixup_addr(fixup);
294+
295+ if (fixup->fixup - fixup->insn >= 0x7ffffff0 - 4) {
296+ /* Special hack for uaccess_err */
297+ current_thread_info()->uaccess_err = 1;
298+ new_ip -= 0x7ffffff0;
299+ }
300+ regs->ip = new_ip;
301+ return 1;
302+ }
303
304- handler = ex_fixup_handler(e);
305- return handler(e, regs, trapnr);
306+ return 0;
307 }
308
309 /* Restricted version used during very early boot */
310 int __init early_fixup_exception(unsigned long *ip)
311 {
312- const struct exception_table_entry *e;
313+ const struct exception_table_entry *fixup;
314 unsigned long new_ip;
315- ex_handler_t handler;
316-
317- e = search_exception_tables(*ip);
318- if (!e)
319- return 0;
320
321- new_ip = ex_fixup_addr(e);
322- handler = ex_fixup_handler(e);
323+ fixup = search_exception_tables(*ip);
324+ if (fixup) {
325+ new_ip = ex_fixup_addr(fixup);
326+
327+ if (fixup->fixup - fixup->insn >= 0x7ffffff0 - 4) {
328+ /* uaccess handling not supported during early boot */
329+ return 0;
330+ }
331
332- /* special handling not supported during early boot */
333- if (handler != ex_handler_default)
334- return 0;
335+ *ip = new_ip;
336+ return 1;
337+ }
338
339- *ip = new_ip;
340- return 1;
341+ return 0;
342 }
343
344 /*
345@@ -173,8 +133,6 @@ void sort_extable(struct exception_table
346 i += 4;
347 p->fixup += i;
348 i += 4;
349- p->handler += i;
350- i += 4;
351 }
352
353 sort(start, finish - start, sizeof(struct exception_table_entry),
354@@ -187,8 +145,6 @@ void sort_extable(struct exception_table
355 i += 4;
356 p->fixup -= i;
357 i += 4;
358- p->handler -= i;
359- i += 4;
360 }
361 }
362
363--- a/arch/x86/mm/fault.c
364+++ b/arch/x86/mm/fault.c
365@@ -663,7 +663,7 @@ no_context(struct pt_regs *regs, unsigne
366 int sig;
367
368 /* Are we prepared to handle this kernel fault? */
369- if (fixup_exception(regs, X86_TRAP_PF)) {
370+ if (fixup_exception(regs)) {
371 /*
372 * Any interrupt that takes a fault gets the fixup. This makes
373 * the below recursive fault logic only apply to a faults from
374--- a/scripts/sortextable.c
375+++ b/scripts/sortextable.c
376@@ -209,35 +209,6 @@ static int compare_relative_table(const
377 return 0;
378 }
379
380-static void x86_sort_relative_table(char *extab_image, int image_size)
381-{
382- int i;
383-
384- i = 0;
385- while (i < image_size) {
386- uint32_t *loc = (uint32_t *)(extab_image + i);
387-
388- w(r(loc) + i, loc);
389- w(r(loc + 1) + i + 4, loc + 1);
390- w(r(loc + 2) + i + 8, loc + 2);
391-
392- i += sizeof(uint32_t) * 3;
393- }
394-
395- qsort(extab_image, image_size / 12, 12, compare_relative_table);
396-
397- i = 0;
398- while (i < image_size) {
399- uint32_t *loc = (uint32_t *)(extab_image + i);
400-
401- w(r(loc) - i, loc);
402- w(r(loc + 1) - (i + 4), loc + 1);
403- w(r(loc + 2) - (i + 8), loc + 2);
404-
405- i += sizeof(uint32_t) * 3;
406- }
407-}
408-
409 static void sort_relative_table(char *extab_image, int image_size)
410 {
411 int i;
412@@ -310,9 +281,6 @@ do_file(char const *const fname)
413 break;
414 case EM_386:
415 case EM_X86_64:
416- custom_sort = x86_sort_relative_table;
417- break;
418-
419 case EM_S390:
420 custom_sort = sort_relative_table;
421 break;