aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/unwind_frame.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/kernel/unwind_frame.c')
-rw-r--r--arch/x86/kernel/unwind_frame.c38
1 files changed, 36 insertions, 2 deletions
diff --git a/arch/x86/kernel/unwind_frame.c b/arch/x86/kernel/unwind_frame.c
index d145a0b1f529..3dc26f95d46e 100644
--- a/arch/x86/kernel/unwind_frame.c
+++ b/arch/x86/kernel/unwind_frame.c
@@ -44,7 +44,8 @@ static void unwind_dump(struct unwind_state *state)
44 state->stack_info.type, state->stack_info.next_sp, 44 state->stack_info.type, state->stack_info.next_sp,
45 state->stack_mask, state->graph_idx); 45 state->stack_mask, state->graph_idx);
46 46
47 for (sp = state->orig_sp; sp; sp = PTR_ALIGN(stack_info.next_sp, sizeof(long))) { 47 for (sp = PTR_ALIGN(state->orig_sp, sizeof(long)); sp;
48 sp = PTR_ALIGN(stack_info.next_sp, sizeof(long))) {
48 if (get_stack_info(sp, state->task, &stack_info, &visit_mask)) 49 if (get_stack_info(sp, state->task, &stack_info, &visit_mask))
49 break; 50 break;
50 51
@@ -174,6 +175,7 @@ static bool is_last_task_frame(struct unwind_state *state)
174 * This determines if the frame pointer actually contains an encoded pointer to 175 * This determines if the frame pointer actually contains an encoded pointer to
175 * pt_regs on the stack. See ENCODE_FRAME_POINTER. 176 * pt_regs on the stack. See ENCODE_FRAME_POINTER.
176 */ 177 */
178#ifdef CONFIG_X86_64
177static struct pt_regs *decode_frame_pointer(unsigned long *bp) 179static struct pt_regs *decode_frame_pointer(unsigned long *bp)
178{ 180{
179 unsigned long regs = (unsigned long)bp; 181 unsigned long regs = (unsigned long)bp;
@@ -183,6 +185,23 @@ static struct pt_regs *decode_frame_pointer(unsigned long *bp)
183 185
184 return (struct pt_regs *)(regs & ~0x1); 186 return (struct pt_regs *)(regs & ~0x1);
185} 187}
188#else
189static struct pt_regs *decode_frame_pointer(unsigned long *bp)
190{
191 unsigned long regs = (unsigned long)bp;
192
193 if (regs & 0x80000000)
194 return NULL;
195
196 return (struct pt_regs *)(regs | 0x80000000);
197}
198#endif
199
200#ifdef CONFIG_X86_32
201#define KERNEL_REGS_SIZE (sizeof(struct pt_regs) - 2*sizeof(long))
202#else
203#define KERNEL_REGS_SIZE (sizeof(struct pt_regs))
204#endif
186 205
187static bool update_stack_state(struct unwind_state *state, 206static bool update_stack_state(struct unwind_state *state,
188 unsigned long *next_bp) 207 unsigned long *next_bp)
@@ -202,7 +221,7 @@ static bool update_stack_state(struct unwind_state *state,
202 regs = decode_frame_pointer(next_bp); 221 regs = decode_frame_pointer(next_bp);
203 if (regs) { 222 if (regs) {
204 frame = (unsigned long *)regs; 223 frame = (unsigned long *)regs;
205 len = regs_size(regs); 224 len = KERNEL_REGS_SIZE;
206 state->got_irq = true; 225 state->got_irq = true;
207 } else { 226 } else {
208 frame = next_bp; 227 frame = next_bp;
@@ -226,6 +245,14 @@ static bool update_stack_state(struct unwind_state *state,
226 frame < prev_frame_end) 245 frame < prev_frame_end)
227 return false; 246 return false;
228 247
248 /*
249 * On 32-bit with user mode regs, make sure the last two regs are safe
250 * to access:
251 */
252 if (IS_ENABLED(CONFIG_X86_32) && regs && user_mode(regs) &&
253 !on_stack(info, frame, len + 2*sizeof(long)))
254 return false;
255
229 /* Move state to the next frame: */ 256 /* Move state to the next frame: */
230 if (regs) { 257 if (regs) {
231 state->regs = regs; 258 state->regs = regs;
@@ -328,6 +355,13 @@ bad_address:
328 state->regs->sp < (unsigned long)task_pt_regs(state->task)) 355 state->regs->sp < (unsigned long)task_pt_regs(state->task))
329 goto the_end; 356 goto the_end;
330 357
358 /*
359 * There are some known frame pointer issues on 32-bit. Disable
360 * unwinder warnings on 32-bit until it gets objtool support.
361 */
362 if (IS_ENABLED(CONFIG_X86_32))
363 goto the_end;
364
331 if (state->regs) { 365 if (state->regs) {
332 printk_deferred_once(KERN_WARNING 366 printk_deferred_once(KERN_WARNING
333 "WARNING: kernel stack regs at %p in %s:%d has bad 'bp' value %p\n", 367 "WARNING: kernel stack regs at %p in %s:%d has bad 'bp' value %p\n",