diff options
author | Prasanna S Panchamukhi <prasanna@in.ibm.com> | 2005-09-06 18:19:27 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-09-07 19:57:59 -0400 |
commit | 3d97ae5b958855ac007b6f56a0f94ab8ade09e9e (patch) | |
tree | 6258b62fdbf4fcc7086e86d920e23609022d0881 /arch/i386/kernel/kprobes.c | |
parent | d0aaff9796c3310326d10da44fc0faed352a1d29 (diff) |
[PATCH] kprobes: prevent possible race conditions i386 changes
This patch contains the i386 architecture specific changes to prevent the
possible race conditions.
Signed-off-by: Prasanna S Panchamukhi <prasanna@in.ibm.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch/i386/kernel/kprobes.c')
-rw-r--r-- | arch/i386/kernel/kprobes.c | 29 |
1 files changed, 15 insertions, 14 deletions
diff --git a/arch/i386/kernel/kprobes.c b/arch/i386/kernel/kprobes.c index a6d8c45961d3..7fb5a6f4a563 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; |
@@ -259,7 +260,7 @@ no_kprobe: | |||
259 | /* | 260 | /* |
260 | * Called when we hit the probe point at kretprobe_trampoline | 261 | * Called when we hit the probe point at kretprobe_trampoline |
261 | */ | 262 | */ |
262 | int trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) | 263 | int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) |
263 | { | 264 | { |
264 | struct kretprobe_instance *ri = NULL; | 265 | struct kretprobe_instance *ri = NULL; |
265 | struct hlist_head *head; | 266 | struct hlist_head *head; |
@@ -338,7 +339,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. | 339 | * that is atop the stack is the address following the copied instruction. |
339 | * We need to make it the address following the original instruction. | 340 | * We need to make it the address following the original instruction. |
340 | */ | 341 | */ |
341 | static void resume_execution(struct kprobe *p, struct pt_regs *regs) | 342 | static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs) |
342 | { | 343 | { |
343 | unsigned long *tos = (unsigned long *)®s->esp; | 344 | unsigned long *tos = (unsigned long *)®s->esp; |
344 | unsigned long next_eip = 0; | 345 | unsigned long next_eip = 0; |
@@ -444,8 +445,8 @@ static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr) | |||
444 | /* | 445 | /* |
445 | * Wrapper routine to for handling exceptions. | 446 | * Wrapper routine to for handling exceptions. |
446 | */ | 447 | */ |
447 | int kprobe_exceptions_notify(struct notifier_block *self, unsigned long val, | 448 | int __kprobes kprobe_exceptions_notify(struct notifier_block *self, |
448 | void *data) | 449 | unsigned long val, void *data) |
449 | { | 450 | { |
450 | struct die_args *args = (struct die_args *)data; | 451 | struct die_args *args = (struct die_args *)data; |
451 | switch (val) { | 452 | switch (val) { |
@@ -473,7 +474,7 @@ int kprobe_exceptions_notify(struct notifier_block *self, unsigned long val, | |||
473 | return NOTIFY_DONE; | 474 | return NOTIFY_DONE; |
474 | } | 475 | } |
475 | 476 | ||
476 | int setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) | 477 | int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) |
477 | { | 478 | { |
478 | struct jprobe *jp = container_of(p, struct jprobe, kp); | 479 | struct jprobe *jp = container_of(p, struct jprobe, kp); |
479 | unsigned long addr; | 480 | unsigned long addr; |
@@ -495,7 +496,7 @@ int setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) | |||
495 | return 1; | 496 | return 1; |
496 | } | 497 | } |
497 | 498 | ||
498 | void jprobe_return(void) | 499 | void __kprobes jprobe_return(void) |
499 | { | 500 | { |
500 | preempt_enable_no_resched(); | 501 | preempt_enable_no_resched(); |
501 | asm volatile (" xchgl %%ebx,%%esp \n" | 502 | asm volatile (" xchgl %%ebx,%%esp \n" |
@@ -506,7 +507,7 @@ void jprobe_return(void) | |||
506 | (jprobe_saved_esp):"memory"); | 507 | (jprobe_saved_esp):"memory"); |
507 | } | 508 | } |
508 | 509 | ||
509 | int longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) | 510 | int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) |
510 | { | 511 | { |
511 | u8 *addr = (u8 *) (regs->eip - 1); | 512 | u8 *addr = (u8 *) (regs->eip - 1); |
512 | unsigned long stack_addr = (unsigned long)jprobe_saved_esp; | 513 | unsigned long stack_addr = (unsigned long)jprobe_saved_esp; |