]>
Commit | Line | Data |
---|---|---|
59d5af67 | 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |
321d628a FG |
2 | From: Thomas Gleixner <tglx@linutronix.de> |
3 | Date: Mon, 28 Aug 2017 08:47:22 +0200 | |
59d5af67 | 4 | Subject: [PATCH] x86/traps: Simplify pagefault tracing logic |
321d628a FG |
5 | MIME-Version: 1.0 |
6 | Content-Type: text/plain; charset=UTF-8 | |
7 | Content-Transfer-Encoding: 8bit | |
8 | ||
9 | CVE-2017-5754 | |
10 | ||
11 | Make use of the new irqvector tracing static key and remove the duplicated | |
12 | trace_do_pagefault() implementation. | |
13 | ||
14 | If irq vector tracing is disabled, then the overhead of this is a single | |
15 | NOP5, which is a reasonable tradeoff to avoid duplicated code and the | |
16 | unholy macro mess. | |
17 | ||
18 | Signed-off-by: Thomas Gleixner <tglx@linutronix.de> | |
19 | Cc: Andy Lutomirski <luto@kernel.org> | |
20 | Cc: Borislav Petkov <bp@alien8.de> | |
21 | Cc: Linus Torvalds <torvalds@linux-foundation.org> | |
22 | Cc: Peter Zijlstra <peterz@infradead.org> | |
23 | Cc: Steven Rostedt <rostedt@goodmis.org> | |
24 | Link: http://lkml.kernel.org/r/20170828064956.672965407@linutronix.de | |
25 | Signed-off-by: Ingo Molnar <mingo@kernel.org> | |
26 | (cherry picked from commit 11a7ffb01703c3bbb1e9b968893f4487a1b0b5a8) | |
27 | Signed-off-by: Andy Whitcroft <apw@canonical.com> | |
28 | Signed-off-by: Kleber Sacilotto de Souza <kleber.souza@canonical.com> | |
29 | (cherry picked from commit 8478bb5608747fd64c9fd4a2f5422fb4af756a50) | |
30 | Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com> | |
31 | --- | |
32 | arch/x86/include/asm/traps.h | 10 +-------- | |
33 | arch/x86/kernel/kvm.c | 2 +- | |
34 | arch/x86/mm/fault.c | 49 ++++++++++++-------------------------------- | |
35 | arch/x86/entry/entry_32.S | 8 -------- | |
36 | arch/x86/entry/entry_64.S | 13 +----------- | |
37 | 5 files changed, 16 insertions(+), 66 deletions(-) | |
38 | ||
39 | diff --git a/arch/x86/include/asm/traps.h b/arch/x86/include/asm/traps.h | |
40 | index 01fd0a7f48cd..b4f322d6c95f 100644 | |
41 | --- a/arch/x86/include/asm/traps.h | |
42 | +++ b/arch/x86/include/asm/traps.h | |
43 | @@ -39,7 +39,6 @@ asmlinkage void machine_check(void); | |
44 | asmlinkage void simd_coprocessor_error(void); | |
45 | ||
46 | #ifdef CONFIG_TRACING | |
47 | -asmlinkage void trace_page_fault(void); | |
48 | #define trace_stack_segment stack_segment | |
49 | #define trace_divide_error divide_error | |
50 | #define trace_bounds bounds | |
51 | @@ -54,6 +53,7 @@ asmlinkage void trace_page_fault(void); | |
52 | #define trace_alignment_check alignment_check | |
53 | #define trace_simd_coprocessor_error simd_coprocessor_error | |
54 | #define trace_async_page_fault async_page_fault | |
55 | +#define trace_page_fault page_fault | |
56 | #endif | |
57 | ||
58 | dotraplinkage void do_divide_error(struct pt_regs *, long); | |
59 | @@ -74,14 +74,6 @@ asmlinkage struct pt_regs *sync_regs(struct pt_regs *); | |
60 | #endif | |
61 | dotraplinkage void do_general_protection(struct pt_regs *, long); | |
62 | dotraplinkage void do_page_fault(struct pt_regs *, unsigned long); | |
63 | -#ifdef CONFIG_TRACING | |
64 | -dotraplinkage void trace_do_page_fault(struct pt_regs *, unsigned long); | |
65 | -#else | |
66 | -static inline void trace_do_page_fault(struct pt_regs *regs, unsigned long error) | |
67 | -{ | |
68 | - do_page_fault(regs, error); | |
69 | -} | |
70 | -#endif | |
71 | dotraplinkage void do_spurious_interrupt_bug(struct pt_regs *, long); | |
72 | dotraplinkage void do_coprocessor_error(struct pt_regs *, long); | |
73 | dotraplinkage void do_alignment_check(struct pt_regs *, long); | |
74 | diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c | |
75 | index e5e4306e4546..9e3798b00e40 100644 | |
76 | --- a/arch/x86/kernel/kvm.c | |
77 | +++ b/arch/x86/kernel/kvm.c | |
78 | @@ -270,7 +270,7 @@ do_async_page_fault(struct pt_regs *regs, unsigned long error_code) | |
79 | ||
80 | switch (kvm_read_and_reset_pf_reason()) { | |
81 | default: | |
82 | - trace_do_page_fault(regs, error_code); | |
83 | + do_page_fault(regs, error_code); | |
84 | break; | |
85 | case KVM_PV_REASON_PAGE_NOT_PRESENT: | |
86 | /* page is swapped out by the host. */ | |
87 | diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c | |
88 | index 955be01dd9cc..4ee9eb916826 100644 | |
89 | --- a/arch/x86/mm/fault.c | |
90 | +++ b/arch/x86/mm/fault.c | |
91 | @@ -1253,10 +1253,6 @@ static inline bool smap_violation(int error_code, struct pt_regs *regs) | |
92 | * This routine handles page faults. It determines the address, | |
93 | * and the problem, and then passes it off to one of the appropriate | |
94 | * routines. | |
95 | - * | |
96 | - * This function must have noinline because both callers | |
97 | - * {,trace_}do_page_fault() have notrace on. Having this an actual function | |
98 | - * guarantees there's a function trace entry. | |
99 | */ | |
100 | static noinline void | |
101 | __do_page_fault(struct pt_regs *regs, unsigned long error_code, | |
102 | @@ -1491,27 +1487,6 @@ __do_page_fault(struct pt_regs *regs, unsigned long error_code, | |
103 | } | |
104 | NOKPROBE_SYMBOL(__do_page_fault); | |
105 | ||
106 | -dotraplinkage void notrace | |
107 | -do_page_fault(struct pt_regs *regs, unsigned long error_code) | |
108 | -{ | |
109 | - unsigned long address = read_cr2(); /* Get the faulting address */ | |
110 | - enum ctx_state prev_state; | |
111 | - | |
112 | - /* | |
113 | - * We must have this function tagged with __kprobes, notrace and call | |
114 | - * read_cr2() before calling anything else. To avoid calling any kind | |
115 | - * of tracing machinery before we've observed the CR2 value. | |
116 | - * | |
117 | - * exception_{enter,exit}() contain all sorts of tracepoints. | |
118 | - */ | |
119 | - | |
120 | - prev_state = exception_enter(); | |
121 | - __do_page_fault(regs, error_code, address); | |
122 | - exception_exit(prev_state); | |
123 | -} | |
124 | -NOKPROBE_SYMBOL(do_page_fault); | |
125 | - | |
126 | -#ifdef CONFIG_TRACING | |
127 | static nokprobe_inline void | |
128 | trace_page_fault_entries(unsigned long address, struct pt_regs *regs, | |
129 | unsigned long error_code) | |
130 | @@ -1522,22 +1497,24 @@ trace_page_fault_entries(unsigned long address, struct pt_regs *regs, | |
131 | trace_page_fault_kernel(address, regs, error_code); | |
132 | } | |
133 | ||
134 | +/* | |
135 | + * We must have this function blacklisted from kprobes, tagged with notrace | |
136 | + * and call read_cr2() before calling anything else. To avoid calling any | |
137 | + * kind of tracing machinery before we've observed the CR2 value. | |
138 | + * | |
139 | + * exception_{enter,exit}() contains all sorts of tracepoints. | |
140 | + */ | |
141 | dotraplinkage void notrace | |
142 | -trace_do_page_fault(struct pt_regs *regs, unsigned long error_code) | |
143 | +do_page_fault(struct pt_regs *regs, unsigned long error_code) | |
144 | { | |
145 | - /* | |
146 | - * The exception_enter and tracepoint processing could | |
147 | - * trigger another page faults (user space callchain | |
148 | - * reading) and destroy the original cr2 value, so read | |
149 | - * the faulting address now. | |
150 | - */ | |
151 | - unsigned long address = read_cr2(); | |
152 | + unsigned long address = read_cr2(); /* Get the faulting address */ | |
153 | enum ctx_state prev_state; | |
154 | ||
155 | prev_state = exception_enter(); | |
156 | - trace_page_fault_entries(address, regs, error_code); | |
157 | + if (trace_irqvectors_enabled()) | |
158 | + trace_page_fault_entries(address, regs, error_code); | |
159 | + | |
160 | __do_page_fault(regs, error_code, address); | |
161 | exception_exit(prev_state); | |
162 | } | |
163 | -NOKPROBE_SYMBOL(trace_do_page_fault); | |
164 | -#endif /* CONFIG_TRACING */ | |
165 | +NOKPROBE_SYMBOL(do_page_fault); | |
166 | diff --git a/arch/x86/entry/entry_32.S b/arch/x86/entry/entry_32.S | |
167 | index 48ef7bb32c42..0092da1c056f 100644 | |
168 | --- a/arch/x86/entry/entry_32.S | |
169 | +++ b/arch/x86/entry/entry_32.S | |
170 | @@ -891,14 +891,6 @@ BUILD_INTERRUPT3(hyperv_callback_vector, HYPERVISOR_CALLBACK_VECTOR, | |
171 | ||
172 | #endif /* CONFIG_HYPERV */ | |
173 | ||
174 | -#ifdef CONFIG_TRACING | |
175 | -ENTRY(trace_page_fault) | |
176 | - ASM_CLAC | |
177 | - pushl $trace_do_page_fault | |
178 | - jmp common_exception | |
179 | -END(trace_page_fault) | |
180 | -#endif | |
181 | - | |
182 | ENTRY(page_fault) | |
183 | ASM_CLAC | |
184 | pushl $do_page_fault | |
185 | diff --git a/arch/x86/entry/entry_64.S b/arch/x86/entry/entry_64.S | |
186 | index ca0b250eefc4..dfabcbf8e813 100644 | |
187 | --- a/arch/x86/entry/entry_64.S | |
188 | +++ b/arch/x86/entry/entry_64.S | |
189 | @@ -913,17 +913,6 @@ ENTRY(\sym) | |
190 | END(\sym) | |
191 | .endm | |
192 | ||
193 | -#ifdef CONFIG_TRACING | |
194 | -.macro trace_idtentry sym do_sym has_error_code:req | |
195 | -idtentry trace(\sym) trace(\do_sym) has_error_code=\has_error_code | |
196 | -idtentry \sym \do_sym has_error_code=\has_error_code | |
197 | -.endm | |
198 | -#else | |
199 | -.macro trace_idtentry sym do_sym has_error_code:req | |
200 | -idtentry \sym \do_sym has_error_code=\has_error_code | |
201 | -.endm | |
202 | -#endif | |
203 | - | |
204 | idtentry divide_error do_divide_error has_error_code=0 | |
205 | idtentry overflow do_overflow has_error_code=0 | |
206 | idtentry bounds do_bounds has_error_code=0 | |
207 | @@ -1091,7 +1080,7 @@ idtentry xen_stack_segment do_stack_segment has_error_code=1 | |
208 | #endif | |
209 | ||
210 | idtentry general_protection do_general_protection has_error_code=1 | |
211 | -trace_idtentry page_fault do_page_fault has_error_code=1 | |
212 | +idtentry page_fault do_page_fault has_error_code=1 | |
213 | ||
214 | #ifdef CONFIG_KVM_GUEST | |
215 | idtentry async_page_fault do_async_page_fault has_error_code=1 | |
216 | -- | |
217 | 2.14.2 | |
218 |