.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | #include <linux/sched.h> |
---|
2 | 3 | #include <linux/sched/task.h> |
---|
3 | 4 | #include <linux/sched/task_stack.h> |
---|
.. | .. |
---|
69 | 70 | } |
---|
70 | 71 | } |
---|
71 | 72 | |
---|
72 | | -static size_t regs_size(struct pt_regs *regs) |
---|
73 | | -{ |
---|
74 | | - /* x86_32 regs from kernel mode are two words shorter: */ |
---|
75 | | - if (IS_ENABLED(CONFIG_X86_32) && !user_mode(regs)) |
---|
76 | | - return sizeof(*regs) - 2*sizeof(long); |
---|
77 | | - |
---|
78 | | - return sizeof(*regs); |
---|
79 | | -} |
---|
80 | | - |
---|
81 | 73 | static bool in_entry_code(unsigned long ip) |
---|
82 | 74 | { |
---|
83 | 75 | char *addr = (char *)ip; |
---|
84 | 76 | |
---|
85 | | - if (addr >= __entry_text_start && addr < __entry_text_end) |
---|
86 | | - return true; |
---|
87 | | - |
---|
88 | | - if (addr >= __irqentry_text_start && addr < __irqentry_text_end) |
---|
89 | | - return true; |
---|
90 | | - |
---|
91 | | - return false; |
---|
| 77 | + return addr >= __entry_text_start && addr < __entry_text_end; |
---|
92 | 78 | } |
---|
93 | 79 | |
---|
94 | 80 | static inline unsigned long *last_frame(struct unwind_state *state) |
---|
.. | .. |
---|
197 | 183 | } |
---|
198 | 184 | #endif |
---|
199 | 185 | |
---|
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 |
---|
205 | | - |
---|
206 | 186 | static bool update_stack_state(struct unwind_state *state, |
---|
207 | 187 | unsigned long *next_bp) |
---|
208 | 188 | { |
---|
.. | .. |
---|
213 | 193 | size_t len; |
---|
214 | 194 | |
---|
215 | 195 | if (state->regs) |
---|
216 | | - prev_frame_end = (void *)state->regs + regs_size(state->regs); |
---|
| 196 | + prev_frame_end = (void *)state->regs + sizeof(*state->regs); |
---|
217 | 197 | else |
---|
218 | 198 | prev_frame_end = (void *)state->bp + FRAME_HEADER_SIZE; |
---|
219 | 199 | |
---|
.. | .. |
---|
221 | 201 | regs = decode_frame_pointer(next_bp); |
---|
222 | 202 | if (regs) { |
---|
223 | 203 | frame = (unsigned long *)regs; |
---|
224 | | - len = KERNEL_REGS_SIZE; |
---|
| 204 | + len = sizeof(*regs); |
---|
225 | 205 | state->got_irq = true; |
---|
226 | 206 | } else { |
---|
227 | 207 | frame = next_bp; |
---|
.. | .. |
---|
243 | 223 | /* Make sure it only unwinds up and doesn't overlap the prev frame: */ |
---|
244 | 224 | if (state->orig_sp && state->stack_info.type == prev_type && |
---|
245 | 225 | frame < prev_frame_end) |
---|
246 | | - return false; |
---|
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 | 226 | return false; |
---|
255 | 227 | |
---|
256 | 228 | /* Move state to the next frame: */ |
---|
.. | .. |
---|
297 | 269 | /* |
---|
298 | 270 | * kthreads (other than the boot CPU's idle thread) have some |
---|
299 | 271 | * partial regs at the end of their stack which were placed |
---|
300 | | - * there by copy_thread_tls(). But the regs don't have any |
---|
| 272 | + * there by copy_thread(). But the regs don't have any |
---|
301 | 273 | * useful information, so we can skip them. |
---|
302 | 274 | * |
---|
303 | 275 | * This user_mode() check is slightly broader than a PF_KTHREAD |
---|
304 | 276 | * check because it also catches the awkward situation where a |
---|
305 | 277 | * newly forked kthread transitions into a user task by calling |
---|
306 | | - * do_execve(), which eventually clears PF_KTHREAD. |
---|
| 278 | + * kernel_execve(), which eventually clears PF_KTHREAD. |
---|
307 | 279 | */ |
---|
308 | 280 | if (!user_mode(regs)) |
---|
309 | 281 | goto the_end; |
---|
.. | .. |
---|
366 | 338 | if (IS_ENABLED(CONFIG_X86_32)) |
---|
367 | 339 | goto the_end; |
---|
368 | 340 | |
---|
| 341 | + if (state->task != current) |
---|
| 342 | + goto the_end; |
---|
| 343 | + |
---|
369 | 344 | if (state->regs) { |
---|
370 | 345 | printk_deferred_once(KERN_WARNING |
---|
371 | 346 | "WARNING: kernel stack regs at %p in %s:%d has bad 'bp' value %p\n", |
---|
.. | .. |
---|
411 | 386 | * Pretend that the frame is complete and that BP points to it, but save |
---|
412 | 387 | * the real BP so that we can use it when looking for the next frame. |
---|
413 | 388 | */ |
---|
414 | | - if (regs && regs->ip == 0 && |
---|
415 | | - (unsigned long *)kernel_stack_pointer(regs) >= first_frame) { |
---|
| 389 | + if (regs && regs->ip == 0 && (unsigned long *)regs->sp >= first_frame) { |
---|
416 | 390 | state->next_bp = bp; |
---|
417 | | - bp = ((unsigned long *)kernel_stack_pointer(regs)) - 1; |
---|
| 391 | + bp = ((unsigned long *)regs->sp) - 1; |
---|
418 | 392 | } |
---|
419 | 393 | |
---|
420 | 394 | /* Initialize stack info and make sure the frame data is accessible: */ |
---|