diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/include/asm/kprobes.h | 2 | ||||
-rw-r--r-- | arch/x86/kernel/kprobes/core.c | 24 | ||||
-rw-r--r-- | arch/x86/kernel/traps.c | 10 |
3 files changed, 15 insertions, 21 deletions
diff --git a/arch/x86/include/asm/kprobes.h b/arch/x86/include/asm/kprobes.h index 9454c167629f..53cdfb2857ab 100644 --- a/arch/x86/include/asm/kprobes.h +++ b/arch/x86/include/asm/kprobes.h | |||
@@ -116,4 +116,6 @@ struct kprobe_ctlblk { | |||
116 | extern int kprobe_fault_handler(struct pt_regs *regs, int trapnr); | 116 | extern int kprobe_fault_handler(struct pt_regs *regs, int trapnr); |
117 | extern int kprobe_exceptions_notify(struct notifier_block *self, | 117 | extern int kprobe_exceptions_notify(struct notifier_block *self, |
118 | unsigned long val, void *data); | 118 | unsigned long val, void *data); |
119 | extern int kprobe_int3_handler(struct pt_regs *regs); | ||
120 | extern int kprobe_debug_handler(struct pt_regs *regs); | ||
119 | #endif /* _ASM_X86_KPROBES_H */ | 121 | #endif /* _ASM_X86_KPROBES_H */ |
diff --git a/arch/x86/kernel/kprobes/core.c b/arch/x86/kernel/kprobes/core.c index 7751b3dee53a..9b80aec1ea1a 100644 --- a/arch/x86/kernel/kprobes/core.c +++ b/arch/x86/kernel/kprobes/core.c | |||
@@ -559,7 +559,7 @@ reenter_kprobe(struct kprobe *p, struct pt_regs *regs, struct kprobe_ctlblk *kcb | |||
559 | * Interrupts are disabled on entry as trap3 is an interrupt gate and they | 559 | * Interrupts are disabled on entry as trap3 is an interrupt gate and they |
560 | * remain disabled throughout this function. | 560 | * remain disabled throughout this function. |
561 | */ | 561 | */ |
562 | static int __kprobes kprobe_handler(struct pt_regs *regs) | 562 | int __kprobes kprobe_int3_handler(struct pt_regs *regs) |
563 | { | 563 | { |
564 | kprobe_opcode_t *addr; | 564 | kprobe_opcode_t *addr; |
565 | struct kprobe *p; | 565 | struct kprobe *p; |
@@ -857,7 +857,7 @@ no_change: | |||
857 | * Interrupts are disabled on entry as trap1 is an interrupt gate and they | 857 | * Interrupts are disabled on entry as trap1 is an interrupt gate and they |
858 | * remain disabled throughout this function. | 858 | * remain disabled throughout this function. |
859 | */ | 859 | */ |
860 | static int __kprobes post_kprobe_handler(struct pt_regs *regs) | 860 | int __kprobes kprobe_debug_handler(struct pt_regs *regs) |
861 | { | 861 | { |
862 | struct kprobe *cur = kprobe_running(); | 862 | struct kprobe *cur = kprobe_running(); |
863 | struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); | 863 | struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); |
@@ -963,22 +963,7 @@ kprobe_exceptions_notify(struct notifier_block *self, unsigned long val, void *d | |||
963 | if (args->regs && user_mode_vm(args->regs)) | 963 | if (args->regs && user_mode_vm(args->regs)) |
964 | return ret; | 964 | return ret; |
965 | 965 | ||
966 | switch (val) { | 966 | if (val == DIE_GPF) { |
967 | case DIE_INT3: | ||
968 | if (kprobe_handler(args->regs)) | ||
969 | ret = NOTIFY_STOP; | ||
970 | break; | ||
971 | case DIE_DEBUG: | ||
972 | if (post_kprobe_handler(args->regs)) { | ||
973 | /* | ||
974 | * Reset the BS bit in dr6 (pointed by args->err) to | ||
975 | * denote completion of processing | ||
976 | */ | ||
977 | (*(unsigned long *)ERR_PTR(args->err)) &= ~DR_STEP; | ||
978 | ret = NOTIFY_STOP; | ||
979 | } | ||
980 | break; | ||
981 | case DIE_GPF: | ||
982 | /* | 967 | /* |
983 | * To be potentially processing a kprobe fault and to | 968 | * To be potentially processing a kprobe fault and to |
984 | * trust the result from kprobe_running(), we have | 969 | * trust the result from kprobe_running(), we have |
@@ -987,9 +972,6 @@ kprobe_exceptions_notify(struct notifier_block *self, unsigned long val, void *d | |||
987 | if (!preemptible() && kprobe_running() && | 972 | if (!preemptible() && kprobe_running() && |
988 | kprobe_fault_handler(args->regs, args->trapnr)) | 973 | kprobe_fault_handler(args->regs, args->trapnr)) |
989 | ret = NOTIFY_STOP; | 974 | ret = NOTIFY_STOP; |
990 | break; | ||
991 | default: | ||
992 | break; | ||
993 | } | 975 | } |
994 | return ret; | 976 | return ret; |
995 | } | 977 | } |
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index 57409f6b8c62..e5d4a70814d7 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c | |||
@@ -334,6 +334,11 @@ dotraplinkage void __kprobes notrace do_int3(struct pt_regs *regs, long error_co | |||
334 | goto exit; | 334 | goto exit; |
335 | #endif /* CONFIG_KGDB_LOW_LEVEL_TRAP */ | 335 | #endif /* CONFIG_KGDB_LOW_LEVEL_TRAP */ |
336 | 336 | ||
337 | #ifdef CONFIG_KPROBES | ||
338 | if (kprobe_int3_handler(regs)) | ||
339 | return; | ||
340 | #endif | ||
341 | |||
337 | if (notify_die(DIE_INT3, "int3", regs, error_code, X86_TRAP_BP, | 342 | if (notify_die(DIE_INT3, "int3", regs, error_code, X86_TRAP_BP, |
338 | SIGTRAP) == NOTIFY_STOP) | 343 | SIGTRAP) == NOTIFY_STOP) |
339 | goto exit; | 344 | goto exit; |
@@ -440,6 +445,11 @@ dotraplinkage void __kprobes do_debug(struct pt_regs *regs, long error_code) | |||
440 | /* Store the virtualized DR6 value */ | 445 | /* Store the virtualized DR6 value */ |
441 | tsk->thread.debugreg6 = dr6; | 446 | tsk->thread.debugreg6 = dr6; |
442 | 447 | ||
448 | #ifdef CONFIG_KPROBES | ||
449 | if (kprobe_debug_handler(regs)) | ||
450 | goto exit; | ||
451 | #endif | ||
452 | |||
443 | if (notify_die(DIE_DEBUG, "debug", regs, (long)&dr6, error_code, | 453 | if (notify_die(DIE_DEBUG, "debug", regs, (long)&dr6, error_code, |
444 | SIGTRAP) == NOTIFY_STOP) | 454 | SIGTRAP) == NOTIFY_STOP) |
445 | goto exit; | 455 | goto exit; |