diff options
| -rw-r--r-- | arch/x86/kernel/unwind_frame.c | 16 |
1 files changed, 15 insertions, 1 deletions
diff --git a/arch/x86/kernel/unwind_frame.c b/arch/x86/kernel/unwind_frame.c index d145a0b1f529..d05637726c10 100644 --- a/arch/x86/kernel/unwind_frame.c +++ b/arch/x86/kernel/unwind_frame.c | |||
| @@ -184,6 +184,12 @@ static struct pt_regs *decode_frame_pointer(unsigned long *bp) | |||
| 184 | return (struct pt_regs *)(regs & ~0x1); | 184 | return (struct pt_regs *)(regs & ~0x1); |
| 185 | } | 185 | } |
| 186 | 186 | ||
| 187 | #ifdef CONFIG_X86_32 | ||
| 188 | #define KERNEL_REGS_SIZE (sizeof(struct pt_regs) - 2*sizeof(long)) | ||
| 189 | #else | ||
| 190 | #define KERNEL_REGS_SIZE (sizeof(struct pt_regs)) | ||
| 191 | #endif | ||
| 192 | |||
| 187 | static bool update_stack_state(struct unwind_state *state, | 193 | static bool update_stack_state(struct unwind_state *state, |
| 188 | unsigned long *next_bp) | 194 | unsigned long *next_bp) |
| 189 | { | 195 | { |
| @@ -202,7 +208,7 @@ static bool update_stack_state(struct unwind_state *state, | |||
| 202 | regs = decode_frame_pointer(next_bp); | 208 | regs = decode_frame_pointer(next_bp); |
| 203 | if (regs) { | 209 | if (regs) { |
| 204 | frame = (unsigned long *)regs; | 210 | frame = (unsigned long *)regs; |
| 205 | len = regs_size(regs); | 211 | len = KERNEL_REGS_SIZE; |
| 206 | state->got_irq = true; | 212 | state->got_irq = true; |
| 207 | } else { | 213 | } else { |
| 208 | frame = next_bp; | 214 | frame = next_bp; |
| @@ -226,6 +232,14 @@ static bool update_stack_state(struct unwind_state *state, | |||
| 226 | frame < prev_frame_end) | 232 | frame < prev_frame_end) |
| 227 | return false; | 233 | return false; |
| 228 | 234 | ||
| 235 | /* | ||
| 236 | * On 32-bit with user mode regs, make sure the last two regs are safe | ||
| 237 | * to access: | ||
| 238 | */ | ||
| 239 | if (IS_ENABLED(CONFIG_X86_32) && regs && user_mode(regs) && | ||
| 240 | !on_stack(info, frame, len + 2*sizeof(long))) | ||
| 241 | return false; | ||
| 242 | |||
| 229 | /* Move state to the next frame: */ | 243 | /* Move state to the next frame: */ |
| 230 | if (regs) { | 244 | if (regs) { |
| 231 | state->regs = regs; | 245 | state->regs = regs; |
