diff options
author | Prasanna S Panchamukhi <prasanna@in.ibm.com> | 2005-09-06 18:19:29 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-09-07 19:58:00 -0400 |
commit | bb144a85c70a65730424ad1a9dc50fef66e5cafe (patch) | |
tree | eecffdc773b84cd1da172117354c3ade600608d1 | |
parent | 0f2fbdcbb041f9087da42f8ac2e81f2817098d2a (diff) |
[PATCH] Kprobes: prevent possible race conditions ppc64 changes
This patch contains the ppc64 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>
-rw-r--r-- | arch/ppc64/kernel/kprobes.c | 29 | ||||
-rw-r--r-- | arch/ppc64/kernel/misc.S | 4 | ||||
-rw-r--r-- | arch/ppc64/kernel/traps.c | 5 | ||||
-rw-r--r-- | arch/ppc64/kernel/vmlinux.lds.S | 1 | ||||
-rw-r--r-- | arch/ppc64/mm/fault.c | 5 | ||||
-rw-r--r-- | include/asm-ppc64/processor.h | 14 |
6 files changed, 38 insertions, 20 deletions
diff --git a/arch/ppc64/kernel/kprobes.c b/arch/ppc64/kernel/kprobes.c index a3d519518fb8..591e4b67b5a5 100644 --- a/arch/ppc64/kernel/kprobes.c +++ b/arch/ppc64/kernel/kprobes.c | |||
@@ -44,7 +44,7 @@ static struct kprobe *kprobe_prev; | |||
44 | static unsigned long kprobe_status_prev, kprobe_saved_msr_prev; | 44 | static unsigned long kprobe_status_prev, kprobe_saved_msr_prev; |
45 | static struct pt_regs jprobe_saved_regs; | 45 | static struct pt_regs jprobe_saved_regs; |
46 | 46 | ||
47 | int arch_prepare_kprobe(struct kprobe *p) | 47 | int __kprobes arch_prepare_kprobe(struct kprobe *p) |
48 | { | 48 | { |
49 | int ret = 0; | 49 | int ret = 0; |
50 | kprobe_opcode_t insn = *p->addr; | 50 | kprobe_opcode_t insn = *p->addr; |
@@ -68,27 +68,27 @@ int arch_prepare_kprobe(struct kprobe *p) | |||
68 | return ret; | 68 | return ret; |
69 | } | 69 | } |
70 | 70 | ||
71 | void arch_copy_kprobe(struct kprobe *p) | 71 | void __kprobes arch_copy_kprobe(struct kprobe *p) |
72 | { | 72 | { |
73 | memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t)); | 73 | memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t)); |
74 | p->opcode = *p->addr; | 74 | p->opcode = *p->addr; |
75 | } | 75 | } |
76 | 76 | ||
77 | void arch_arm_kprobe(struct kprobe *p) | 77 | void __kprobes arch_arm_kprobe(struct kprobe *p) |
78 | { | 78 | { |
79 | *p->addr = BREAKPOINT_INSTRUCTION; | 79 | *p->addr = BREAKPOINT_INSTRUCTION; |
80 | flush_icache_range((unsigned long) p->addr, | 80 | flush_icache_range((unsigned long) p->addr, |
81 | (unsigned long) p->addr + sizeof(kprobe_opcode_t)); | 81 | (unsigned long) p->addr + sizeof(kprobe_opcode_t)); |
82 | } | 82 | } |
83 | 83 | ||
84 | void arch_disarm_kprobe(struct kprobe *p) | 84 | void __kprobes arch_disarm_kprobe(struct kprobe *p) |
85 | { | 85 | { |
86 | *p->addr = p->opcode; | 86 | *p->addr = p->opcode; |
87 | flush_icache_range((unsigned long) p->addr, | 87 | flush_icache_range((unsigned long) p->addr, |
88 | (unsigned long) p->addr + sizeof(kprobe_opcode_t)); | 88 | (unsigned long) p->addr + sizeof(kprobe_opcode_t)); |
89 | } | 89 | } |
90 | 90 | ||
91 | void arch_remove_kprobe(struct kprobe *p) | 91 | void __kprobes arch_remove_kprobe(struct kprobe *p) |
92 | { | 92 | { |
93 | up(&kprobe_mutex); | 93 | up(&kprobe_mutex); |
94 | free_insn_slot(p->ainsn.insn); | 94 | free_insn_slot(p->ainsn.insn); |
@@ -122,7 +122,8 @@ static inline void restore_previous_kprobe(void) | |||
122 | kprobe_saved_msr = kprobe_saved_msr_prev; | 122 | kprobe_saved_msr = kprobe_saved_msr_prev; |
123 | } | 123 | } |
124 | 124 | ||
125 | void arch_prepare_kretprobe(struct kretprobe *rp, struct pt_regs *regs) | 125 | void __kprobes arch_prepare_kretprobe(struct kretprobe *rp, |
126 | struct pt_regs *regs) | ||
126 | { | 127 | { |
127 | struct kretprobe_instance *ri; | 128 | struct kretprobe_instance *ri; |
128 | 129 | ||
@@ -244,7 +245,7 @@ void kretprobe_trampoline_holder(void) | |||
244 | /* | 245 | /* |
245 | * Called when the probe at kretprobe trampoline is hit | 246 | * Called when the probe at kretprobe trampoline is hit |
246 | */ | 247 | */ |
247 | int trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) | 248 | int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) |
248 | { | 249 | { |
249 | struct kretprobe_instance *ri = NULL; | 250 | struct kretprobe_instance *ri = NULL; |
250 | struct hlist_head *head; | 251 | struct hlist_head *head; |
@@ -308,7 +309,7 @@ int trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) | |||
308 | * single-stepped a copy of the instruction. The address of this | 309 | * single-stepped a copy of the instruction. The address of this |
309 | * copy is p->ainsn.insn. | 310 | * copy is p->ainsn.insn. |
310 | */ | 311 | */ |
311 | static void resume_execution(struct kprobe *p, struct pt_regs *regs) | 312 | static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs) |
312 | { | 313 | { |
313 | int ret; | 314 | int ret; |
314 | unsigned int insn = *p->ainsn.insn; | 315 | unsigned int insn = *p->ainsn.insn; |
@@ -373,8 +374,8 @@ static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr) | |||
373 | /* | 374 | /* |
374 | * Wrapper routine to for handling exceptions. | 375 | * Wrapper routine to for handling exceptions. |
375 | */ | 376 | */ |
376 | int kprobe_exceptions_notify(struct notifier_block *self, unsigned long val, | 377 | int __kprobes kprobe_exceptions_notify(struct notifier_block *self, |
377 | void *data) | 378 | unsigned long val, void *data) |
378 | { | 379 | { |
379 | struct die_args *args = (struct die_args *)data; | 380 | struct die_args *args = (struct die_args *)data; |
380 | int ret = NOTIFY_DONE; | 381 | int ret = NOTIFY_DONE; |
@@ -406,7 +407,7 @@ int kprobe_exceptions_notify(struct notifier_block *self, unsigned long val, | |||
406 | return ret; | 407 | return ret; |
407 | } | 408 | } |
408 | 409 | ||
409 | int setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) | 410 | int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) |
410 | { | 411 | { |
411 | struct jprobe *jp = container_of(p, struct jprobe, kp); | 412 | struct jprobe *jp = container_of(p, struct jprobe, kp); |
412 | 413 | ||
@@ -419,16 +420,16 @@ int setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) | |||
419 | return 1; | 420 | return 1; |
420 | } | 421 | } |
421 | 422 | ||
422 | void jprobe_return(void) | 423 | void __kprobes jprobe_return(void) |
423 | { | 424 | { |
424 | asm volatile("trap" ::: "memory"); | 425 | asm volatile("trap" ::: "memory"); |
425 | } | 426 | } |
426 | 427 | ||
427 | void jprobe_return_end(void) | 428 | void __kprobes jprobe_return_end(void) |
428 | { | 429 | { |
429 | }; | 430 | }; |
430 | 431 | ||
431 | int longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) | 432 | int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) |
432 | { | 433 | { |
433 | /* | 434 | /* |
434 | * FIXME - we should ideally be validating that we got here 'cos | 435 | * FIXME - we should ideally be validating that we got here 'cos |
diff --git a/arch/ppc64/kernel/misc.S b/arch/ppc64/kernel/misc.S index 2164bd7b4ef6..6d860c1d9fa0 100644 --- a/arch/ppc64/kernel/misc.S +++ b/arch/ppc64/kernel/misc.S | |||
@@ -183,7 +183,7 @@ PPC64_CACHES: | |||
183 | * flush all bytes from start through stop-1 inclusive | 183 | * flush all bytes from start through stop-1 inclusive |
184 | */ | 184 | */ |
185 | 185 | ||
186 | _GLOBAL(__flush_icache_range) | 186 | _KPROBE(__flush_icache_range) |
187 | 187 | ||
188 | /* | 188 | /* |
189 | * Flush the data cache to memory | 189 | * Flush the data cache to memory |
@@ -223,7 +223,7 @@ _GLOBAL(__flush_icache_range) | |||
223 | bdnz 2b | 223 | bdnz 2b |
224 | isync | 224 | isync |
225 | blr | 225 | blr |
226 | 226 | .previous .text | |
227 | /* | 227 | /* |
228 | * Like above, but only do the D-cache. | 228 | * Like above, but only do the D-cache. |
229 | * | 229 | * |
diff --git a/arch/ppc64/kernel/traps.c b/arch/ppc64/kernel/traps.c index a8d5e83ee89f..7467ae508e6e 100644 --- a/arch/ppc64/kernel/traps.c +++ b/arch/ppc64/kernel/traps.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/init.h> | 30 | #include <linux/init.h> |
31 | #include <linux/module.h> | 31 | #include <linux/module.h> |
32 | #include <linux/delay.h> | 32 | #include <linux/delay.h> |
33 | #include <linux/kprobes.h> | ||
33 | #include <asm/kdebug.h> | 34 | #include <asm/kdebug.h> |
34 | 35 | ||
35 | #include <asm/pgtable.h> | 36 | #include <asm/pgtable.h> |
@@ -220,7 +221,7 @@ void instruction_breakpoint_exception(struct pt_regs *regs) | |||
220 | _exception(SIGTRAP, regs, TRAP_BRKPT, regs->nip); | 221 | _exception(SIGTRAP, regs, TRAP_BRKPT, regs->nip); |
221 | } | 222 | } |
222 | 223 | ||
223 | void single_step_exception(struct pt_regs *regs) | 224 | void __kprobes single_step_exception(struct pt_regs *regs) |
224 | { | 225 | { |
225 | regs->msr &= ~MSR_SE; /* Turn off 'trace' bit */ | 226 | regs->msr &= ~MSR_SE; /* Turn off 'trace' bit */ |
226 | 227 | ||
@@ -398,7 +399,7 @@ check_bug_trap(struct pt_regs *regs) | |||
398 | return 0; | 399 | return 0; |
399 | } | 400 | } |
400 | 401 | ||
401 | void program_check_exception(struct pt_regs *regs) | 402 | void __kprobes program_check_exception(struct pt_regs *regs) |
402 | { | 403 | { |
403 | if (debugger_fault_handler(regs)) | 404 | if (debugger_fault_handler(regs)) |
404 | return; | 405 | return; |
diff --git a/arch/ppc64/kernel/vmlinux.lds.S b/arch/ppc64/kernel/vmlinux.lds.S index 4103cc13f8d6..0306510bc4ff 100644 --- a/arch/ppc64/kernel/vmlinux.lds.S +++ b/arch/ppc64/kernel/vmlinux.lds.S | |||
@@ -15,6 +15,7 @@ SECTIONS | |||
15 | *(.text .text.*) | 15 | *(.text .text.*) |
16 | SCHED_TEXT | 16 | SCHED_TEXT |
17 | LOCK_TEXT | 17 | LOCK_TEXT |
18 | KPROBES_TEXT | ||
18 | *(.fixup) | 19 | *(.fixup) |
19 | . = ALIGN(4096); | 20 | . = ALIGN(4096); |
20 | _etext = .; | 21 | _etext = .; |
diff --git a/arch/ppc64/mm/fault.c b/arch/ppc64/mm/fault.c index 20b0f37e8bf8..772f0714a5b7 100644 --- a/arch/ppc64/mm/fault.c +++ b/arch/ppc64/mm/fault.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/interrupt.h> | 29 | #include <linux/interrupt.h> |
30 | #include <linux/smp_lock.h> | 30 | #include <linux/smp_lock.h> |
31 | #include <linux/module.h> | 31 | #include <linux/module.h> |
32 | #include <linux/kprobes.h> | ||
32 | 33 | ||
33 | #include <asm/page.h> | 34 | #include <asm/page.h> |
34 | #include <asm/pgtable.h> | 35 | #include <asm/pgtable.h> |
@@ -84,8 +85,8 @@ static int store_updates_sp(struct pt_regs *regs) | |||
84 | * The return value is 0 if the fault was handled, or the signal | 85 | * The return value is 0 if the fault was handled, or the signal |
85 | * number if this is a kernel fault that can't be handled here. | 86 | * number if this is a kernel fault that can't be handled here. |
86 | */ | 87 | */ |
87 | int do_page_fault(struct pt_regs *regs, unsigned long address, | 88 | int __kprobes do_page_fault(struct pt_regs *regs, unsigned long address, |
88 | unsigned long error_code) | 89 | unsigned long error_code) |
89 | { | 90 | { |
90 | struct vm_area_struct * vma; | 91 | struct vm_area_struct * vma; |
91 | struct mm_struct *mm = current->mm; | 92 | struct mm_struct *mm = current->mm; |
diff --git a/include/asm-ppc64/processor.h b/include/asm-ppc64/processor.h index 7bd4796f1236..8bd7aa959385 100644 --- a/include/asm-ppc64/processor.h +++ b/include/asm-ppc64/processor.h | |||
@@ -311,6 +311,20 @@ name: \ | |||
311 | .type GLUE(.,name),@function; \ | 311 | .type GLUE(.,name),@function; \ |
312 | GLUE(.,name): | 312 | GLUE(.,name): |
313 | 313 | ||
314 | #define _KPROBE(name) \ | ||
315 | .section ".kprobes.text","a"; \ | ||
316 | .align 2 ; \ | ||
317 | .globl name; \ | ||
318 | .globl GLUE(.,name); \ | ||
319 | .section ".opd","aw"; \ | ||
320 | name: \ | ||
321 | .quad GLUE(.,name); \ | ||
322 | .quad .TOC.@tocbase; \ | ||
323 | .quad 0; \ | ||
324 | .previous; \ | ||
325 | .type GLUE(.,name),@function; \ | ||
326 | GLUE(.,name): | ||
327 | |||
314 | #define _STATIC(name) \ | 328 | #define _STATIC(name) \ |
315 | .section ".text"; \ | 329 | .section ".text"; \ |
316 | .align 2 ; \ | 330 | .align 2 ; \ |