diff options
Diffstat (limited to 'arch/i386/kernel/kprobes.c')
-rw-r--r-- | arch/i386/kernel/kprobes.c | 35 |
1 files changed, 20 insertions, 15 deletions
diff --git a/arch/i386/kernel/kprobes.c b/arch/i386/kernel/kprobes.c index a6d8c45961d3..6345b430b105 100644 --- a/arch/i386/kernel/kprobes.c +++ b/arch/i386/kernel/kprobes.c | |||
@@ -62,32 +62,32 @@ static inline int is_IF_modifier(kprobe_opcode_t opcode) | |||
62 | return 0; | 62 | return 0; |
63 | } | 63 | } |
64 | 64 | ||
65 | int arch_prepare_kprobe(struct kprobe *p) | 65 | int __kprobes arch_prepare_kprobe(struct kprobe *p) |
66 | { | 66 | { |
67 | return 0; | 67 | return 0; |
68 | } | 68 | } |
69 | 69 | ||
70 | void arch_copy_kprobe(struct kprobe *p) | 70 | void __kprobes arch_copy_kprobe(struct kprobe *p) |
71 | { | 71 | { |
72 | memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t)); | 72 | memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t)); |
73 | p->opcode = *p->addr; | 73 | p->opcode = *p->addr; |
74 | } | 74 | } |
75 | 75 | ||
76 | void arch_arm_kprobe(struct kprobe *p) | 76 | void __kprobes arch_arm_kprobe(struct kprobe *p) |
77 | { | 77 | { |
78 | *p->addr = BREAKPOINT_INSTRUCTION; | 78 | *p->addr = BREAKPOINT_INSTRUCTION; |
79 | flush_icache_range((unsigned long) p->addr, | 79 | flush_icache_range((unsigned long) p->addr, |
80 | (unsigned long) p->addr + sizeof(kprobe_opcode_t)); | 80 | (unsigned long) p->addr + sizeof(kprobe_opcode_t)); |
81 | } | 81 | } |
82 | 82 | ||
83 | void arch_disarm_kprobe(struct kprobe *p) | 83 | void __kprobes arch_disarm_kprobe(struct kprobe *p) |
84 | { | 84 | { |
85 | *p->addr = p->opcode; | 85 | *p->addr = p->opcode; |
86 | flush_icache_range((unsigned long) p->addr, | 86 | flush_icache_range((unsigned long) p->addr, |
87 | (unsigned long) p->addr + sizeof(kprobe_opcode_t)); | 87 | (unsigned long) p->addr + sizeof(kprobe_opcode_t)); |
88 | } | 88 | } |
89 | 89 | ||
90 | void arch_remove_kprobe(struct kprobe *p) | 90 | void __kprobes arch_remove_kprobe(struct kprobe *p) |
91 | { | 91 | { |
92 | } | 92 | } |
93 | 93 | ||
@@ -127,7 +127,8 @@ static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs) | |||
127 | regs->eip = (unsigned long)&p->ainsn.insn; | 127 | regs->eip = (unsigned long)&p->ainsn.insn; |
128 | } | 128 | } |
129 | 129 | ||
130 | void arch_prepare_kretprobe(struct kretprobe *rp, struct pt_regs *regs) | 130 | void __kprobes arch_prepare_kretprobe(struct kretprobe *rp, |
131 | struct pt_regs *regs) | ||
131 | { | 132 | { |
132 | unsigned long *sara = (unsigned long *)®s->esp; | 133 | unsigned long *sara = (unsigned long *)®s->esp; |
133 | struct kretprobe_instance *ri; | 134 | struct kretprobe_instance *ri; |
@@ -150,7 +151,7 @@ void arch_prepare_kretprobe(struct kretprobe *rp, struct pt_regs *regs) | |||
150 | * Interrupts are disabled on entry as trap3 is an interrupt gate and they | 151 | * Interrupts are disabled on entry as trap3 is an interrupt gate and they |
151 | * remain disabled thorough out this function. | 152 | * remain disabled thorough out this function. |
152 | */ | 153 | */ |
153 | static int kprobe_handler(struct pt_regs *regs) | 154 | static int __kprobes kprobe_handler(struct pt_regs *regs) |
154 | { | 155 | { |
155 | struct kprobe *p; | 156 | struct kprobe *p; |
156 | int ret = 0; | 157 | int ret = 0; |
@@ -176,7 +177,8 @@ static int kprobe_handler(struct pt_regs *regs) | |||
176 | Disarm the probe we just hit, and ignore it. */ | 177 | Disarm the probe we just hit, and ignore it. */ |
177 | p = get_kprobe(addr); | 178 | p = get_kprobe(addr); |
178 | if (p) { | 179 | if (p) { |
179 | if (kprobe_status == KPROBE_HIT_SS) { | 180 | if (kprobe_status == KPROBE_HIT_SS && |
181 | *p->ainsn.insn == BREAKPOINT_INSTRUCTION) { | ||
180 | regs->eflags &= ~TF_MASK; | 182 | regs->eflags &= ~TF_MASK; |
181 | regs->eflags |= kprobe_saved_eflags; | 183 | regs->eflags |= kprobe_saved_eflags; |
182 | unlock_kprobes(); | 184 | unlock_kprobes(); |
@@ -220,7 +222,10 @@ static int kprobe_handler(struct pt_regs *regs) | |||
220 | * either a probepoint or a debugger breakpoint | 222 | * either a probepoint or a debugger breakpoint |
221 | * at this address. In either case, no further | 223 | * at this address. In either case, no further |
222 | * handling of this interrupt is appropriate. | 224 | * handling of this interrupt is appropriate. |
225 | * Back up over the (now missing) int3 and run | ||
226 | * the original instruction. | ||
223 | */ | 227 | */ |
228 | regs->eip -= sizeof(kprobe_opcode_t); | ||
224 | ret = 1; | 229 | ret = 1; |
225 | } | 230 | } |
226 | /* Not one of ours: let kernel handle it */ | 231 | /* Not one of ours: let kernel handle it */ |
@@ -259,7 +264,7 @@ no_kprobe: | |||
259 | /* | 264 | /* |
260 | * Called when we hit the probe point at kretprobe_trampoline | 265 | * Called when we hit the probe point at kretprobe_trampoline |
261 | */ | 266 | */ |
262 | int trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) | 267 | int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) |
263 | { | 268 | { |
264 | struct kretprobe_instance *ri = NULL; | 269 | struct kretprobe_instance *ri = NULL; |
265 | struct hlist_head *head; | 270 | struct hlist_head *head; |
@@ -338,7 +343,7 @@ int trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) | |||
338 | * that is atop the stack is the address following the copied instruction. | 343 | * that is atop the stack is the address following the copied instruction. |
339 | * We need to make it the address following the original instruction. | 344 | * We need to make it the address following the original instruction. |
340 | */ | 345 | */ |
341 | static void resume_execution(struct kprobe *p, struct pt_regs *regs) | 346 | static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs) |
342 | { | 347 | { |
343 | unsigned long *tos = (unsigned long *)®s->esp; | 348 | unsigned long *tos = (unsigned long *)®s->esp; |
344 | unsigned long next_eip = 0; | 349 | unsigned long next_eip = 0; |
@@ -444,8 +449,8 @@ static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr) | |||
444 | /* | 449 | /* |
445 | * Wrapper routine to for handling exceptions. | 450 | * Wrapper routine to for handling exceptions. |
446 | */ | 451 | */ |
447 | int kprobe_exceptions_notify(struct notifier_block *self, unsigned long val, | 452 | int __kprobes kprobe_exceptions_notify(struct notifier_block *self, |
448 | void *data) | 453 | unsigned long val, void *data) |
449 | { | 454 | { |
450 | struct die_args *args = (struct die_args *)data; | 455 | struct die_args *args = (struct die_args *)data; |
451 | switch (val) { | 456 | switch (val) { |
@@ -473,7 +478,7 @@ int kprobe_exceptions_notify(struct notifier_block *self, unsigned long val, | |||
473 | return NOTIFY_DONE; | 478 | return NOTIFY_DONE; |
474 | } | 479 | } |
475 | 480 | ||
476 | int setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) | 481 | int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) |
477 | { | 482 | { |
478 | struct jprobe *jp = container_of(p, struct jprobe, kp); | 483 | struct jprobe *jp = container_of(p, struct jprobe, kp); |
479 | unsigned long addr; | 484 | unsigned long addr; |
@@ -495,7 +500,7 @@ int setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) | |||
495 | return 1; | 500 | return 1; |
496 | } | 501 | } |
497 | 502 | ||
498 | void jprobe_return(void) | 503 | void __kprobes jprobe_return(void) |
499 | { | 504 | { |
500 | preempt_enable_no_resched(); | 505 | preempt_enable_no_resched(); |
501 | asm volatile (" xchgl %%ebx,%%esp \n" | 506 | asm volatile (" xchgl %%ebx,%%esp \n" |
@@ -506,7 +511,7 @@ void jprobe_return(void) | |||
506 | (jprobe_saved_esp):"memory"); | 511 | (jprobe_saved_esp):"memory"); |
507 | } | 512 | } |
508 | 513 | ||
509 | int longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) | 514 | int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) |
510 | { | 515 | { |
511 | u8 *addr = (u8 *) (regs->eip - 1); | 516 | u8 *addr = (u8 *) (regs->eip - 1); |
512 | unsigned long stack_addr = (unsigned long)jprobe_saved_esp; | 517 | unsigned long stack_addr = (unsigned long)jprobe_saved_esp; |