diff options
-rw-r--r-- | arch/x86/include/asm/debugreg.h | 22 | ||||
-rw-r--r-- | arch/x86/include/asm/processor.h | 6 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/common.c | 6 | ||||
-rw-r--r-- | arch/x86/kernel/traps.c | 14 |
4 files changed, 40 insertions, 8 deletions
diff --git a/arch/x86/include/asm/debugreg.h b/arch/x86/include/asm/debugreg.h index 078ad0caefc..b903d5ea394 100644 --- a/arch/x86/include/asm/debugreg.h +++ b/arch/x86/include/asm/debugreg.h | |||
@@ -101,6 +101,28 @@ extern void aout_dump_debugregs(struct user *dump); | |||
101 | 101 | ||
102 | extern void hw_breakpoint_restore(void); | 102 | extern void hw_breakpoint_restore(void); |
103 | 103 | ||
104 | #ifdef CONFIG_X86_64 | ||
105 | DECLARE_PER_CPU(int, debug_stack_usage); | ||
106 | static inline void debug_stack_usage_inc(void) | ||
107 | { | ||
108 | __get_cpu_var(debug_stack_usage)++; | ||
109 | } | ||
110 | static inline void debug_stack_usage_dec(void) | ||
111 | { | ||
112 | __get_cpu_var(debug_stack_usage)--; | ||
113 | } | ||
114 | int is_debug_stack(unsigned long addr); | ||
115 | void debug_stack_set_zero(void); | ||
116 | void debug_stack_reset(void); | ||
117 | #else /* !X86_64 */ | ||
118 | static inline int is_debug_stack(unsigned long addr) { return 0; } | ||
119 | static inline void debug_stack_set_zero(void) { } | ||
120 | static inline void debug_stack_reset(void) { } | ||
121 | static inline void debug_stack_usage_inc(void) { } | ||
122 | static inline void debug_stack_usage_dec(void) { } | ||
123 | #endif /* X86_64 */ | ||
124 | |||
125 | |||
104 | #endif /* __KERNEL__ */ | 126 | #endif /* __KERNEL__ */ |
105 | 127 | ||
106 | #endif /* _ASM_X86_DEBUGREG_H */ | 128 | #endif /* _ASM_X86_DEBUGREG_H */ |
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index 4b39d6d7e3a..b650435ffb5 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h | |||
@@ -402,9 +402,6 @@ DECLARE_PER_CPU(char *, irq_stack_ptr); | |||
402 | DECLARE_PER_CPU(unsigned int, irq_count); | 402 | DECLARE_PER_CPU(unsigned int, irq_count); |
403 | extern unsigned long kernel_eflags; | 403 | extern unsigned long kernel_eflags; |
404 | extern asmlinkage void ignore_sysret(void); | 404 | extern asmlinkage void ignore_sysret(void); |
405 | int is_debug_stack(unsigned long addr); | ||
406 | void debug_stack_set_zero(void); | ||
407 | void debug_stack_reset(void); | ||
408 | #else /* X86_64 */ | 405 | #else /* X86_64 */ |
409 | #ifdef CONFIG_CC_STACKPROTECTOR | 406 | #ifdef CONFIG_CC_STACKPROTECTOR |
410 | /* | 407 | /* |
@@ -419,9 +416,6 @@ struct stack_canary { | |||
419 | }; | 416 | }; |
420 | DECLARE_PER_CPU_ALIGNED(struct stack_canary, stack_canary); | 417 | DECLARE_PER_CPU_ALIGNED(struct stack_canary, stack_canary); |
421 | #endif | 418 | #endif |
422 | static inline int is_debug_stack(unsigned long addr) { return 0; } | ||
423 | static inline void debug_stack_set_zero(void) { } | ||
424 | static inline void debug_stack_reset(void) { } | ||
425 | #endif /* X86_64 */ | 419 | #endif /* X86_64 */ |
426 | 420 | ||
427 | extern unsigned int xstate_size; | 421 | extern unsigned int xstate_size; |
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index caa404556b9..266e4649b1d 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c | |||
@@ -1093,11 +1093,13 @@ unsigned long kernel_eflags; | |||
1093 | DEFINE_PER_CPU(struct orig_ist, orig_ist); | 1093 | DEFINE_PER_CPU(struct orig_ist, orig_ist); |
1094 | 1094 | ||
1095 | static DEFINE_PER_CPU(unsigned long, debug_stack_addr); | 1095 | static DEFINE_PER_CPU(unsigned long, debug_stack_addr); |
1096 | DEFINE_PER_CPU(int, debug_stack_usage); | ||
1096 | 1097 | ||
1097 | int is_debug_stack(unsigned long addr) | 1098 | int is_debug_stack(unsigned long addr) |
1098 | { | 1099 | { |
1099 | return addr <= __get_cpu_var(debug_stack_addr) && | 1100 | return __get_cpu_var(debug_stack_usage) || |
1100 | addr > (__get_cpu_var(debug_stack_addr) - DEBUG_STKSZ); | 1101 | (addr <= __get_cpu_var(debug_stack_addr) && |
1102 | addr > (__get_cpu_var(debug_stack_addr) - DEBUG_STKSZ)); | ||
1101 | } | 1103 | } |
1102 | 1104 | ||
1103 | void debug_stack_set_zero(void) | 1105 | void debug_stack_set_zero(void) |
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index a93c5cabc36..0072b38e3ea 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c | |||
@@ -316,9 +316,15 @@ dotraplinkage void __kprobes do_int3(struct pt_regs *regs, long error_code) | |||
316 | return; | 316 | return; |
317 | #endif | 317 | #endif |
318 | 318 | ||
319 | /* | ||
320 | * Let others (NMI) know that the debug stack is in use | ||
321 | * as we may switch to the interrupt stack. | ||
322 | */ | ||
323 | debug_stack_usage_inc(); | ||
319 | preempt_conditional_sti(regs); | 324 | preempt_conditional_sti(regs); |
320 | do_trap(3, SIGTRAP, "int3", regs, error_code, NULL); | 325 | do_trap(3, SIGTRAP, "int3", regs, error_code, NULL); |
321 | preempt_conditional_cli(regs); | 326 | preempt_conditional_cli(regs); |
327 | debug_stack_usage_dec(); | ||
322 | } | 328 | } |
323 | 329 | ||
324 | #ifdef CONFIG_X86_64 | 330 | #ifdef CONFIG_X86_64 |
@@ -411,6 +417,12 @@ dotraplinkage void __kprobes do_debug(struct pt_regs *regs, long error_code) | |||
411 | SIGTRAP) == NOTIFY_STOP) | 417 | SIGTRAP) == NOTIFY_STOP) |
412 | return; | 418 | return; |
413 | 419 | ||
420 | /* | ||
421 | * Let others (NMI) know that the debug stack is in use | ||
422 | * as we may switch to the interrupt stack. | ||
423 | */ | ||
424 | debug_stack_usage_inc(); | ||
425 | |||
414 | /* It's safe to allow irq's after DR6 has been saved */ | 426 | /* It's safe to allow irq's after DR6 has been saved */ |
415 | preempt_conditional_sti(regs); | 427 | preempt_conditional_sti(regs); |
416 | 428 | ||
@@ -418,6 +430,7 @@ dotraplinkage void __kprobes do_debug(struct pt_regs *regs, long error_code) | |||
418 | handle_vm86_trap((struct kernel_vm86_regs *) regs, | 430 | handle_vm86_trap((struct kernel_vm86_regs *) regs, |
419 | error_code, 1); | 431 | error_code, 1); |
420 | preempt_conditional_cli(regs); | 432 | preempt_conditional_cli(regs); |
433 | debug_stack_usage_dec(); | ||
421 | return; | 434 | return; |
422 | } | 435 | } |
423 | 436 | ||
@@ -437,6 +450,7 @@ dotraplinkage void __kprobes do_debug(struct pt_regs *regs, long error_code) | |||
437 | if (tsk->thread.debugreg6 & (DR_STEP | DR_TRAP_BITS) || user_icebp) | 450 | if (tsk->thread.debugreg6 & (DR_STEP | DR_TRAP_BITS) || user_icebp) |
438 | send_sigtrap(tsk, regs, error_code, si_code); | 451 | send_sigtrap(tsk, regs, error_code, si_code); |
439 | preempt_conditional_cli(regs); | 452 | preempt_conditional_cli(regs); |
453 | debug_stack_usage_dec(); | ||
440 | 454 | ||
441 | return; | 455 | return; |
442 | } | 456 | } |