aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPrasanna S Panchamukhi <prasanna@in.ibm.com>2005-09-06 18:19:30 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2005-09-07 19:58:00 -0400
commit1f7ad57b75ab0fba27455c7344a6ab7aa6bd90c5 (patch)
treee0dd1b5a23c0e7088fe6bab276118accf4dc14c1
parentbb144a85c70a65730424ad1a9dc50fef66e5cafe (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.S1
-rw-r--r--arch/ia64/kernel/kprobes.c57
-rw-r--r--arch/ia64/kernel/traps.c5
-rw-r--r--arch/ia64/kernel/vmlinux.lds.S1
-rw-r--r--arch/ia64/lib/flush.S1
-rw-r--r--arch/ia64/mm/fault.c3
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"
52ENTRY(jprobe_break) 53ENTRY(jprobe_break)
53 break.m 0x80300 54 break.m 0x80300
54END(jprobe_break) 55END(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 */
90static void update_kprobe_inst_flag(uint template, uint slot, uint major_opcode, 90static 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 */
129static int unsupported_inst(uint template, uint slot, uint major_opcode, 131static 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 */
171static uint is_cmp_ctype_unc_inst(uint template, uint slot, uint major_opcode, 175static uint __kprobes is_cmp_ctype_unc_inst(uint template, uint slot,
172unsigned 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 */
204static void prepare_break_inst(uint template, uint slot, uint major_opcode, 209static 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
274static int valid_kprobe_addr(int template, int slot, unsigned long addr) 281static 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 */
326int trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) 334int __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
384void arch_prepare_kretprobe(struct kretprobe *rp, struct pt_regs *regs) 392void __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
402int arch_prepare_kprobe(struct kprobe *p) 411int __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
433void arch_arm_kprobe(struct kprobe *p) 442void __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
442void arch_disarm_kprobe(struct kprobe *p) 451void __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
452void arch_remove_kprobe(struct kprobe *p) 461void __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 */
464static void resume_execution(struct kprobe *p, struct pt_regs *regs) 473static 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
531static void prepare_ss(struct kprobe *p, struct pt_regs *regs) 540static 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
548static int pre_kprobes_handler(struct die_args *args) 557static 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
619static int post_kprobes_handler(struct pt_regs *regs) 628static 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
644static int kprobes_fault_handler(struct pt_regs *regs, int trapnr) 653static 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
662int kprobe_exceptions_notify(struct notifier_block *self, unsigned long val, 671int __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
684int setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) 693int __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
706int longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) 715int __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
124void 125void
125ia64_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
447void 448void __kprobes
448ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa, 449ia64_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"
23GLOBAL_ENTRY(flush_icache_range) 24GLOBAL_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
79void 80void __kprobes
80ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *regs) 81ia64_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;