diff options
-rw-r--r-- | arch/x86/kernel/traps.c | 7 | ||||
-rw-r--r-- | include/linux/uprobes.h | 4 | ||||
-rw-r--r-- | kernel/events/uprobes.c | 10 |
3 files changed, 18 insertions, 3 deletions
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index 73b3ea32245a..3fdb20548c4b 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/kernel.h> | 23 | #include <linux/kernel.h> |
24 | #include <linux/module.h> | 24 | #include <linux/module.h> |
25 | #include <linux/ptrace.h> | 25 | #include <linux/ptrace.h> |
26 | #include <linux/uprobes.h> | ||
26 | #include <linux/string.h> | 27 | #include <linux/string.h> |
27 | #include <linux/delay.h> | 28 | #include <linux/delay.h> |
28 | #include <linux/errno.h> | 29 | #include <linux/errno.h> |
@@ -148,11 +149,11 @@ static siginfo_t *fill_trap_info(struct pt_regs *regs, int signr, int trapnr, | |||
148 | 149 | ||
149 | case X86_TRAP_DE: | 150 | case X86_TRAP_DE: |
150 | sicode = FPE_INTDIV; | 151 | sicode = FPE_INTDIV; |
151 | siaddr = regs->ip; | 152 | siaddr = uprobe_get_trap_addr(regs); |
152 | break; | 153 | break; |
153 | case X86_TRAP_UD: | 154 | case X86_TRAP_UD: |
154 | sicode = ILL_ILLOPN; | 155 | sicode = ILL_ILLOPN; |
155 | siaddr = regs->ip; | 156 | siaddr = uprobe_get_trap_addr(regs); |
156 | break; | 157 | break; |
157 | case X86_TRAP_AC: | 158 | case X86_TRAP_AC: |
158 | sicode = BUS_ADRALN; | 159 | sicode = BUS_ADRALN; |
@@ -531,7 +532,7 @@ static void math_error(struct pt_regs *regs, int error_code, int trapnr) | |||
531 | task->thread.error_code = error_code; | 532 | task->thread.error_code = error_code; |
532 | info.si_signo = SIGFPE; | 533 | info.si_signo = SIGFPE; |
533 | info.si_errno = 0; | 534 | info.si_errno = 0; |
534 | info.si_addr = (void __user *)regs->ip; | 535 | info.si_addr = (void __user *)uprobe_get_trap_addr(regs); |
535 | if (trapnr == X86_TRAP_MF) { | 536 | if (trapnr == X86_TRAP_MF) { |
536 | unsigned short cwd, swd; | 537 | unsigned short cwd, swd; |
537 | /* | 538 | /* |
diff --git a/include/linux/uprobes.h b/include/linux/uprobes.h index edff2b97b864..88c3b7e8b384 100644 --- a/include/linux/uprobes.h +++ b/include/linux/uprobes.h | |||
@@ -102,6 +102,7 @@ extern int __weak set_orig_insn(struct arch_uprobe *aup, struct mm_struct *mm, u | |||
102 | extern bool __weak is_swbp_insn(uprobe_opcode_t *insn); | 102 | extern bool __weak is_swbp_insn(uprobe_opcode_t *insn); |
103 | extern bool __weak is_trap_insn(uprobe_opcode_t *insn); | 103 | extern bool __weak is_trap_insn(uprobe_opcode_t *insn); |
104 | extern unsigned long __weak uprobe_get_swbp_addr(struct pt_regs *regs); | 104 | extern unsigned long __weak uprobe_get_swbp_addr(struct pt_regs *regs); |
105 | extern unsigned long uprobe_get_trap_addr(struct pt_regs *regs); | ||
105 | extern int uprobe_write_opcode(struct mm_struct *mm, unsigned long vaddr, uprobe_opcode_t); | 106 | extern int uprobe_write_opcode(struct mm_struct *mm, unsigned long vaddr, uprobe_opcode_t); |
106 | extern int uprobe_register(struct inode *inode, loff_t offset, struct uprobe_consumer *uc); | 107 | extern int uprobe_register(struct inode *inode, loff_t offset, struct uprobe_consumer *uc); |
107 | extern int uprobe_apply(struct inode *inode, loff_t offset, struct uprobe_consumer *uc, bool); | 108 | extern int uprobe_apply(struct inode *inode, loff_t offset, struct uprobe_consumer *uc, bool); |
@@ -130,6 +131,9 @@ extern bool __weak arch_uprobe_ignore(struct arch_uprobe *aup, struct pt_regs *r | |||
130 | #else /* !CONFIG_UPROBES */ | 131 | #else /* !CONFIG_UPROBES */ |
131 | struct uprobes_state { | 132 | struct uprobes_state { |
132 | }; | 133 | }; |
134 | |||
135 | #define uprobe_get_trap_addr(regs) instruction_pointer(regs) | ||
136 | |||
133 | static inline int | 137 | static inline int |
134 | uprobe_register(struct inode *inode, loff_t offset, struct uprobe_consumer *uc) | 138 | uprobe_register(struct inode *inode, loff_t offset, struct uprobe_consumer *uc) |
135 | { | 139 | { |
diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c index a13251e8bfa4..3b02c72938a8 100644 --- a/kernel/events/uprobes.c +++ b/kernel/events/uprobes.c | |||
@@ -1351,6 +1351,16 @@ unsigned long __weak uprobe_get_swbp_addr(struct pt_regs *regs) | |||
1351 | return instruction_pointer(regs) - UPROBE_SWBP_INSN_SIZE; | 1351 | return instruction_pointer(regs) - UPROBE_SWBP_INSN_SIZE; |
1352 | } | 1352 | } |
1353 | 1353 | ||
1354 | unsigned long uprobe_get_trap_addr(struct pt_regs *regs) | ||
1355 | { | ||
1356 | struct uprobe_task *utask = current->utask; | ||
1357 | |||
1358 | if (unlikely(utask && utask->active_uprobe)) | ||
1359 | return utask->vaddr; | ||
1360 | |||
1361 | return instruction_pointer(regs); | ||
1362 | } | ||
1363 | |||
1354 | /* | 1364 | /* |
1355 | * Called with no locks held. | 1365 | * Called with no locks held. |
1356 | * Called in context of a exiting or a exec-ing thread. | 1366 | * Called in context of a exiting or a exec-ing thread. |