diff options
author | Prasanna S Panchamukhi <prasanna@in.ibm.com> | 2005-09-06 18:19:30 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-09-07 19:58:00 -0400 |
commit | 1f7ad57b75ab0fba27455c7344a6ab7aa6bd90c5 (patch) | |
tree | e0dd1b5a23c0e7088fe6bab276118accf4dc14c1 | |
parent | bb144a85c70a65730424ad1a9dc50fef66e5cafe (diff) |
[PATCH] Kprobes: prevent possible race conditions ia64 changes
This patch contains the ia64 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/ia64/kernel/jprobes.S | 1 | ||||
-rw-r--r-- | arch/ia64/kernel/kprobes.c | 57 | ||||
-rw-r--r-- | arch/ia64/kernel/traps.c | 5 | ||||
-rw-r--r-- | arch/ia64/kernel/vmlinux.lds.S | 1 | ||||
-rw-r--r-- | arch/ia64/lib/flush.S | 1 | ||||
-rw-r--r-- | arch/ia64/mm/fault.c | 3 |
6 files changed, 41 insertions, 27 deletions
diff --git a/arch/ia64/kernel/jprobes.S b/arch/ia64/kernel/jprobes.S index b7fa3ccd2b0f..2323377e3695 100644 --- a/arch/ia64/kernel/jprobes.S +++ b/arch/ia64/kernel/jprobes.S | |||
@@ -49,6 +49,7 @@ | |||
49 | /* | 49 | /* |
50 | * void jprobe_break(void) | 50 | * void jprobe_break(void) |
51 | */ | 51 | */ |
52 | .section .kprobes.text, "ax" | ||
52 | ENTRY(jprobe_break) | 53 | ENTRY(jprobe_break) |
53 | break.m 0x80300 | 54 | break.m 0x80300 |
54 | END(jprobe_break) | 55 | END(jprobe_break) |
diff --git a/arch/ia64/kernel/kprobes.c b/arch/ia64/kernel/kprobes.c index 884f5cd27d8a..82a41ac29386 100644 --- a/arch/ia64/kernel/kprobes.c +++ b/arch/ia64/kernel/kprobes.c | |||
@@ -87,8 +87,10 @@ static enum instruction_type bundle_encoding[32][3] = { | |||
87 | * is IP relative instruction and update the kprobe | 87 | * is IP relative instruction and update the kprobe |
88 | * inst flag accordingly | 88 | * inst flag accordingly |
89 | */ | 89 | */ |
90 | static void update_kprobe_inst_flag(uint template, uint slot, uint major_opcode, | 90 | static void __kprobes update_kprobe_inst_flag(uint template, uint slot, |
91 | unsigned long kprobe_inst, struct kprobe *p) | 91 | uint major_opcode, |
92 | unsigned long kprobe_inst, | ||
93 | struct kprobe *p) | ||
92 | { | 94 | { |
93 | p->ainsn.inst_flag = 0; | 95 | p->ainsn.inst_flag = 0; |
94 | p->ainsn.target_br_reg = 0; | 96 | p->ainsn.target_br_reg = 0; |
@@ -126,8 +128,10 @@ static void update_kprobe_inst_flag(uint template, uint slot, uint major_opcode | |||
126 | * Returns 0 if supported | 128 | * Returns 0 if supported |
127 | * Returns -EINVAL if unsupported | 129 | * Returns -EINVAL if unsupported |
128 | */ | 130 | */ |
129 | static int unsupported_inst(uint template, uint slot, uint major_opcode, | 131 | static int __kprobes unsupported_inst(uint template, uint slot, |
130 | unsigned long kprobe_inst, struct kprobe *p) | 132 | uint major_opcode, |
133 | unsigned long kprobe_inst, | ||
134 | struct kprobe *p) | ||
131 | { | 135 | { |
132 | unsigned long addr = (unsigned long)p->addr; | 136 | unsigned long addr = (unsigned long)p->addr; |
133 | 137 | ||
@@ -168,8 +172,9 @@ static int unsupported_inst(uint template, uint slot, uint major_opcode, | |||
168 | * on which we are inserting kprobe is cmp instruction | 172 | * on which we are inserting kprobe is cmp instruction |
169 | * with ctype as unc. | 173 | * with ctype as unc. |
170 | */ | 174 | */ |
171 | static uint is_cmp_ctype_unc_inst(uint template, uint slot, uint major_opcode, | 175 | static uint __kprobes is_cmp_ctype_unc_inst(uint template, uint slot, |
172 | unsigned long kprobe_inst) | 176 | uint major_opcode, |
177 | unsigned long kprobe_inst) | ||
173 | { | 178 | { |
174 | cmp_inst_t cmp_inst; | 179 | cmp_inst_t cmp_inst; |
175 | uint ctype_unc = 0; | 180 | uint ctype_unc = 0; |
@@ -201,8 +206,10 @@ out: | |||
201 | * In this function we override the bundle with | 206 | * In this function we override the bundle with |
202 | * the break instruction at the given slot. | 207 | * the break instruction at the given slot. |
203 | */ | 208 | */ |
204 | static void prepare_break_inst(uint template, uint slot, uint major_opcode, | 209 | static void __kprobes prepare_break_inst(uint template, uint slot, |
205 | unsigned long kprobe_inst, struct kprobe *p) | 210 | uint major_opcode, |
211 | unsigned long kprobe_inst, | ||
212 | struct kprobe *p) | ||
206 | { | 213 | { |
207 | unsigned long break_inst = BREAK_INST; | 214 | unsigned long break_inst = BREAK_INST; |
208 | bundle_t *bundle = &p->ainsn.insn.bundle; | 215 | bundle_t *bundle = &p->ainsn.insn.bundle; |
@@ -271,7 +278,8 @@ static inline int in_ivt_functions(unsigned long addr) | |||
271 | && addr < (unsigned long)__end_ivt_text); | 278 | && addr < (unsigned long)__end_ivt_text); |
272 | } | 279 | } |
273 | 280 | ||
274 | static int valid_kprobe_addr(int template, int slot, unsigned long addr) | 281 | static int __kprobes valid_kprobe_addr(int template, int slot, |
282 | unsigned long addr) | ||
275 | { | 283 | { |
276 | if ((slot > 2) || ((bundle_encoding[template][1] == L) && slot > 1)) { | 284 | if ((slot > 2) || ((bundle_encoding[template][1] == L) && slot > 1)) { |
277 | printk(KERN_WARNING "Attempting to insert unaligned kprobe " | 285 | printk(KERN_WARNING "Attempting to insert unaligned kprobe " |
@@ -323,7 +331,7 @@ static void kretprobe_trampoline(void) | |||
323 | * - cleanup by marking the instance as unused | 331 | * - cleanup by marking the instance as unused |
324 | * - long jump back to the original return address | 332 | * - long jump back to the original return address |
325 | */ | 333 | */ |
326 | int trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) | 334 | int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) |
327 | { | 335 | { |
328 | struct kretprobe_instance *ri = NULL; | 336 | struct kretprobe_instance *ri = NULL; |
329 | struct hlist_head *head; | 337 | struct hlist_head *head; |
@@ -381,7 +389,8 @@ int trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) | |||
381 | return 1; | 389 | return 1; |
382 | } | 390 | } |
383 | 391 | ||
384 | void arch_prepare_kretprobe(struct kretprobe *rp, struct pt_regs *regs) | 392 | void __kprobes arch_prepare_kretprobe(struct kretprobe *rp, |
393 | struct pt_regs *regs) | ||
385 | { | 394 | { |
386 | struct kretprobe_instance *ri; | 395 | struct kretprobe_instance *ri; |
387 | 396 | ||
@@ -399,7 +408,7 @@ void arch_prepare_kretprobe(struct kretprobe *rp, struct pt_regs *regs) | |||
399 | } | 408 | } |
400 | } | 409 | } |
401 | 410 | ||
402 | int arch_prepare_kprobe(struct kprobe *p) | 411 | int __kprobes arch_prepare_kprobe(struct kprobe *p) |
403 | { | 412 | { |
404 | unsigned long addr = (unsigned long) p->addr; | 413 | unsigned long addr = (unsigned long) p->addr; |
405 | unsigned long *kprobe_addr = (unsigned long *)(addr & ~0xFULL); | 414 | unsigned long *kprobe_addr = (unsigned long *)(addr & ~0xFULL); |
@@ -430,7 +439,7 @@ int arch_prepare_kprobe(struct kprobe *p) | |||
430 | return 0; | 439 | return 0; |
431 | } | 440 | } |
432 | 441 | ||
433 | void arch_arm_kprobe(struct kprobe *p) | 442 | void __kprobes arch_arm_kprobe(struct kprobe *p) |
434 | { | 443 | { |
435 | unsigned long addr = (unsigned long)p->addr; | 444 | unsigned long addr = (unsigned long)p->addr; |
436 | unsigned long arm_addr = addr & ~0xFULL; | 445 | unsigned long arm_addr = addr & ~0xFULL; |
@@ -439,7 +448,7 @@ void arch_arm_kprobe(struct kprobe *p) | |||
439 | flush_icache_range(arm_addr, arm_addr + sizeof(bundle_t)); | 448 | flush_icache_range(arm_addr, arm_addr + sizeof(bundle_t)); |
440 | } | 449 | } |
441 | 450 | ||
442 | void arch_disarm_kprobe(struct kprobe *p) | 451 | void __kprobes arch_disarm_kprobe(struct kprobe *p) |
443 | { | 452 | { |
444 | unsigned long addr = (unsigned long)p->addr; | 453 | unsigned long addr = (unsigned long)p->addr; |
445 | unsigned long arm_addr = addr & ~0xFULL; | 454 | unsigned long arm_addr = addr & ~0xFULL; |
@@ -449,7 +458,7 @@ void arch_disarm_kprobe(struct kprobe *p) | |||
449 | flush_icache_range(arm_addr, arm_addr + sizeof(bundle_t)); | 458 | flush_icache_range(arm_addr, arm_addr + sizeof(bundle_t)); |
450 | } | 459 | } |
451 | 460 | ||
452 | void arch_remove_kprobe(struct kprobe *p) | 461 | void __kprobes arch_remove_kprobe(struct kprobe *p) |
453 | { | 462 | { |
454 | } | 463 | } |
455 | 464 | ||
@@ -461,7 +470,7 @@ void arch_remove_kprobe(struct kprobe *p) | |||
461 | * to original stack address, handle the case where we need to fixup the | 470 | * to original stack address, handle the case where we need to fixup the |
462 | * relative IP address and/or fixup branch register. | 471 | * relative IP address and/or fixup branch register. |
463 | */ | 472 | */ |
464 | static void resume_execution(struct kprobe *p, struct pt_regs *regs) | 473 | static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs) |
465 | { | 474 | { |
466 | unsigned long bundle_addr = ((unsigned long) (&p->opcode.bundle)) & ~0xFULL; | 475 | unsigned long bundle_addr = ((unsigned long) (&p->opcode.bundle)) & ~0xFULL; |
467 | unsigned long resume_addr = (unsigned long)p->addr & ~0xFULL; | 476 | unsigned long resume_addr = (unsigned long)p->addr & ~0xFULL; |
@@ -528,7 +537,7 @@ turn_ss_off: | |||
528 | ia64_psr(regs)->ss = 0; | 537 | ia64_psr(regs)->ss = 0; |
529 | } | 538 | } |
530 | 539 | ||
531 | static void prepare_ss(struct kprobe *p, struct pt_regs *regs) | 540 | static void __kprobes prepare_ss(struct kprobe *p, struct pt_regs *regs) |
532 | { | 541 | { |
533 | unsigned long bundle_addr = (unsigned long) &p->opcode.bundle; | 542 | unsigned long bundle_addr = (unsigned long) &p->opcode.bundle; |
534 | unsigned long slot = (unsigned long)p->addr & 0xf; | 543 | unsigned long slot = (unsigned long)p->addr & 0xf; |
@@ -545,7 +554,7 @@ static void prepare_ss(struct kprobe *p, struct pt_regs *regs) | |||
545 | ia64_psr(regs)->ss = 1; | 554 | ia64_psr(regs)->ss = 1; |
546 | } | 555 | } |
547 | 556 | ||
548 | static int pre_kprobes_handler(struct die_args *args) | 557 | static int __kprobes pre_kprobes_handler(struct die_args *args) |
549 | { | 558 | { |
550 | struct kprobe *p; | 559 | struct kprobe *p; |
551 | int ret = 0; | 560 | int ret = 0; |
@@ -616,7 +625,7 @@ no_kprobe: | |||
616 | return ret; | 625 | return ret; |
617 | } | 626 | } |
618 | 627 | ||
619 | static int post_kprobes_handler(struct pt_regs *regs) | 628 | static int __kprobes post_kprobes_handler(struct pt_regs *regs) |
620 | { | 629 | { |
621 | if (!kprobe_running()) | 630 | if (!kprobe_running()) |
622 | return 0; | 631 | return 0; |
@@ -641,7 +650,7 @@ out: | |||
641 | return 1; | 650 | return 1; |
642 | } | 651 | } |
643 | 652 | ||
644 | static int kprobes_fault_handler(struct pt_regs *regs, int trapnr) | 653 | static int __kprobes kprobes_fault_handler(struct pt_regs *regs, int trapnr) |
645 | { | 654 | { |
646 | if (!kprobe_running()) | 655 | if (!kprobe_running()) |
647 | return 0; | 656 | return 0; |
@@ -659,8 +668,8 @@ static int kprobes_fault_handler(struct pt_regs *regs, int trapnr) | |||
659 | return 0; | 668 | return 0; |
660 | } | 669 | } |
661 | 670 | ||
662 | int kprobe_exceptions_notify(struct notifier_block *self, unsigned long val, | 671 | int __kprobes kprobe_exceptions_notify(struct notifier_block *self, |
663 | void *data) | 672 | unsigned long val, void *data) |
664 | { | 673 | { |
665 | struct die_args *args = (struct die_args *)data; | 674 | struct die_args *args = (struct die_args *)data; |
666 | switch(val) { | 675 | switch(val) { |
@@ -681,7 +690,7 @@ int kprobe_exceptions_notify(struct notifier_block *self, unsigned long val, | |||
681 | return NOTIFY_DONE; | 690 | return NOTIFY_DONE; |
682 | } | 691 | } |
683 | 692 | ||
684 | int setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) | 693 | int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) |
685 | { | 694 | { |
686 | struct jprobe *jp = container_of(p, struct jprobe, kp); | 695 | struct jprobe *jp = container_of(p, struct jprobe, kp); |
687 | unsigned long addr = ((struct fnptr *)(jp->entry))->ip; | 696 | unsigned long addr = ((struct fnptr *)(jp->entry))->ip; |
@@ -703,7 +712,7 @@ int setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) | |||
703 | return 1; | 712 | return 1; |
704 | } | 713 | } |
705 | 714 | ||
706 | int longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) | 715 | int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) |
707 | { | 716 | { |
708 | *regs = jprobe_saved_regs; | 717 | *regs = jprobe_saved_regs; |
709 | return 1; | 718 | return 1; |
diff --git a/arch/ia64/kernel/traps.c b/arch/ia64/kernel/traps.c index 4440c8343fa4..f970359e7edf 100644 --- a/arch/ia64/kernel/traps.c +++ b/arch/ia64/kernel/traps.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/vt_kern.h> /* For unblank_screen() */ | 15 | #include <linux/vt_kern.h> /* For unblank_screen() */ |
16 | #include <linux/module.h> /* for EXPORT_SYMBOL */ | 16 | #include <linux/module.h> /* for EXPORT_SYMBOL */ |
17 | #include <linux/hardirq.h> | 17 | #include <linux/hardirq.h> |
18 | #include <linux/kprobes.h> | ||
18 | 19 | ||
19 | #include <asm/fpswa.h> | 20 | #include <asm/fpswa.h> |
20 | #include <asm/ia32.h> | 21 | #include <asm/ia32.h> |
@@ -122,7 +123,7 @@ die_if_kernel (char *str, struct pt_regs *regs, long err) | |||
122 | } | 123 | } |
123 | 124 | ||
124 | void | 125 | void |
125 | ia64_bad_break (unsigned long break_num, struct pt_regs *regs) | 126 | __kprobes ia64_bad_break (unsigned long break_num, struct pt_regs *regs) |
126 | { | 127 | { |
127 | siginfo_t siginfo; | 128 | siginfo_t siginfo; |
128 | int sig, code; | 129 | int sig, code; |
@@ -444,7 +445,7 @@ ia64_illegal_op_fault (unsigned long ec, long arg1, long arg2, long arg3, | |||
444 | return rv; | 445 | return rv; |
445 | } | 446 | } |
446 | 447 | ||
447 | void | 448 | void __kprobes |
448 | ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa, | 449 | ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa, |
449 | unsigned long iim, unsigned long itir, long arg5, long arg6, | 450 | unsigned long iim, unsigned long itir, long arg5, long arg6, |
450 | long arg7, struct pt_regs regs) | 451 | long arg7, struct pt_regs regs) |
diff --git a/arch/ia64/kernel/vmlinux.lds.S b/arch/ia64/kernel/vmlinux.lds.S index a676e79e0681..30d8564e9603 100644 --- a/arch/ia64/kernel/vmlinux.lds.S +++ b/arch/ia64/kernel/vmlinux.lds.S | |||
@@ -48,6 +48,7 @@ SECTIONS | |||
48 | *(.text) | 48 | *(.text) |
49 | SCHED_TEXT | 49 | SCHED_TEXT |
50 | LOCK_TEXT | 50 | LOCK_TEXT |
51 | KPROBES_TEXT | ||
51 | *(.gnu.linkonce.t*) | 52 | *(.gnu.linkonce.t*) |
52 | } | 53 | } |
53 | .text2 : AT(ADDR(.text2) - LOAD_OFFSET) | 54 | .text2 : AT(ADDR(.text2) - LOAD_OFFSET) |
diff --git a/arch/ia64/lib/flush.S b/arch/ia64/lib/flush.S index 3e2cfa2c6d39..2a0d27f2f21b 100644 --- a/arch/ia64/lib/flush.S +++ b/arch/ia64/lib/flush.S | |||
@@ -20,6 +20,7 @@ | |||
20 | * | 20 | * |
21 | * Note: "in0" and "in1" are preserved for debugging purposes. | 21 | * Note: "in0" and "in1" are preserved for debugging purposes. |
22 | */ | 22 | */ |
23 | .section .kprobes.text,"ax" | ||
23 | GLOBAL_ENTRY(flush_icache_range) | 24 | GLOBAL_ENTRY(flush_icache_range) |
24 | 25 | ||
25 | .prologue | 26 | .prologue |
diff --git a/arch/ia64/mm/fault.c b/arch/ia64/mm/fault.c index ff62551eb3a1..24614869e866 100644 --- a/arch/ia64/mm/fault.c +++ b/arch/ia64/mm/fault.c | |||
@@ -9,6 +9,7 @@ | |||
9 | #include <linux/mm.h> | 9 | #include <linux/mm.h> |
10 | #include <linux/smp_lock.h> | 10 | #include <linux/smp_lock.h> |
11 | #include <linux/interrupt.h> | 11 | #include <linux/interrupt.h> |
12 | #include <linux/kprobes.h> | ||
12 | 13 | ||
13 | #include <asm/pgtable.h> | 14 | #include <asm/pgtable.h> |
14 | #include <asm/processor.h> | 15 | #include <asm/processor.h> |
@@ -76,7 +77,7 @@ mapped_kernel_page_is_present (unsigned long address) | |||
76 | return pte_present(pte); | 77 | return pte_present(pte); |
77 | } | 78 | } |
78 | 79 | ||
79 | void | 80 | void __kprobes |
80 | ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *regs) | 81 | ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *regs) |
81 | { | 82 | { |
82 | int signal = SIGSEGV, code = SEGV_MAPERR; | 83 | int signal = SIGSEGV, code = SEGV_MAPERR; |