* [1/6 PATCH] Kprobes : Prevent possible race conditions generic changes
@ 2005-07-07 10:10 Prasanna S Panchamukhi
2005-07-07 10:11 ` [2/6 PATCH] Kprobes : Prevent possible race conditions i386 changes Prasanna S Panchamukhi
2005-07-07 10:25 ` [1/6 PATCH] Kprobes : Prevent possible race conditions generic changes Andrew Morton
0 siblings, 2 replies; 19+ messages in thread
From: Prasanna S Panchamukhi @ 2005-07-07 10:10 UTC (permalink / raw)
To: akpm, Andi Kleen, David S. Miller, systemtap; +Cc: linux-kernel
Hi,
Please provide your feedback on this kprobes patch set.
Thanks
Prasanna
There are possible race conditions if probes are placed on routines within the
kprobes files and routines used by the kprobes. For example if you put probe on
get_kprobe() routines, the system can hang while inserting probes on
any routine such as do_fork(). Because while inserting probes on do_fork(),
register_kprobes() routine grabs the kprobes spin lock and executes get_kprobe()
routine and to handle probe of get_kprobe(), kprobes_handler() gets executed
and tries to grab kprobes spin lock, and spins forever. This patch avoids such
possible race conditions by preventing probes on routines within the kprobes
file and routines used by kprobes.
I have modified the patches as per Andi Kleen's suggestion to move kprobes
routines and other routines used by kprobes to a seperate section .kprobes.text.
Also moved page fault and exception handlers to .kprobes.text section.
These patches have been tested on i386, x86_64 and ppc64 architectures,
also compiled on ia64 and sparc64 architectures.
Signed-off-by: Prasanna S Panchamukhi <prasanna@in.ibm.com>
---
linux-2.6.13-rc1-mm1-prasanna/include/asm-generic/vmlinux.lds.h | 5
linux-2.6.13-rc1-mm1-prasanna/include/linux/kprobes.h | 4
linux-2.6.13-rc1-mm1-prasanna/kernel/kprobes.c | 69 ++++++----
3 files changed, 51 insertions(+), 27 deletions(-)
diff -puN kernel/kprobes.c~kprobes-exclude-functions-generic kernel/kprobes.c
--- linux-2.6.13-rc1-mm1/kernel/kprobes.c~kprobes-exclude-functions-generic 2005-07-06 18:51:16.000000000 +0530
+++ linux-2.6.13-rc1-mm1-prasanna/kernel/kprobes.c 2005-07-06 18:51:45.000000000 +0530
@@ -72,7 +72,7 @@ static struct hlist_head kprobe_insn_pag
* get_insn_slot() - Find a slot on an executable page for an instruction.
* We allocate an executable page if there's no room on existing ones.
*/
-kprobe_opcode_t *get_insn_slot(void)
+kprobe_opcode_t * __kprobes get_insn_slot(void)
{
struct kprobe_insn_page *kip;
struct hlist_node *pos;
@@ -117,7 +117,7 @@ kprobe_opcode_t *get_insn_slot(void)
return kip->insns;
}
-void free_insn_slot(kprobe_opcode_t *slot)
+void __kprobes free_insn_slot(kprobe_opcode_t *slot)
{
struct kprobe_insn_page *kip;
struct hlist_node *pos;
@@ -152,20 +152,20 @@ void free_insn_slot(kprobe_opcode_t *slo
}
/* Locks kprobe: irqs must be disabled */
-void lock_kprobes(void)
+void __kprobes lock_kprobes(void)
{
spin_lock(&kprobe_lock);
kprobe_cpu = smp_processor_id();
}
-void unlock_kprobes(void)
+void __kprobes unlock_kprobes(void)
{
kprobe_cpu = NR_CPUS;
spin_unlock(&kprobe_lock);
}
/* You have to be holding the kprobe_lock */
-struct kprobe *get_kprobe(void *addr)
+struct kprobe * __kprobes get_kprobe(void *addr)
{
struct hlist_head *head;
struct hlist_node *node;
@@ -183,7 +183,7 @@ struct kprobe *get_kprobe(void *addr)
* Aggregate handlers for multiple kprobes support - these handlers
* take care of invoking the individual kprobe handlers on p->list
*/
-static int aggr_pre_handler(struct kprobe *p, struct pt_regs *regs)
+static int __kprobes aggr_pre_handler(struct kprobe *p, struct pt_regs *regs)
{
struct kprobe *kp;
@@ -198,8 +198,8 @@ static int aggr_pre_handler(struct kprob
return 0;
}
-static void aggr_post_handler(struct kprobe *p, struct pt_regs *regs,
- unsigned long flags)
+static void __kprobes aggr_post_handler(struct kprobe *p, struct pt_regs *regs,
+ unsigned long flags)
{
struct kprobe *kp;
@@ -213,8 +213,8 @@ static void aggr_post_handler(struct kpr
return;
}
-static int aggr_fault_handler(struct kprobe *p, struct pt_regs *regs,
- int trapnr)
+static int __kprobes aggr_fault_handler(struct kprobe *p, struct pt_regs *regs,
+ int trapnr)
{
/*
* if we faulted "during" the execution of a user specified
@@ -227,7 +227,7 @@ static int aggr_fault_handler(struct kpr
return 0;
}
-static int aggr_break_handler(struct kprobe *p, struct pt_regs *regs)
+static int __kprobes aggr_break_handler(struct kprobe *p, struct pt_regs *regs)
{
struct kprobe *kp = curr_kprobe;
if (curr_kprobe && kp->break_handler) {
@@ -240,7 +240,7 @@ static int aggr_break_handler(struct kpr
return 0;
}
-struct kretprobe_instance *get_free_rp_inst(struct kretprobe *rp)
+struct kretprobe_instance * __kprobes get_free_rp_inst(struct kretprobe *rp)
{
struct hlist_node *node;
struct kretprobe_instance *ri;
@@ -249,7 +249,8 @@ struct kretprobe_instance *get_free_rp_i
return NULL;
}
-static struct kretprobe_instance *get_used_rp_inst(struct kretprobe *rp)
+static struct kretprobe_instance * __kprobes get_used_rp_inst(struct kretprobe
+ *rp)
{
struct hlist_node *node;
struct kretprobe_instance *ri;
@@ -258,7 +259,7 @@ static struct kretprobe_instance *get_us
return NULL;
}
-void add_rp_inst(struct kretprobe_instance *ri)
+void __kprobes add_rp_inst(struct kretprobe_instance *ri)
{
/*
* Remove rp inst off the free list -
@@ -276,7 +277,7 @@ void add_rp_inst(struct kretprobe_instan
hlist_add_head(&ri->uflist, &ri->rp->used_instances);
}
-void recycle_rp_inst(struct kretprobe_instance *ri)
+void __kprobes recycle_rp_inst(struct kretprobe_instance *ri)
{
/* remove rp inst off the rprobe_inst_table */
hlist_del(&ri->hlist);
@@ -291,7 +292,7 @@ void recycle_rp_inst(struct kretprobe_in
kfree(ri);
}
-struct hlist_head * kretprobe_inst_table_head(struct task_struct *tsk)
+struct hlist_head * __kprobes kretprobe_inst_table_head(struct task_struct *tsk)
{
return &kretprobe_inst_table[hash_ptr(tsk, KPROBE_HASH_BITS)];
}
@@ -302,7 +303,7 @@ struct hlist_head * kretprobe_inst_table
* instances associated with this task. These left over instances represent
* probed functions that have been called but will never return.
*/
-void kprobe_flush_task(struct task_struct *tk)
+void __kprobes kprobe_flush_task(struct task_struct *tk)
{
struct kretprobe_instance *ri;
struct hlist_head *head;
@@ -322,7 +323,8 @@ void kprobe_flush_task(struct task_struc
* This kprobe pre_handler is registered with every kretprobe. When probe
* hits it will set up the return probe.
*/
-static int pre_handler_kretprobe(struct kprobe *p, struct pt_regs *regs)
+static int __kprobes pre_handler_kretprobe(struct kprobe *p,
+ struct pt_regs *regs)
{
struct kretprobe *rp = container_of(p, struct kretprobe, kp);
@@ -353,7 +355,7 @@ static inline void copy_kprobe(struct kp
* Add the new probe to old_p->list. Fail if this is the
* second jprobe at the address - two jprobes can't coexist
*/
-static int add_new_kprobe(struct kprobe *old_p, struct kprobe *p)
+static int __kprobes add_new_kprobe(struct kprobe *old_p, struct kprobe *p)
{
struct kprobe *kp;
@@ -395,7 +397,8 @@ static inline void add_aggr_kprobe(struc
* the intricacies
* TODO: Move kcalloc outside the spinlock
*/
-static int register_aggr_kprobe(struct kprobe *old_p, struct kprobe *p)
+static int __kprobes register_aggr_kprobe(struct kprobe *old_p,
+ struct kprobe *p)
{
int ret = 0;
struct kprobe *ap;
@@ -434,12 +437,24 @@ static inline void cleanup_aggr_kprobe(s
spin_unlock_irqrestore(&kprobe_lock, flags);
}
-int register_kprobe(struct kprobe *p)
+static int __kprobes in_kprobes_functions(unsigned long addr)
+{
+ /* Linker adds these: start and end of __kprobes functions */
+ extern char __kprobes_text_start[], __kprobes_text_end[];
+ if (addr >= (unsigned long)__kprobes_text_start
+ && addr < (unsigned long)__kprobes_text_end)
+ return -EINVAL;
+ return 0;
+}
+
+int __kprobes register_kprobe(struct kprobe *p)
{
int ret = 0;
unsigned long flags = 0;
struct kprobe *old_p;
+ if ((ret = in_kprobes_functions((unsigned long) p->addr)) !=0)
+ return ret;
if ((ret = arch_prepare_kprobe(p)) != 0) {
goto rm_kprobe;
}
@@ -466,7 +481,7 @@ rm_kprobe:
return ret;
}
-void unregister_kprobe(struct kprobe *p)
+void __kprobes unregister_kprobe(struct kprobe *p)
{
unsigned long flags;
struct kprobe *old_p;
@@ -487,7 +502,7 @@ static struct notifier_block kprobe_exce
.priority = 0x7fffffff /* we need to notified first */
};
-int register_jprobe(struct jprobe *jp)
+int __kprobes register_jprobe(struct jprobe *jp)
{
/* Todo: Verify probepoint is a function entry point */
jp->kp.pre_handler = setjmp_pre_handler;
@@ -496,14 +511,14 @@ int register_jprobe(struct jprobe *jp)
return register_kprobe(&jp->kp);
}
-void unregister_jprobe(struct jprobe *jp)
+void __kprobes unregister_jprobe(struct jprobe *jp)
{
unregister_kprobe(&jp->kp);
}
#ifdef ARCH_SUPPORTS_KRETPROBES
-int register_kretprobe(struct kretprobe *rp)
+int __kprobes register_kretprobe(struct kretprobe *rp)
{
int ret = 0;
struct kretprobe_instance *inst;
@@ -540,14 +555,14 @@ int register_kretprobe(struct kretprobe
#else /* ARCH_SUPPORTS_KRETPROBES */
-int register_kretprobe(struct kretprobe *rp)
+int __kprobes register_kretprobe(struct kretprobe *rp)
{
return -ENOSYS;
}
#endif /* ARCH_SUPPORTS_KRETPROBES */
-void unregister_kretprobe(struct kretprobe *rp)
+void __kprobes unregister_kretprobe(struct kretprobe *rp)
{
unsigned long flags;
struct kretprobe_instance *ri;
diff -puN include/linux/kprobes.h~kprobes-exclude-functions-generic include/linux/kprobes.h
--- linux-2.6.13-rc1-mm1/include/linux/kprobes.h~kprobes-exclude-functions-generic 2005-07-06 18:51:16.000000000 +0530
+++ linux-2.6.13-rc1-mm1-prasanna/include/linux/kprobes.h 2005-07-06 18:51:16.000000000 +0530
@@ -42,6 +42,10 @@
#define KPROBE_REENTER 0x00000004
#define KPROBE_HIT_SSDONE 0x00000008
+/* Attach to insert probes on any functions which should be ignored*/
+#define __kprobes __attribute__((__section__(".kprobes.text")))
+/* Is this address in the __kprobes functions? */
+
struct kprobe;
struct pt_regs;
struct kretprobe;
diff -puN include/asm-generic/vmlinux.lds.h~kprobes-exclude-functions-generic include/asm-generic/vmlinux.lds.h
--- linux-2.6.13-rc1-mm1/include/asm-generic/vmlinux.lds.h~kprobes-exclude-functions-generic 2005-07-06 18:51:16.000000000 +0530
+++ linux-2.6.13-rc1-mm1-prasanna/include/asm-generic/vmlinux.lds.h 2005-07-06 18:51:16.000000000 +0530
@@ -95,3 +95,8 @@
VMLINUX_SYMBOL(__lock_text_start) = .; \
*(.spinlock.text) \
VMLINUX_SYMBOL(__lock_text_end) = .;
+
+#define KPROBES_TEXT \
+ VMLINUX_SYMBOL(__kprobes_text_start) = .; \
+ *(.kprobes.text) \
+ VMLINUX_SYMBOL(__kprobes_text_end) = .;
_
--
Prasanna S Panchamukhi
Linux Technology Center
India Software Labs, IBM Bangalore
Ph: 91-80-25044636
<prasanna@in.ibm.com>
^ permalink raw reply [flat|nested] 19+ messages in thread* Re: [2/6 PATCH] Kprobes : Prevent possible race conditions i386 changes 2005-07-07 10:10 [1/6 PATCH] Kprobes : Prevent possible race conditions generic changes Prasanna S Panchamukhi @ 2005-07-07 10:11 ` Prasanna S Panchamukhi 2005-07-07 10:14 ` [3/6 PATCH] Kprobes : Prevent possible race conditions x86_64 changes Prasanna S Panchamukhi 2005-07-07 13:19 ` [2/6 PATCH] Kprobes : Prevent possible race conditions i386 changes Andi Kleen 2005-07-07 10:25 ` [1/6 PATCH] Kprobes : Prevent possible race conditions generic changes Andrew Morton 1 sibling, 2 replies; 19+ messages in thread From: Prasanna S Panchamukhi @ 2005-07-07 10:11 UTC (permalink / raw) To: akpm, Andi Kleen, David S. Miller, systemtap; +Cc: linux-kernel This patch contains the i386 architecture specific changes to prevent the possible race conditions. Signed-off-by: Prasanna S Panchamukhi <prasanna@in.ibm.com> --- linux-2.6.13-rc1-mm1-prasanna/arch/i386/kernel/kprobes.c | 29 +++++------ linux-2.6.13-rc1-mm1-prasanna/arch/i386/kernel/traps.c | 12 ++-- linux-2.6.13-rc1-mm1-prasanna/arch/i386/kernel/vmlinux.lds.S | 1 linux-2.6.13-rc1-mm1-prasanna/arch/i386/mm/fault.c | 4 + 4 files changed, 26 insertions(+), 20 deletions(-) diff -puN arch/i386/kernel/kprobes.c~kprobes-exclude-functions-i386 arch/i386/kernel/kprobes.c --- linux-2.6.13-rc1-mm1/arch/i386/kernel/kprobes.c~kprobes-exclude-functions-i386 2005-07-06 17:31:04.000000000 +0530 +++ linux-2.6.13-rc1-mm1-prasanna/arch/i386/kernel/kprobes.c 2005-07-06 17:43:59.000000000 +0530 @@ -62,32 +62,32 @@ static inline int is_IF_modifier(kprobe_ return 0; } -int arch_prepare_kprobe(struct kprobe *p) +int __kprobes arch_prepare_kprobe(struct kprobe *p) { return 0; } -void arch_copy_kprobe(struct kprobe *p) +void __kprobes arch_copy_kprobe(struct kprobe *p) { memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t)); p->opcode = *p->addr; } -void arch_arm_kprobe(struct kprobe *p) +void __kprobes arch_arm_kprobe(struct kprobe *p) { *p->addr = BREAKPOINT_INSTRUCTION; flush_icache_range((unsigned long) p->addr, (unsigned long) p->addr + sizeof(kprobe_opcode_t)); } -void arch_disarm_kprobe(struct kprobe *p) +void __kprobes arch_disarm_kprobe(struct kprobe *p) { *p->addr = p->opcode; flush_icache_range((unsigned long) p->addr, (unsigned long) p->addr + sizeof(kprobe_opcode_t)); } -void arch_remove_kprobe(struct kprobe *p) +void __kprobes arch_remove_kprobe(struct kprobe *p) { } @@ -127,7 +127,8 @@ static inline void prepare_singlestep(st regs->eip = (unsigned long)&p->ainsn.insn; } -void arch_prepare_kretprobe(struct kretprobe *rp, struct pt_regs *regs) +void __kprobes arch_prepare_kretprobe(struct kretprobe *rp, + struct pt_regs *regs) { unsigned long *sara = (unsigned long *)®s->esp; struct kretprobe_instance *ri; @@ -150,7 +151,7 @@ void arch_prepare_kretprobe(struct kretp * Interrupts are disabled on entry as trap3 is an interrupt gate and they * remain disabled thorough out this function. */ -static int kprobe_handler(struct pt_regs *regs) +static int __kprobes kprobe_handler(struct pt_regs *regs) { struct kprobe *p; int ret = 0; @@ -259,7 +260,7 @@ no_kprobe: /* * Called when we hit the probe point at kretprobe_trampoline */ -int trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) +int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) { struct kretprobe_instance *ri = NULL; struct hlist_head *head; @@ -338,7 +339,7 @@ int trampoline_probe_handler(struct kpro * that is atop the stack is the address following the copied instruction. * We need to make it the address following the original instruction. */ -static void resume_execution(struct kprobe *p, struct pt_regs *regs) +static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs) { unsigned long *tos = (unsigned long *)®s->esp; unsigned long next_eip = 0; @@ -444,8 +445,8 @@ static inline int kprobe_fault_handler(s /* * Wrapper routine to for handling exceptions. */ -int kprobe_exceptions_notify(struct notifier_block *self, unsigned long val, - void *data) +int __kprobes kprobe_exceptions_notify(struct notifier_block *self, + unsigned long val, void *data) { struct die_args *args = (struct die_args *)data; switch (val) { @@ -473,7 +474,7 @@ int kprobe_exceptions_notify(struct noti return NOTIFY_DONE; } -int setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) +int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) { struct jprobe *jp = container_of(p, struct jprobe, kp); unsigned long addr; @@ -495,7 +496,7 @@ int setjmp_pre_handler(struct kprobe *p, return 1; } -void jprobe_return(void) +void __kprobes jprobe_return(void) { preempt_enable_no_resched(); asm volatile (" xchgl %%ebx,%%esp \n" @@ -506,7 +507,7 @@ void jprobe_return(void) (jprobe_saved_esp):"memory"); } -int longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) +int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) { u8 *addr = (u8 *) (regs->eip - 1); unsigned long stack_addr = (unsigned long)jprobe_saved_esp; diff -puN arch/i386/kernel/traps.c~kprobes-exclude-functions-i386 arch/i386/kernel/traps.c --- linux-2.6.13-rc1-mm1/arch/i386/kernel/traps.c~kprobes-exclude-functions-i386 2005-07-06 17:31:04.000000000 +0530 +++ linux-2.6.13-rc1-mm1-prasanna/arch/i386/kernel/traps.c 2005-07-06 17:31:04.000000000 +0530 @@ -408,8 +408,9 @@ static inline void die_if_kernel(const c die(str, regs, err); } -static void do_trap(int trapnr, int signr, char *str, int vm86, - struct pt_regs * regs, long error_code, siginfo_t *info) +static void __kprobes do_trap(int trapnr, int signr, char *str, int vm86, + struct pt_regs * regs, long error_code, + siginfo_t *info) { struct task_struct *tsk = current; tsk->thread.error_code = error_code; @@ -507,7 +508,8 @@ DO_ERROR(12, SIGBUS, "stack segment", s DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, 0) DO_ERROR_INFO(32, SIGSEGV, "iret exception", iret_error, ILL_BADSTK, 0) -fastcall void do_general_protection(struct pt_regs * regs, long error_code) +fastcall void __kprobes do_general_protection(struct pt_regs * regs, + long error_code) { int cpu = get_cpu(); struct tss_struct *tss = &per_cpu(init_tss, cpu); @@ -737,7 +739,7 @@ void unset_nmi_callback(void) EXPORT_SYMBOL_GPL(unset_nmi_callback); #ifdef CONFIG_KPROBES -fastcall void do_int3(struct pt_regs *regs, long error_code) +fastcall void __kprobes do_int3(struct pt_regs *regs, long error_code) { if (notify_die(DIE_INT3, "int3", regs, error_code, 3, SIGTRAP) == NOTIFY_STOP) @@ -771,7 +773,7 @@ fastcall void do_int3(struct pt_regs *re * find every occurrence of the TF bit that could be saved away even * by user code) */ -fastcall void do_debug(struct pt_regs * regs, long error_code) +fastcall void __kprobes do_debug(struct pt_regs * regs, long error_code) { unsigned int condition; struct task_struct *tsk = current; diff -puN arch/i386/kernel/vmlinux.lds.S~kprobes-exclude-functions-i386 arch/i386/kernel/vmlinux.lds.S --- linux-2.6.13-rc1-mm1/arch/i386/kernel/vmlinux.lds.S~kprobes-exclude-functions-i386 2005-07-06 17:31:04.000000000 +0530 +++ linux-2.6.13-rc1-mm1-prasanna/arch/i386/kernel/vmlinux.lds.S 2005-07-06 17:31:04.000000000 +0530 @@ -22,6 +22,7 @@ SECTIONS *(.text) SCHED_TEXT LOCK_TEXT + KPROBES_TEXT *(.fixup) *(.gnu.warning) } = 0x9090 diff -puN arch/i386/mm/fault.c~kprobes-exclude-functions-i386 arch/i386/mm/fault.c --- linux-2.6.13-rc1-mm1/arch/i386/mm/fault.c~kprobes-exclude-functions-i386 2005-07-06 17:31:04.000000000 +0530 +++ linux-2.6.13-rc1-mm1-prasanna/arch/i386/mm/fault.c 2005-07-06 17:31:04.000000000 +0530 @@ -21,6 +21,7 @@ #include <linux/vt_kern.h> /* For unblank_screen() */ #include <linux/highmem.h> #include <linux/module.h> +#include <linux/kprobes.h> #include <asm/system.h> #include <asm/uaccess.h> @@ -211,7 +212,8 @@ fastcall void do_invalid_op(struct pt_re * bit 1 == 0 means read, 1 means write * bit 2 == 0 means kernel, 1 means user-mode */ -fastcall void do_page_fault(struct pt_regs *regs, unsigned long error_code) +fastcall void __kprobes do_page_fault(struct pt_regs *regs, + unsigned long error_code) { struct task_struct *tsk; struct mm_struct *mm; _ -- Prasanna S Panchamukhi Linux Technology Center India Software Labs, IBM Bangalore Ph: 91-80-25044636 <prasanna@in.ibm.com> ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [3/6 PATCH] Kprobes : Prevent possible race conditions x86_64 changes 2005-07-07 10:11 ` [2/6 PATCH] Kprobes : Prevent possible race conditions i386 changes Prasanna S Panchamukhi @ 2005-07-07 10:14 ` Prasanna S Panchamukhi 2005-07-07 10:16 ` [4/6 PATCH] Kprobes : Prevent possible race conditions ppc64 changes Prasanna S Panchamukhi 2005-07-08 11:07 ` [3/6 PATCH] Kprobes : Prevent possible race conditions x86_64 changes Prasanna S Panchamukhi 2005-07-07 13:19 ` [2/6 PATCH] Kprobes : Prevent possible race conditions i386 changes Andi Kleen 1 sibling, 2 replies; 19+ messages in thread From: Prasanna S Panchamukhi @ 2005-07-07 10:14 UTC (permalink / raw) To: akpm, Andi Kleen, David S. Miller, systemtap; +Cc: linux-kernel This patch contains the x86_64 architecture specific changes to prevent the possible race conditions. Signed-off-by: Prasanna S Panchamukhi <prasanna@in.ibm.com> --- linux-2.6.13-rc1-mm1-prasanna/arch/x86_64/kernel/kprobes.c | 35 +++++----- linux-2.6.13-rc1-mm1-prasanna/arch/x86_64/kernel/traps.c | 14 ++-- linux-2.6.13-rc1-mm1-prasanna/arch/x86_64/kernel/vmlinux.lds.S | 1 linux-2.6.13-rc1-mm1-prasanna/arch/x86_64/mm/fault.c | 3 4 files changed, 30 insertions(+), 23 deletions(-) diff -puN arch/x86_64/kernel/kprobes.c~kprobes-exclude-functions-x86_64 arch/x86_64/kernel/kprobes.c --- linux-2.6.13-rc1-mm1/arch/x86_64/kernel/kprobes.c~kprobes-exclude-functions-x86_64 2005-07-06 17:45:18.000000000 +0530 +++ linux-2.6.13-rc1-mm1-prasanna/arch/x86_64/kernel/kprobes.c 2005-07-06 17:45:43.000000000 +0530 @@ -74,7 +74,7 @@ static inline int is_IF_modifier(kprobe_ return 0; } -int arch_prepare_kprobe(struct kprobe *p) +int __kprobes arch_prepare_kprobe(struct kprobe *p) { /* insn: must be on special executable page on x86_64. */ up(&kprobe_mutex); @@ -189,7 +189,7 @@ static inline s32 *is_riprel(u8 *insn) return NULL; } -void arch_copy_kprobe(struct kprobe *p) +void __kprobes arch_copy_kprobe(struct kprobe *p) { s32 *ripdisp; memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE); @@ -215,21 +215,21 @@ void arch_copy_kprobe(struct kprobe *p) p->opcode = *p->addr; } -void arch_arm_kprobe(struct kprobe *p) +void __kprobes arch_arm_kprobe(struct kprobe *p) { *p->addr = BREAKPOINT_INSTRUCTION; flush_icache_range((unsigned long) p->addr, (unsigned long) p->addr + sizeof(kprobe_opcode_t)); } -void arch_disarm_kprobe(struct kprobe *p) +void __kprobes arch_disarm_kprobe(struct kprobe *p) { *p->addr = p->opcode; flush_icache_range((unsigned long) p->addr, (unsigned long) p->addr + sizeof(kprobe_opcode_t)); } -void arch_remove_kprobe(struct kprobe *p) +void __kprobes arch_remove_kprobe(struct kprobe *p) { up(&kprobe_mutex); free_insn_slot(p->ainsn.insn); @@ -261,7 +261,7 @@ static inline void set_current_kprobe(st kprobe_saved_rflags &= ~IF_MASK; } -static void prepare_singlestep(struct kprobe *p, struct pt_regs *regs) +static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs) { regs->eflags |= TF_MASK; regs->eflags &= ~IF_MASK; @@ -272,7 +272,8 @@ static void prepare_singlestep(struct kp regs->rip = (unsigned long)p->ainsn.insn; } -void arch_prepare_kretprobe(struct kretprobe *rp, struct pt_regs *regs) +void __kprobes arch_prepare_kretprobe(struct kretprobe *rp, + struct pt_regs *regs) { unsigned long *sara = (unsigned long *)regs->rsp; struct kretprobe_instance *ri; @@ -295,7 +296,7 @@ void arch_prepare_kretprobe(struct kretp * Interrupts are disabled on entry as trap3 is an interrupt gate and they * remain disabled thorough out this function. */ -int kprobe_handler(struct pt_regs *regs) +int __kprobes kprobe_handler(struct pt_regs *regs) { struct kprobe *p; int ret = 0; @@ -399,7 +400,7 @@ no_kprobe: /* * Called when we hit the probe point at kretprobe_trampoline */ -int trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) +int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) { struct kretprobe_instance *ri = NULL; struct hlist_head *head; @@ -478,7 +479,7 @@ int trampoline_probe_handler(struct kpro * that is atop the stack is the address following the copied instruction. * We need to make it the address following the original instruction. */ -static void resume_execution(struct kprobe *p, struct pt_regs *regs) +static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs) { unsigned long *tos = (unsigned long *)regs->rsp; unsigned long next_rip = 0; @@ -536,7 +537,7 @@ static void resume_execution(struct kpro * Interrupts are disabled on entry as trap1 is an interrupt gate and they * remain disabled thoroughout this function. And we hold kprobe lock. */ -int post_kprobe_handler(struct pt_regs *regs) +int __kprobes post_kprobe_handler(struct pt_regs *regs) { if (!kprobe_running()) return 0; @@ -571,7 +572,7 @@ out: } /* Interrupts disabled, kprobe_lock held. */ -int kprobe_fault_handler(struct pt_regs *regs, int trapnr) +int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr) { if (current_kprobe->fault_handler && current_kprobe->fault_handler(current_kprobe, regs, trapnr)) @@ -590,8 +591,8 @@ int kprobe_fault_handler(struct pt_regs /* * Wrapper routine for handling exceptions. */ -int kprobe_exceptions_notify(struct notifier_block *self, unsigned long val, - void *data) +int __kprobes kprobe_exceptions_notify(struct notifier_block *self, + unsigned long val, void *data) { struct die_args *args = (struct die_args *)data; switch (val) { @@ -619,7 +620,7 @@ int kprobe_exceptions_notify(struct noti return NOTIFY_DONE; } -int setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) +int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) { struct jprobe *jp = container_of(p, struct jprobe, kp); unsigned long addr; @@ -640,7 +641,7 @@ int setjmp_pre_handler(struct kprobe *p, return 1; } -void jprobe_return(void) +void __kprobes jprobe_return(void) { preempt_enable_no_resched(); asm volatile (" xchg %%rbx,%%rsp \n" @@ -651,7 +652,7 @@ void jprobe_return(void) (jprobe_saved_rsp):"memory"); } -int longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) +int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) { u8 *addr = (u8 *) (regs->rip - 1); unsigned long stack_addr = (unsigned long)jprobe_saved_rsp; diff -puN arch/x86_64/kernel/traps.c~kprobes-exclude-functions-x86_64 arch/x86_64/kernel/traps.c --- linux-2.6.13-rc1-mm1/arch/x86_64/kernel/traps.c~kprobes-exclude-functions-x86_64 2005-07-06 17:45:18.000000000 +0530 +++ linux-2.6.13-rc1-mm1-prasanna/arch/x86_64/kernel/traps.c 2005-07-06 17:45:18.000000000 +0530 @@ -29,6 +29,7 @@ #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/nmi.h> +#include <linux/kprobes.h> #include <asm/system.h> #include <asm/uaccess.h> @@ -422,8 +423,9 @@ void die_nmi(char *str, struct pt_regs * do_exit(SIGSEGV); } -static void do_trap(int trapnr, int signr, char *str, - struct pt_regs * regs, long error_code, siginfo_t *info) +static void __kprobes do_trap(int trapnr, int signr, char *str, + struct pt_regs * regs, long error_code, + siginfo_t *info) { conditional_sti(regs); @@ -507,7 +509,8 @@ DO_ERROR(18, SIGSEGV, "reserved", reserv DO_ERROR(12, SIGBUS, "stack segment", stack_segment) DO_ERROR( 8, SIGSEGV, "double fault", double_fault) -asmlinkage void do_general_protection(struct pt_regs * regs, long error_code) +asmlinkage void __kprobes do_general_protection(struct pt_regs * regs, + long error_code) { conditional_sti(regs); @@ -628,7 +631,7 @@ asmlinkage void default_do_nmi(struct pt io_check_error(reason, regs); } -asmlinkage void do_int3(struct pt_regs * regs, long error_code) +asmlinkage void __kprobes do_int3(struct pt_regs * regs, long error_code) { if (notify_die(DIE_INT3, "int3", regs, error_code, 3, SIGTRAP) == NOTIFY_STOP) { return; @@ -659,7 +662,8 @@ asmlinkage struct pt_regs *sync_regs(str } /* runs on IST stack. */ -asmlinkage void do_debug(struct pt_regs * regs, unsigned long error_code) +asmlinkage void __kprobes do_debug(struct pt_regs * regs, + unsigned long error_code) { unsigned long condition; struct task_struct *tsk = current; diff -puN arch/x86_64/kernel/vmlinux.lds.S~kprobes-exclude-functions-x86_64 arch/x86_64/kernel/vmlinux.lds.S --- linux-2.6.13-rc1-mm1/arch/x86_64/kernel/vmlinux.lds.S~kprobes-exclude-functions-x86_64 2005-07-06 17:45:18.000000000 +0530 +++ linux-2.6.13-rc1-mm1-prasanna/arch/x86_64/kernel/vmlinux.lds.S 2005-07-06 17:45:18.000000000 +0530 @@ -21,6 +21,7 @@ SECTIONS *(.text) SCHED_TEXT LOCK_TEXT + KPROBES_TEXT *(.fixup) *(.gnu.warning) } = 0x9090 diff -puN arch/x86_64/mm/fault.c~kprobes-exclude-functions-x86_64 arch/x86_64/mm/fault.c --- linux-2.6.13-rc1-mm1/arch/x86_64/mm/fault.c~kprobes-exclude-functions-x86_64 2005-07-06 17:45:18.000000000 +0530 +++ linux-2.6.13-rc1-mm1-prasanna/arch/x86_64/mm/fault.c 2005-07-06 17:45:18.000000000 +0530 @@ -297,7 +297,8 @@ int exception_trace = 1; * bit 2 == 0 means kernel, 1 means user-mode * bit 3 == 1 means fault was an instruction fetch */ -asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code) +asmlinkage void __kprobes do_page_fault(struct pt_regs *regs, + unsigned long error_code) { struct task_struct *tsk; struct mm_struct *mm; _ -- Prasanna S Panchamukhi Linux Technology Center India Software Labs, IBM Bangalore Ph: 91-80-25044636 <prasanna@in.ibm.com> ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [4/6 PATCH] Kprobes : Prevent possible race conditions ppc64 changes 2005-07-07 10:14 ` [3/6 PATCH] Kprobes : Prevent possible race conditions x86_64 changes Prasanna S Panchamukhi @ 2005-07-07 10:16 ` Prasanna S Panchamukhi 2005-07-07 10:18 ` [5/6 PATCH] Kprobes : Prevent possible race conditions ia64 changes Prasanna S Panchamukhi 2005-07-08 14:13 ` [4/6 PATCH] Kprobes : Prevent possible race conditions ppc64 changes Ananth N Mavinakayanahalli 2005-07-08 11:07 ` [3/6 PATCH] Kprobes : Prevent possible race conditions x86_64 changes Prasanna S Panchamukhi 1 sibling, 2 replies; 19+ messages in thread From: Prasanna S Panchamukhi @ 2005-07-07 10:16 UTC (permalink / raw) To: akpm, Andi Kleen, David S. Miller, systemtap; +Cc: linux-kernel This patch contains the ppc64 architecture specific changes to prevent the possible race conditions. Signed-off-by: Prasanna S Panchamukhi <prasanna@in.ibm.com> --- linux-2.6.13-rc1-mm1-prasanna/arch/ppc64/kernel/kprobes.c | 29 +++++----- linux-2.6.13-rc1-mm1-prasanna/arch/ppc64/kernel/misc.S | 4 - linux-2.6.13-rc1-mm1-prasanna/arch/ppc64/kernel/traps.c | 5 + linux-2.6.13-rc1-mm1-prasanna/arch/ppc64/kernel/vmlinux.lds.S | 1 linux-2.6.13-rc1-mm1-prasanna/arch/ppc64/mm/fault.c | 5 + linux-2.6.13-rc1-mm1-prasanna/include/asm-ppc64/processor.h | 14 ++++ 6 files changed, 38 insertions(+), 20 deletions(-) diff -puN arch/ppc64/kernel/kprobes.c~kprobes-exclude-functions-ppc64 arch/ppc64/kernel/kprobes.c --- linux-2.6.13-rc1-mm1/arch/ppc64/kernel/kprobes.c~kprobes-exclude-functions-ppc64 2005-07-06 20:07:22.000000000 +0530 +++ linux-2.6.13-rc1-mm1-prasanna/arch/ppc64/kernel/kprobes.c 2005-07-06 20:07:22.000000000 +0530 @@ -44,7 +44,7 @@ static struct kprobe *kprobe_prev; static unsigned long kprobe_status_prev, kprobe_saved_msr_prev; static struct pt_regs jprobe_saved_regs; -int arch_prepare_kprobe(struct kprobe *p) +int __kprobes arch_prepare_kprobe(struct kprobe *p) { int ret = 0; kprobe_opcode_t insn = *p->addr; @@ -68,27 +68,27 @@ int arch_prepare_kprobe(struct kprobe *p return ret; } -void arch_copy_kprobe(struct kprobe *p) +void __kprobes arch_copy_kprobe(struct kprobe *p) { memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t)); p->opcode = *p->addr; } -void arch_arm_kprobe(struct kprobe *p) +void __kprobes arch_arm_kprobe(struct kprobe *p) { *p->addr = BREAKPOINT_INSTRUCTION; flush_icache_range((unsigned long) p->addr, (unsigned long) p->addr + sizeof(kprobe_opcode_t)); } -void arch_disarm_kprobe(struct kprobe *p) +void __kprobes arch_disarm_kprobe(struct kprobe *p) { *p->addr = p->opcode; flush_icache_range((unsigned long) p->addr, (unsigned long) p->addr + sizeof(kprobe_opcode_t)); } -void arch_remove_kprobe(struct kprobe *p) +void __kprobes arch_remove_kprobe(struct kprobe *p) { up(&kprobe_mutex); free_insn_slot(p->ainsn.insn); @@ -122,7 +122,8 @@ static inline void restore_previous_kpro kprobe_saved_msr = kprobe_saved_msr_prev; } -void arch_prepare_kretprobe(struct kretprobe *rp, struct pt_regs *regs) +void __kprobes arch_prepare_kretprobe(struct kretprobe *rp, + struct pt_regs *regs) { struct kretprobe_instance *ri; @@ -244,7 +245,7 @@ void kretprobe_trampoline_holder(void) /* * Called when the probe at kretprobe trampoline is hit */ -int trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) +int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) { struct kretprobe_instance *ri = NULL; struct hlist_head *head; @@ -308,7 +309,7 @@ int trampoline_probe_handler(struct kpro * single-stepped a copy of the instruction. The address of this * copy is p->ainsn.insn. */ -static void resume_execution(struct kprobe *p, struct pt_regs *regs) +static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs) { int ret; unsigned int insn = *p->ainsn.insn; @@ -373,8 +374,8 @@ static inline int kprobe_fault_handler(s /* * Wrapper routine to for handling exceptions. */ -int kprobe_exceptions_notify(struct notifier_block *self, unsigned long val, - void *data) +int __kprobes kprobe_exceptions_notify(struct notifier_block *self, + unsigned long val, void *data) { struct die_args *args = (struct die_args *)data; int ret = NOTIFY_DONE; @@ -406,7 +407,7 @@ int kprobe_exceptions_notify(struct noti return ret; } -int setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) +int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) { struct jprobe *jp = container_of(p, struct jprobe, kp); @@ -419,16 +420,16 @@ int setjmp_pre_handler(struct kprobe *p, return 1; } -void jprobe_return(void) +void __kprobes jprobe_return(void) { asm volatile("trap" ::: "memory"); } -void jprobe_return_end(void) +void __kprobes jprobe_return_end(void) { }; -int longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) +int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) { /* * FIXME - we should ideally be validating that we got here 'cos diff -puN arch/ppc64/kernel/traps.c~kprobes-exclude-functions-ppc64 arch/ppc64/kernel/traps.c --- linux-2.6.13-rc1-mm1/arch/ppc64/kernel/traps.c~kprobes-exclude-functions-ppc64 2005-07-06 20:07:22.000000000 +0530 +++ linux-2.6.13-rc1-mm1-prasanna/arch/ppc64/kernel/traps.c 2005-07-06 20:07:22.000000000 +0530 @@ -30,6 +30,7 @@ #include <linux/init.h> #include <linux/module.h> #include <linux/delay.h> +#include <linux/kprobes.h> #include <asm/kdebug.h> #include <asm/pgtable.h> @@ -220,7 +221,7 @@ void instruction_breakpoint_exception(st _exception(SIGTRAP, regs, TRAP_BRKPT, regs->nip); } -void single_step_exception(struct pt_regs *regs) +void __kprobes single_step_exception(struct pt_regs *regs) { regs->msr &= ~MSR_SE; /* Turn off 'trace' bit */ @@ -398,7 +399,7 @@ check_bug_trap(struct pt_regs *regs) return 0; } -void program_check_exception(struct pt_regs *regs) +void __kprobes program_check_exception(struct pt_regs *regs) { if (debugger_fault_handler(regs)) return; diff -puN arch/ppc64/kernel/vmlinux.lds.S~kprobes-exclude-functions-ppc64 arch/ppc64/kernel/vmlinux.lds.S --- linux-2.6.13-rc1-mm1/arch/ppc64/kernel/vmlinux.lds.S~kprobes-exclude-functions-ppc64 2005-07-06 20:07:22.000000000 +0530 +++ linux-2.6.13-rc1-mm1-prasanna/arch/ppc64/kernel/vmlinux.lds.S 2005-07-06 20:07:22.000000000 +0530 @@ -15,6 +15,7 @@ SECTIONS *(.text .text.*) SCHED_TEXT LOCK_TEXT + KPROBES_TEXT *(.fixup) . = ALIGN(4096); _etext = .; diff -puN arch/ppc64/mm/fault.c~kprobes-exclude-functions-ppc64 arch/ppc64/mm/fault.c --- linux-2.6.13-rc1-mm1/arch/ppc64/mm/fault.c~kprobes-exclude-functions-ppc64 2005-07-06 20:07:22.000000000 +0530 +++ linux-2.6.13-rc1-mm1-prasanna/arch/ppc64/mm/fault.c 2005-07-06 20:07:22.000000000 +0530 @@ -29,6 +29,7 @@ #include <linux/interrupt.h> #include <linux/smp_lock.h> #include <linux/module.h> +#include <linux/kprobes.h> #include <asm/page.h> #include <asm/pgtable.h> @@ -84,8 +85,8 @@ static int store_updates_sp(struct pt_re * The return value is 0 if the fault was handled, or the signal * number if this is a kernel fault that can't be handled here. */ -int do_page_fault(struct pt_regs *regs, unsigned long address, - unsigned long error_code) +int __kprobes do_page_fault(struct pt_regs *regs, unsigned long address, + unsigned long error_code) { struct vm_area_struct * vma; struct mm_struct *mm = current->mm; diff -puN arch/ppc64/kernel/misc.S~kprobes-exclude-functions-ppc64 arch/ppc64/kernel/misc.S --- linux-2.6.13-rc1-mm1/arch/ppc64/kernel/misc.S~kprobes-exclude-functions-ppc64 2005-07-06 20:07:22.000000000 +0530 +++ linux-2.6.13-rc1-mm1-prasanna/arch/ppc64/kernel/misc.S 2005-07-07 10:24:00.000000000 +0530 @@ -183,7 +183,7 @@ PPC64_CACHES: * flush all bytes from start through stop-1 inclusive */ -_GLOBAL(__flush_icache_range) +_KPROBE(__flush_icache_range) /* * Flush the data cache to memory @@ -223,7 +223,7 @@ _GLOBAL(__flush_icache_range) bdnz 2b isync blr - + .previous .text /* * Like above, but only do the D-cache. * diff -puN include/asm-ppc64/processor.h~kprobes-exclude-functions-ppc64 include/asm-ppc64/processor.h --- linux-2.6.13-rc1-mm1/include/asm-ppc64/processor.h~kprobes-exclude-functions-ppc64 2005-07-06 20:07:22.000000000 +0530 +++ linux-2.6.13-rc1-mm1-prasanna/include/asm-ppc64/processor.h 2005-07-07 10:22:29.000000000 +0530 @@ -309,6 +309,20 @@ name: \ .type GLUE(.,name),@function; \ GLUE(.,name): +#define _KPROBE(name) \ + .section ".kprobes.text","a"; \ + .align 2 ; \ + .globl name; \ + .globl GLUE(.,name); \ + .section ".opd","aw"; \ +name: \ + .quad GLUE(.,name); \ + .quad .TOC.@tocbase; \ + .quad 0; \ + .previous; \ + .type GLUE(.,name),@function; \ +GLUE(.,name): + #define _STATIC(name) \ .section ".text"; \ .align 2 ; \ _ -- Prasanna S Panchamukhi Linux Technology Center India Software Labs, IBM Bangalore Ph: 91-80-25044636 <prasanna@in.ibm.com> ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [5/6 PATCH] Kprobes : Prevent possible race conditions ia64 changes 2005-07-07 10:16 ` [4/6 PATCH] Kprobes : Prevent possible race conditions ppc64 changes Prasanna S Panchamukhi @ 2005-07-07 10:18 ` Prasanna S Panchamukhi 2005-07-07 10:20 ` [6/6 PATCH] Kprobes : Prevent possible race conditions sparc64 changes Prasanna S Panchamukhi 2005-07-08 2:06 ` [5/6 PATCH] Kprobes : Prevent possible race conditions ia64 changes Keshavamurthy Anil S 2005-07-08 14:13 ` [4/6 PATCH] Kprobes : Prevent possible race conditions ppc64 changes Ananth N Mavinakayanahalli 1 sibling, 2 replies; 19+ messages in thread From: Prasanna S Panchamukhi @ 2005-07-07 10:18 UTC (permalink / raw) To: akpm, Andi Kleen, David S. Miller, systemtap; +Cc: linux-kernel This patch contains the ia64 architecture specific changes to prevent the possible race conditions. Signed-off-by: Prasanna S Panchamukhi <prasanna@in.ibm.com> --- linux-2.6.13-rc1-mm1-prasanna/arch/ia64/kernel/kprobes.c | 57 ++++++----- linux-2.6.13-rc1-mm1-prasanna/arch/ia64/kernel/traps.c | 5 linux-2.6.13-rc1-mm1-prasanna/arch/ia64/kernel/vmlinux.lds.S | 1 linux-2.6.13-rc1-mm1-prasanna/arch/ia64/lib/flush.S | 1 linux-2.6.13-rc1-mm1-prasanna/arch/ia64/mm/fault.c | 3 5 files changed, 40 insertions(+), 27 deletions(-) diff -puN arch/ia64/kernel/kprobes.c~kprobes-exclude-functions-ia64 arch/ia64/kernel/kprobes.c --- linux-2.6.13-rc1-mm1/arch/ia64/kernel/kprobes.c~kprobes-exclude-functions-ia64 2005-07-07 11:19:05.000000000 +0530 +++ linux-2.6.13-rc1-mm1-prasanna/arch/ia64/kernel/kprobes.c 2005-07-07 11:19:05.000000000 +0530 @@ -87,8 +87,10 @@ static enum instruction_type bundle_enco * is IP relative instruction and update the kprobe * inst flag accordingly */ -static void update_kprobe_inst_flag(uint template, uint slot, uint major_opcode, - unsigned long kprobe_inst, struct kprobe *p) +static void __kprobes update_kprobe_inst_flag(uint template, uint slot, + uint major_opcode, + unsigned long kprobe_inst, + struct kprobe *p) { p->ainsn.inst_flag = 0; p->ainsn.target_br_reg = 0; @@ -126,8 +128,10 @@ static void update_kprobe_inst_flag(uint * Returns 0 if supported * Returns -EINVAL if unsupported */ -static int unsupported_inst(uint template, uint slot, uint major_opcode, - unsigned long kprobe_inst, struct kprobe *p) +static int __kprobes unsupported_inst(uint template, uint slot, + uint major_opcode, + unsigned long kprobe_inst, + struct kprobe *p) { unsigned long addr = (unsigned long)p->addr; @@ -168,8 +172,9 @@ static int unsupported_inst(uint templat * on which we are inserting kprobe is cmp instruction * with ctype as unc. */ -static uint is_cmp_ctype_unc_inst(uint template, uint slot, uint major_opcode, -unsigned long kprobe_inst) +static uint __kprobes is_cmp_ctype_unc_inst(uint template, uint slot, + uint major_opcode, + unsigned long kprobe_inst) { cmp_inst_t cmp_inst; uint ctype_unc = 0; @@ -201,8 +206,10 @@ out: * In this function we override the bundle with * the break instruction at the given slot. */ -static void prepare_break_inst(uint template, uint slot, uint major_opcode, - unsigned long kprobe_inst, struct kprobe *p) +static void __kprobes prepare_break_inst(uint template, uint slot, + uint major_opcode, + unsigned long kprobe_inst, + struct kprobe *p) { unsigned long break_inst = BREAK_INST; bundle_t *bundle = &p->ainsn.insn.bundle; @@ -271,7 +278,8 @@ static inline int in_ivt_functions(unsig && addr < (unsigned long)__end_ivt_text); } -static int valid_kprobe_addr(int template, int slot, unsigned long addr) +static int __kprobes valid_kprobe_addr(int template, int slot, + unsigned long addr) { if ((slot > 2) || ((bundle_encoding[template][1] == L) && slot > 1)) { printk(KERN_WARNING "Attempting to insert unaligned kprobe " @@ -323,7 +331,7 @@ static void kretprobe_trampoline(void) * - cleanup by marking the instance as unused * - long jump back to the original return address */ -int trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) +int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) { struct kretprobe_instance *ri = NULL; struct hlist_head *head; @@ -381,7 +389,8 @@ int trampoline_probe_handler(struct kpro return 1; } -void arch_prepare_kretprobe(struct kretprobe *rp, struct pt_regs *regs) +void __kprobes arch_prepare_kretprobe(struct kretprobe *rp, + struct pt_regs *regs) { struct kretprobe_instance *ri; @@ -399,7 +408,7 @@ void arch_prepare_kretprobe(struct kretp } } -int arch_prepare_kprobe(struct kprobe *p) +int __kprobes arch_prepare_kprobe(struct kprobe *p) { unsigned long addr = (unsigned long) p->addr; unsigned long *kprobe_addr = (unsigned long *)(addr & ~0xFULL); @@ -430,7 +439,7 @@ int arch_prepare_kprobe(struct kprobe *p return 0; } -void arch_arm_kprobe(struct kprobe *p) +void __kprobes arch_arm_kprobe(struct kprobe *p) { unsigned long addr = (unsigned long)p->addr; unsigned long arm_addr = addr & ~0xFULL; @@ -439,7 +448,7 @@ void arch_arm_kprobe(struct kprobe *p) flush_icache_range(arm_addr, arm_addr + sizeof(bundle_t)); } -void arch_disarm_kprobe(struct kprobe *p) +void __kprobes arch_disarm_kprobe(struct kprobe *p) { unsigned long addr = (unsigned long)p->addr; unsigned long arm_addr = addr & ~0xFULL; @@ -449,7 +458,7 @@ void arch_disarm_kprobe(struct kprobe *p flush_icache_range(arm_addr, arm_addr + sizeof(bundle_t)); } -void arch_remove_kprobe(struct kprobe *p) +void __kprobes arch_remove_kprobe(struct kprobe *p) { } @@ -461,7 +470,7 @@ void arch_remove_kprobe(struct kprobe *p * to original stack address, handle the case where we need to fixup the * relative IP address and/or fixup branch register. */ -static void resume_execution(struct kprobe *p, struct pt_regs *regs) +static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs) { unsigned long bundle_addr = ((unsigned long) (&p->opcode.bundle)) & ~0xFULL; unsigned long resume_addr = (unsigned long)p->addr & ~0xFULL; @@ -528,7 +537,7 @@ turn_ss_off: ia64_psr(regs)->ss = 0; } -static void prepare_ss(struct kprobe *p, struct pt_regs *regs) +static void __kprobes prepare_ss(struct kprobe *p, struct pt_regs *regs) { unsigned long bundle_addr = (unsigned long) &p->opcode.bundle; unsigned long slot = (unsigned long)p->addr & 0xf; @@ -545,7 +554,7 @@ static void prepare_ss(struct kprobe *p, ia64_psr(regs)->ss = 1; } -static int pre_kprobes_handler(struct die_args *args) +static int __kprobes pre_kprobes_handler(struct die_args *args) { struct kprobe *p; int ret = 0; @@ -616,7 +625,7 @@ no_kprobe: return ret; } -static int post_kprobes_handler(struct pt_regs *regs) +static int __kprobes post_kprobes_handler(struct pt_regs *regs) { if (!kprobe_running()) return 0; @@ -641,7 +650,7 @@ out: return 1; } -static int kprobes_fault_handler(struct pt_regs *regs, int trapnr) +static int __kprobes kprobes_fault_handler(struct pt_regs *regs, int trapnr) { if (!kprobe_running()) return 0; @@ -659,8 +668,8 @@ static int kprobes_fault_handler(struct return 0; } -int kprobe_exceptions_notify(struct notifier_block *self, unsigned long val, - void *data) +int __kprobes kprobe_exceptions_notify(struct notifier_block *self, + unsigned long val, void *data) { struct die_args *args = (struct die_args *)data; switch(val) { @@ -681,7 +690,7 @@ int kprobe_exceptions_notify(struct noti return NOTIFY_DONE; } -int setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) +int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) { struct jprobe *jp = container_of(p, struct jprobe, kp); unsigned long addr = ((struct fnptr *)(jp->entry))->ip; @@ -703,7 +712,7 @@ int setjmp_pre_handler(struct kprobe *p, return 1; } -int longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) +int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) { *regs = jprobe_saved_regs; return 1; diff -puN arch/ia64/kernel/traps.c~kprobes-exclude-functions-ia64 arch/ia64/kernel/traps.c --- linux-2.6.13-rc1-mm1/arch/ia64/kernel/traps.c~kprobes-exclude-functions-ia64 2005-07-07 11:19:05.000000000 +0530 +++ linux-2.6.13-rc1-mm1-prasanna/arch/ia64/kernel/traps.c 2005-07-07 11:19:05.000000000 +0530 @@ -15,6 +15,7 @@ #include <linux/vt_kern.h> /* For unblank_screen() */ #include <linux/module.h> /* for EXPORT_SYMBOL */ #include <linux/hardirq.h> +#include <linux/kprobes.h> #include <asm/fpswa.h> #include <asm/ia32.h> @@ -120,7 +121,7 @@ die_if_kernel (char *str, struct pt_regs } void -ia64_bad_break (unsigned long break_num, struct pt_regs *regs) +__kprobes ia64_bad_break (unsigned long break_num, struct pt_regs *regs) { siginfo_t siginfo; int sig, code; @@ -442,7 +443,7 @@ ia64_illegal_op_fault (unsigned long ec, return rv; } -void +void __kprobes ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa, unsigned long iim, unsigned long itir, long arg5, long arg6, long arg7, struct pt_regs regs) diff -puN arch/ia64/kernel/vmlinux.lds.S~kprobes-exclude-functions-ia64 arch/ia64/kernel/vmlinux.lds.S --- linux-2.6.13-rc1-mm1/arch/ia64/kernel/vmlinux.lds.S~kprobes-exclude-functions-ia64 2005-07-07 11:19:05.000000000 +0530 +++ linux-2.6.13-rc1-mm1-prasanna/arch/ia64/kernel/vmlinux.lds.S 2005-07-07 11:19:05.000000000 +0530 @@ -48,6 +48,7 @@ SECTIONS *(.text) SCHED_TEXT LOCK_TEXT + KPROBES_TEXT *(.gnu.linkonce.t*) } .text2 : AT(ADDR(.text2) - LOAD_OFFSET) diff -puN arch/ia64/mm/fault.c~kprobes-exclude-functions-ia64 arch/ia64/mm/fault.c --- linux-2.6.13-rc1-mm1/arch/ia64/mm/fault.c~kprobes-exclude-functions-ia64 2005-07-07 11:19:05.000000000 +0530 +++ linux-2.6.13-rc1-mm1-prasanna/arch/ia64/mm/fault.c 2005-07-07 11:19:05.000000000 +0530 @@ -9,6 +9,7 @@ #include <linux/mm.h> #include <linux/smp_lock.h> #include <linux/interrupt.h> +#include <linux/kprobes.h> #include <asm/pgtable.h> #include <asm/processor.h> @@ -76,7 +77,7 @@ mapped_kernel_page_is_present (unsigned return pte_present(pte); } -void +void __kprobes ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *regs) { int signal = SIGSEGV, code = SEGV_MAPERR; diff -puN arch/ia64/lib/flush.S~kprobes-exclude-functions-ia64 arch/ia64/lib/flush.S --- linux-2.6.13-rc1-mm1/arch/ia64/lib/flush.S~kprobes-exclude-functions-ia64 2005-07-07 11:19:05.000000000 +0530 +++ linux-2.6.13-rc1-mm1-prasanna/arch/ia64/lib/flush.S 2005-07-07 11:20:23.000000000 +0530 @@ -12,6 +12,7 @@ * Must flush range from start to end-1 but nothing else (need to * be careful not to touch addresses that may be unmapped). */ + .section .kprobes.text GLOBAL_ENTRY(flush_icache_range) .prologue alloc r2=ar.pfs,2,0,0,0 diff -puN include/asm-ia64/asmmacro.h~kprobes-exclude-functions-ia64 include/asm-ia64/asmmacro.h _ -- Prasanna S Panchamukhi Linux Technology Center India Software Labs, IBM Bangalore Ph: 91-80-25044636 <prasanna@in.ibm.com> ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [6/6 PATCH] Kprobes : Prevent possible race conditions sparc64 changes 2005-07-07 10:18 ` [5/6 PATCH] Kprobes : Prevent possible race conditions ia64 changes Prasanna S Panchamukhi @ 2005-07-07 10:20 ` Prasanna S Panchamukhi 2005-07-08 2:06 ` [5/6 PATCH] Kprobes : Prevent possible race conditions ia64 changes Keshavamurthy Anil S 1 sibling, 0 replies; 19+ messages in thread From: Prasanna S Panchamukhi @ 2005-07-07 10:20 UTC (permalink / raw) To: akpm, Andi Kleen, David S. Miller, systemtap; +Cc: linux-kernel This patch contains the sparc64 architecture specific changes to prevent the possible race conditions. Signed-off-by: Prasanna S Panchamukhi <prasanna@in.ibm.com> --- linux-2.6.13-rc1-mm1-prasanna/arch/sparc64/kernel/kprobes.c | 36 +++++----- linux-2.6.13-rc1-mm1-prasanna/arch/sparc64/kernel/vmlinux.lds.S | 1 linux-2.6.13-rc1-mm1-prasanna/arch/sparc64/mm/fault.c | 8 +- linux-2.6.13-rc1-mm1-prasanna/arch/sparc64/mm/init.c | 3 linux-2.6.13-rc1-mm1-prasanna/arch/sparc64/mm/ultra.S | 2 5 files changed, 30 insertions(+), 20 deletions(-) diff -puN arch/sparc64/kernel/kprobes.c~kprobes-exclude-functions-sparc64 arch/sparc64/kernel/kprobes.c --- linux-2.6.13-rc1-mm1/arch/sparc64/kernel/kprobes.c~kprobes-exclude-functions-sparc64 2005-07-06 20:08:40.000000000 +0530 +++ linux-2.6.13-rc1-mm1-prasanna/arch/sparc64/kernel/kprobes.c 2005-07-06 20:08:40.000000000 +0530 @@ -8,6 +8,7 @@ #include <linux/kprobes.h> #include <asm/kdebug.h> #include <asm/signal.h> +#include <asm/cacheflush.h> /* We do not have hardware single-stepping on sparc64. * So we implement software single-stepping with breakpoint @@ -37,31 +38,31 @@ * - Mark that we are no longer actively in a kprobe. */ -int arch_prepare_kprobe(struct kprobe *p) +int __kprobes arch_prepare_kprobe(struct kprobe *p) { return 0; } -void arch_copy_kprobe(struct kprobe *p) +void __kprobes arch_copy_kprobe(struct kprobe *p) { p->ainsn.insn[0] = *p->addr; p->ainsn.insn[1] = BREAKPOINT_INSTRUCTION_2; p->opcode = *p->addr; } -void arch_arm_kprobe(struct kprobe *p) +void __kprobes arch_arm_kprobe(struct kprobe *p) { *p->addr = BREAKPOINT_INSTRUCTION; flushi(p->addr); } -void arch_disarm_kprobe(struct kprobe *p) +void __kprobes arch_disarm_kprobe(struct kprobe *p) { *p->addr = p->opcode; flushi(p->addr); } -void arch_remove_kprobe(struct kprobe *p) +void __kprobes arch_remove_kprobe(struct kprobe *p) { } @@ -111,7 +112,7 @@ static inline void prepare_singlestep(st } } -static int kprobe_handler(struct pt_regs *regs) +static int __kprobes kprobe_handler(struct pt_regs *regs) { struct kprobe *p; void *addr = (void *) regs->tpc; @@ -191,8 +192,9 @@ no_kprobe: * The original INSN location was REAL_PC, it actually * executed at PC and produced destination address NPC. */ -static unsigned long relbranch_fixup(u32 insn, unsigned long real_pc, - unsigned long pc, unsigned long npc) +static unsigned long __kprobes relbranch_fixup(u32 insn, unsigned long real_pc, + unsigned long pc, + unsigned long npc) { /* Branch not taken, no mods necessary. */ if (npc == pc + 0x4UL) @@ -217,7 +219,8 @@ static unsigned long relbranch_fixup(u32 /* If INSN is an instruction which writes it's PC location * into a destination register, fix that up. */ -static void retpc_fixup(struct pt_regs *regs, u32 insn, unsigned long real_pc) +static void __kprobes retpc_fixup(struct pt_regs *regs, u32 insn, + unsigned long real_pc) { unsigned long *slot = NULL; @@ -257,7 +260,7 @@ static void retpc_fixup(struct pt_regs * * This function prepares to return from the post-single-step * breakpoint trap. */ -static void resume_execution(struct kprobe *p, struct pt_regs *regs) +static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs) { u32 insn = p->ainsn.insn[0]; @@ -315,8 +318,8 @@ static inline int kprobe_fault_handler(s /* * Wrapper routine to for handling exceptions. */ -int kprobe_exceptions_notify(struct notifier_block *self, unsigned long val, - void *data) +int __kprobes kprobe_exceptions_notify(struct notifier_block *self, + unsigned long val, void *data) { struct die_args *args = (struct die_args *)data; switch (val) { @@ -344,7 +347,8 @@ int kprobe_exceptions_notify(struct noti return NOTIFY_DONE; } -asmlinkage void kprobe_trap(unsigned long trap_level, struct pt_regs *regs) +asmlinkage void __kprobes kprobe_trap(unsigned long trap_level, + struct pt_regs *regs) { BUG_ON(trap_level != 0x170 && trap_level != 0x171); @@ -368,7 +372,7 @@ static struct pt_regs jprobe_saved_regs; static struct pt_regs *jprobe_saved_regs_location; static struct sparc_stackf jprobe_saved_stack; -int setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) +int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) { struct jprobe *jp = container_of(p, struct jprobe, kp); @@ -390,7 +394,7 @@ int setjmp_pre_handler(struct kprobe *p, return 1; } -void jprobe_return(void) +void __kprobes jprobe_return(void) { preempt_enable_no_resched(); __asm__ __volatile__( @@ -403,7 +407,7 @@ extern void jprobe_return_trap_instructi extern void __show_regs(struct pt_regs * regs); -int longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) +int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) { u32 *addr = (u32 *) regs->tpc; diff -puN arch/sparc64/kernel/vmlinux.lds.S~kprobes-exclude-functions-sparc64 arch/sparc64/kernel/vmlinux.lds.S --- linux-2.6.13-rc1-mm1/arch/sparc64/kernel/vmlinux.lds.S~kprobes-exclude-functions-sparc64 2005-07-06 20:08:40.000000000 +0530 +++ linux-2.6.13-rc1-mm1-prasanna/arch/sparc64/kernel/vmlinux.lds.S 2005-07-06 20:08:40.000000000 +0530 @@ -17,6 +17,7 @@ SECTIONS *(.text) SCHED_TEXT LOCK_TEXT + KPROBES_TEXT *(.gnu.warning) } =0 _etext = .; diff -puN arch/sparc64/mm/fault.c~kprobes-exclude-functions-sparc64 arch/sparc64/mm/fault.c --- linux-2.6.13-rc1-mm1/arch/sparc64/mm/fault.c~kprobes-exclude-functions-sparc64 2005-07-06 20:08:40.000000000 +0530 +++ linux-2.6.13-rc1-mm1-prasanna/arch/sparc64/mm/fault.c 2005-07-06 20:08:40.000000000 +0530 @@ -18,6 +18,7 @@ #include <linux/smp_lock.h> #include <linux/init.h> #include <linux/interrupt.h> +#include <linux/kprobes.h> #include <asm/page.h> #include <asm/pgtable.h> @@ -133,8 +134,9 @@ unsigned long __init prom_probe_memory ( return tally; } -static void unhandled_fault(unsigned long address, struct task_struct *tsk, - struct pt_regs *regs) +static void __kprobes unhandled_fault(unsigned long address, + struct task_struct *tsk, + struct pt_regs *regs) { if ((unsigned long) address < PAGE_SIZE) { printk(KERN_ALERT "Unable to handle kernel NULL " @@ -320,7 +322,7 @@ cannot_handle: unhandled_fault (address, current, regs); } -asmlinkage void do_sparc64_fault(struct pt_regs *regs) +asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs) { struct mm_struct *mm = current->mm; struct vm_area_struct *vma; diff -puN arch/sparc64/mm/init.c~kprobes-exclude-functions-sparc64 arch/sparc64/mm/init.c --- linux-2.6.13-rc1-mm1/arch/sparc64/mm/init.c~kprobes-exclude-functions-sparc64 2005-07-06 20:08:40.000000000 +0530 +++ linux-2.6.13-rc1-mm1-prasanna/arch/sparc64/mm/init.c 2005-07-06 20:08:40.000000000 +0530 @@ -19,6 +19,7 @@ #include <linux/pagemap.h> #include <linux/fs.h> #include <linux/seq_file.h> +#include <linux/kprobes.h> #include <asm/head.h> #include <asm/system.h> @@ -239,7 +240,7 @@ out: put_cpu(); } -void flush_icache_range(unsigned long start, unsigned long end) +void __kprobes flush_icache_range(unsigned long start, unsigned long end) { /* Cheetah has coherent I-cache. */ if (tlb_type == spitfire) { diff -puN arch/sparc64/mm/ultra.S~kprobes-exclude-functions-sparc64 arch/sparc64/mm/ultra.S --- linux-2.6.13-rc1-mm1/arch/sparc64/mm/ultra.S~kprobes-exclude-functions-sparc64 2005-07-06 20:08:40.000000000 +0530 +++ linux-2.6.13-rc1-mm1-prasanna/arch/sparc64/mm/ultra.S 2005-07-07 10:19:48.000000000 +0530 @@ -112,6 +112,7 @@ __spitfire_flush_tlb_mm_slow: #else #error unsupported PAGE_SIZE #endif + .section .kprobes.text .align 32 .globl __flush_icache_page __flush_icache_page: /* %o0 = phys_page */ @@ -194,6 +195,7 @@ dflush4:stxa %g0, [%o4] ASI_DCACHE_TAG nop #endif /* DCACHE_ALIASING_POSSIBLE */ + .previous .text .align 32 __prefill_dtlb: rdpr %pstate, %g7 _ -- Prasanna S Panchamukhi Linux Technology Center India Software Labs, IBM Bangalore Ph: 91-80-25044636 <prasanna@in.ibm.com> ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [5/6 PATCH] Kprobes : Prevent possible race conditions ia64 changes 2005-07-07 10:18 ` [5/6 PATCH] Kprobes : Prevent possible race conditions ia64 changes Prasanna S Panchamukhi 2005-07-07 10:20 ` [6/6 PATCH] Kprobes : Prevent possible race conditions sparc64 changes Prasanna S Panchamukhi @ 2005-07-08 2:06 ` Keshavamurthy Anil S 2005-07-08 11:10 ` Prasanna S Panchamukhi 1 sibling, 1 reply; 19+ messages in thread From: Keshavamurthy Anil S @ 2005-07-08 2:06 UTC (permalink / raw) To: Prasanna S Panchamukhi Cc: akpm, Andi Kleen, David S. Miller, systemtap, linux-kernel, anil.s.keshavamurthy On Thu, Jul 07, 2005 at 03:18:33AM -0700, Prasanna S Panchamukhi wrote: > > This patch contains the ia64 architecture specific changes to > prevent the possible race conditions. > > Signed-off-by: Prasanna S Panchamukhi <prasanna@in.ibm.com> > > --- > > linux-2.6.13-rc1-mm1-prasanna/arch/ia64/kernel/kprobes.c | 57 > ++++++----- > linux-2.6.13-rc1-mm1-prasanna/arch/ia64/kernel/traps.c | 5 > linux-2.6.13-rc1-mm1-prasanna/arch/ia64/kernel/vmlinux.lds.S | 1 > linux-2.6.13-rc1-mm1-prasanna/arch/ia64/lib/flush.S | 1 > linux-2.6.13-rc1-mm1-prasanna/arch/ia64/mm/fault.c | 3 > 5 files changed, 40 insertions(+), 27 deletions(-) Prasanna, You have missed one jprobe specific file i.e arch/ia64/kernel/jprobe.S. I guess you need to patch this file in the same way as you have done for flush.S, i,e by adding .section .kprobes.text Thanks, Anil ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [5/6 PATCH] Kprobes : Prevent possible race conditions ia64 changes 2005-07-08 2:06 ` [5/6 PATCH] Kprobes : Prevent possible race conditions ia64 changes Keshavamurthy Anil S @ 2005-07-08 11:10 ` Prasanna S Panchamukhi 2005-07-08 19:01 ` Keshavamurthy Anil S 0 siblings, 1 reply; 19+ messages in thread From: Prasanna S Panchamukhi @ 2005-07-08 11:10 UTC (permalink / raw) To: Keshavamurthy Anil S Cc: akpm, Andi Kleen, David S. Miller, systemtap, linux-kernel Hi Anil, I have updated the patch as per your comments to move routines from jprobes.S to .kprobes.text section. Please let me know if you any issues. Thanks Prasanna This patch contains the ia64 architecture specific changes to prevent the possible race conditions. Signed-off-by: Prasanna S Panchamukhi <prasanna@in.ibm.com> --- include/asm-ia64/asmmacro.h | 0 linux-2.6.13-rc1-mm1-prasanna/arch/ia64/kernel/jprobes.S | 1 linux-2.6.13-rc1-mm1-prasanna/arch/ia64/kernel/kprobes.c | 57 ++++++----- linux-2.6.13-rc1-mm1-prasanna/arch/ia64/kernel/traps.c | 5 linux-2.6.13-rc1-mm1-prasanna/arch/ia64/kernel/vmlinux.lds.S | 1 linux-2.6.13-rc1-mm1-prasanna/arch/ia64/lib/flush.S | 1 linux-2.6.13-rc1-mm1-prasanna/arch/ia64/mm/fault.c | 3 7 files changed, 41 insertions(+), 27 deletions(-) diff -puN arch/ia64/kernel/kprobes.c~kprobes-exclude-functions-ia64 arch/ia64/kernel/kprobes.c --- linux-2.6.13-rc1-mm1/arch/ia64/kernel/kprobes.c~kprobes-exclude-functions-ia64 2005-07-08 15:22:52.000000000 +0530 +++ linux-2.6.13-rc1-mm1-prasanna/arch/ia64/kernel/kprobes.c 2005-07-08 15:22:52.000000000 +0530 @@ -87,8 +87,10 @@ static enum instruction_type bundle_enco * is IP relative instruction and update the kprobe * inst flag accordingly */ -static void update_kprobe_inst_flag(uint template, uint slot, uint major_opcode, - unsigned long kprobe_inst, struct kprobe *p) +static void __kprobes update_kprobe_inst_flag(uint template, uint slot, + uint major_opcode, + unsigned long kprobe_inst, + struct kprobe *p) { p->ainsn.inst_flag = 0; p->ainsn.target_br_reg = 0; @@ -126,8 +128,10 @@ static void update_kprobe_inst_flag(uint * Returns 0 if supported * Returns -EINVAL if unsupported */ -static int unsupported_inst(uint template, uint slot, uint major_opcode, - unsigned long kprobe_inst, struct kprobe *p) +static int __kprobes unsupported_inst(uint template, uint slot, + uint major_opcode, + unsigned long kprobe_inst, + struct kprobe *p) { unsigned long addr = (unsigned long)p->addr; @@ -168,8 +172,9 @@ static int unsupported_inst(uint templat * on which we are inserting kprobe is cmp instruction * with ctype as unc. */ -static uint is_cmp_ctype_unc_inst(uint template, uint slot, uint major_opcode, -unsigned long kprobe_inst) +static uint __kprobes is_cmp_ctype_unc_inst(uint template, uint slot, + uint major_opcode, + unsigned long kprobe_inst) { cmp_inst_t cmp_inst; uint ctype_unc = 0; @@ -201,8 +206,10 @@ out: * In this function we override the bundle with * the break instruction at the given slot. */ -static void prepare_break_inst(uint template, uint slot, uint major_opcode, - unsigned long kprobe_inst, struct kprobe *p) +static void __kprobes prepare_break_inst(uint template, uint slot, + uint major_opcode, + unsigned long kprobe_inst, + struct kprobe *p) { unsigned long break_inst = BREAK_INST; bundle_t *bundle = &p->ainsn.insn.bundle; @@ -271,7 +278,8 @@ static inline int in_ivt_functions(unsig && addr < (unsigned long)__end_ivt_text); } -static int valid_kprobe_addr(int template, int slot, unsigned long addr) +static int __kprobes valid_kprobe_addr(int template, int slot, + unsigned long addr) { if ((slot > 2) || ((bundle_encoding[template][1] == L) && slot > 1)) { printk(KERN_WARNING "Attempting to insert unaligned kprobe " @@ -323,7 +331,7 @@ static void kretprobe_trampoline(void) * - cleanup by marking the instance as unused * - long jump back to the original return address */ -int trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) +int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) { struct kretprobe_instance *ri = NULL; struct hlist_head *head; @@ -381,7 +389,8 @@ int trampoline_probe_handler(struct kpro return 1; } -void arch_prepare_kretprobe(struct kretprobe *rp, struct pt_regs *regs) +void __kprobes arch_prepare_kretprobe(struct kretprobe *rp, + struct pt_regs *regs) { struct kretprobe_instance *ri; @@ -399,7 +408,7 @@ void arch_prepare_kretprobe(struct kretp } } -int arch_prepare_kprobe(struct kprobe *p) +int __kprobes arch_prepare_kprobe(struct kprobe *p) { unsigned long addr = (unsigned long) p->addr; unsigned long *kprobe_addr = (unsigned long *)(addr & ~0xFULL); @@ -430,7 +439,7 @@ int arch_prepare_kprobe(struct kprobe *p return 0; } -void arch_arm_kprobe(struct kprobe *p) +void __kprobes arch_arm_kprobe(struct kprobe *p) { unsigned long addr = (unsigned long)p->addr; unsigned long arm_addr = addr & ~0xFULL; @@ -439,7 +448,7 @@ void arch_arm_kprobe(struct kprobe *p) flush_icache_range(arm_addr, arm_addr + sizeof(bundle_t)); } -void arch_disarm_kprobe(struct kprobe *p) +void __kprobes arch_disarm_kprobe(struct kprobe *p) { unsigned long addr = (unsigned long)p->addr; unsigned long arm_addr = addr & ~0xFULL; @@ -449,7 +458,7 @@ void arch_disarm_kprobe(struct kprobe *p flush_icache_range(arm_addr, arm_addr + sizeof(bundle_t)); } -void arch_remove_kprobe(struct kprobe *p) +void __kprobes arch_remove_kprobe(struct kprobe *p) { } @@ -461,7 +470,7 @@ void arch_remove_kprobe(struct kprobe *p * to original stack address, handle the case where we need to fixup the * relative IP address and/or fixup branch register. */ -static void resume_execution(struct kprobe *p, struct pt_regs *regs) +static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs) { unsigned long bundle_addr = ((unsigned long) (&p->opcode.bundle)) & ~0xFULL; unsigned long resume_addr = (unsigned long)p->addr & ~0xFULL; @@ -528,7 +537,7 @@ turn_ss_off: ia64_psr(regs)->ss = 0; } -static void prepare_ss(struct kprobe *p, struct pt_regs *regs) +static void __kprobes prepare_ss(struct kprobe *p, struct pt_regs *regs) { unsigned long bundle_addr = (unsigned long) &p->opcode.bundle; unsigned long slot = (unsigned long)p->addr & 0xf; @@ -545,7 +554,7 @@ static void prepare_ss(struct kprobe *p, ia64_psr(regs)->ss = 1; } -static int pre_kprobes_handler(struct die_args *args) +static int __kprobes pre_kprobes_handler(struct die_args *args) { struct kprobe *p; int ret = 0; @@ -616,7 +625,7 @@ no_kprobe: return ret; } -static int post_kprobes_handler(struct pt_regs *regs) +static int __kprobes post_kprobes_handler(struct pt_regs *regs) { if (!kprobe_running()) return 0; @@ -641,7 +650,7 @@ out: return 1; } -static int kprobes_fault_handler(struct pt_regs *regs, int trapnr) +static int __kprobes kprobes_fault_handler(struct pt_regs *regs, int trapnr) { if (!kprobe_running()) return 0; @@ -659,8 +668,8 @@ static int kprobes_fault_handler(struct return 0; } -int kprobe_exceptions_notify(struct notifier_block *self, unsigned long val, - void *data) +int __kprobes kprobe_exceptions_notify(struct notifier_block *self, + unsigned long val, void *data) { struct die_args *args = (struct die_args *)data; switch(val) { @@ -681,7 +690,7 @@ int kprobe_exceptions_notify(struct noti return NOTIFY_DONE; } -int setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) +int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) { struct jprobe *jp = container_of(p, struct jprobe, kp); unsigned long addr = ((struct fnptr *)(jp->entry))->ip; @@ -703,7 +712,7 @@ int setjmp_pre_handler(struct kprobe *p, return 1; } -int longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) +int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) { *regs = jprobe_saved_regs; return 1; diff -puN arch/ia64/kernel/traps.c~kprobes-exclude-functions-ia64 arch/ia64/kernel/traps.c --- linux-2.6.13-rc1-mm1/arch/ia64/kernel/traps.c~kprobes-exclude-functions-ia64 2005-07-08 15:22:52.000000000 +0530 +++ linux-2.6.13-rc1-mm1-prasanna/arch/ia64/kernel/traps.c 2005-07-08 15:22:52.000000000 +0530 @@ -15,6 +15,7 @@ #include <linux/vt_kern.h> /* For unblank_screen() */ #include <linux/module.h> /* for EXPORT_SYMBOL */ #include <linux/hardirq.h> +#include <linux/kprobes.h> #include <asm/fpswa.h> #include <asm/ia32.h> @@ -120,7 +121,7 @@ die_if_kernel (char *str, struct pt_regs } void -ia64_bad_break (unsigned long break_num, struct pt_regs *regs) +__kprobes ia64_bad_break (unsigned long break_num, struct pt_regs *regs) { siginfo_t siginfo; int sig, code; @@ -442,7 +443,7 @@ ia64_illegal_op_fault (unsigned long ec, return rv; } -void +void __kprobes ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa, unsigned long iim, unsigned long itir, long arg5, long arg6, long arg7, struct pt_regs regs) diff -puN arch/ia64/kernel/vmlinux.lds.S~kprobes-exclude-functions-ia64 arch/ia64/kernel/vmlinux.lds.S --- linux-2.6.13-rc1-mm1/arch/ia64/kernel/vmlinux.lds.S~kprobes-exclude-functions-ia64 2005-07-08 15:22:52.000000000 +0530 +++ linux-2.6.13-rc1-mm1-prasanna/arch/ia64/kernel/vmlinux.lds.S 2005-07-08 15:22:52.000000000 +0530 @@ -48,6 +48,7 @@ SECTIONS *(.text) SCHED_TEXT LOCK_TEXT + KPROBES_TEXT *(.gnu.linkonce.t*) } .text2 : AT(ADDR(.text2) - LOAD_OFFSET) diff -puN arch/ia64/mm/fault.c~kprobes-exclude-functions-ia64 arch/ia64/mm/fault.c --- linux-2.6.13-rc1-mm1/arch/ia64/mm/fault.c~kprobes-exclude-functions-ia64 2005-07-08 15:22:52.000000000 +0530 +++ linux-2.6.13-rc1-mm1-prasanna/arch/ia64/mm/fault.c 2005-07-08 15:22:52.000000000 +0530 @@ -9,6 +9,7 @@ #include <linux/mm.h> #include <linux/smp_lock.h> #include <linux/interrupt.h> +#include <linux/kprobes.h> #include <asm/pgtable.h> #include <asm/processor.h> @@ -76,7 +77,7 @@ mapped_kernel_page_is_present (unsigned return pte_present(pte); } -void +void __kprobes ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *regs) { int signal = SIGSEGV, code = SEGV_MAPERR; diff -puN arch/ia64/lib/flush.S~kprobes-exclude-functions-ia64 arch/ia64/lib/flush.S --- linux-2.6.13-rc1-mm1/arch/ia64/lib/flush.S~kprobes-exclude-functions-ia64 2005-07-08 15:22:52.000000000 +0530 +++ linux-2.6.13-rc1-mm1-prasanna/arch/ia64/lib/flush.S 2005-07-08 15:22:52.000000000 +0530 @@ -12,6 +12,7 @@ * Must flush range from start to end-1 but nothing else (need to * be careful not to touch addresses that may be unmapped). */ + .section .kprobes.text GLOBAL_ENTRY(flush_icache_range) .prologue alloc r2=ar.pfs,2,0,0,0 diff -puN include/asm-ia64/asmmacro.h~kprobes-exclude-functions-ia64 include/asm-ia64/asmmacro.h diff -puN arch/ia64/kernel/jprobes.S~kprobes-exclude-functions-ia64 arch/ia64/kernel/jprobes.S --- linux-2.6.13-rc1-mm1/arch/ia64/kernel/jprobes.S~kprobes-exclude-functions-ia64 2005-07-08 15:22:52.000000000 +0530 +++ linux-2.6.13-rc1-mm1-prasanna/arch/ia64/kernel/jprobes.S 2005-07-08 15:22:52.000000000 +0530 @@ -49,6 +49,7 @@ /* * void jprobe_break(void) */ + .section .kprobes.text, "ax" ENTRY(jprobe_break) break.m 0x80300 END(jprobe_break) _ -- Prasanna S Panchamukhi Linux Technology Center India Software Labs, IBM Bangalore Ph: 91-80-25044636 <prasanna@in.ibm.com> ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [5/6 PATCH] Kprobes : Prevent possible race conditions ia64 changes 2005-07-08 11:10 ` Prasanna S Panchamukhi @ 2005-07-08 19:01 ` Keshavamurthy Anil S 2005-07-08 19:16 ` Prarit Bhargava 0 siblings, 1 reply; 19+ messages in thread From: Keshavamurthy Anil S @ 2005-07-08 19:01 UTC (permalink / raw) To: Prasanna S Panchamukhi Cc: Keshavamurthy Anil S, akpm, Andi Kleen, David S. Miller, systemtap, linux-kernel On Fri, Jul 08, 2005 at 04:40:45PM +0530, Prasanna S Panchamukhi wrote: > Hi Anil, > > I have updated the patch as per your comments to move routines > from jprobes.S to .kprobes.text section. > > Please let me know if you any issues. Looks fine and tested it too on IA64 Tiger4 box and works as intened. Acked-by: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com> ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [5/6 PATCH] Kprobes : Prevent possible race conditions ia64 changes 2005-07-08 19:01 ` Keshavamurthy Anil S @ 2005-07-08 19:16 ` Prarit Bhargava 0 siblings, 0 replies; 19+ messages in thread From: Prarit Bhargava @ 2005-07-08 19:16 UTC (permalink / raw) To: Keshavamurthy Anil S Cc: Prasanna S Panchamukhi, akpm, Andi Kleen, David S. Miller, systemtap, linux-kernel Keshavamurthy Anil S wrote: > On Fri, Jul 08, 2005 at 04:40:45PM +0530, Prasanna S Panchamukhi wrote: > >>Hi Anil, >> >>I have updated the patch as per your comments to move routines >>from jprobes.S to .kprobes.text section. >> >>Please let me know if you any issues. > > Looks fine and tested it too on IA64 Tiger4 box and works as intened. > Acked-by: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com> > I ran this on 16p and a 64p ia64 systems and didn't see any issues. P. ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [4/6 PATCH] Kprobes : Prevent possible race conditions ppc64 changes 2005-07-07 10:16 ` [4/6 PATCH] Kprobes : Prevent possible race conditions ppc64 changes Prasanna S Panchamukhi 2005-07-07 10:18 ` [5/6 PATCH] Kprobes : Prevent possible race conditions ia64 changes Prasanna S Panchamukhi @ 2005-07-08 14:13 ` Ananth N Mavinakayanahalli 1 sibling, 0 replies; 19+ messages in thread From: Ananth N Mavinakayanahalli @ 2005-07-08 14:13 UTC (permalink / raw) To: Prasanna S Panchamukhi Cc: akpm, Andi Kleen, David S. Miller, systemtap, linux-kernel On Thu, Jul 07, 2005 at 03:46:50PM +0530, Prasanna S Panchamukhi wrote: > > This patch contains the ppc64 architecture specific changes to > prevent the possible race conditions. Prasanna, Please cc or post this patch to linuxppc64-dev@ozlabs.org. This patch touches files I am not sure I can comment on with authority. Thanks, Ananth > > Signed-off-by: Prasanna S Panchamukhi <prasanna@in.ibm.com> > > > --- > > linux-2.6.13-rc1-mm1-prasanna/arch/ppc64/kernel/kprobes.c | 29 +++++----- > linux-2.6.13-rc1-mm1-prasanna/arch/ppc64/kernel/misc.S | 4 - > linux-2.6.13-rc1-mm1-prasanna/arch/ppc64/kernel/traps.c | 5 + > linux-2.6.13-rc1-mm1-prasanna/arch/ppc64/kernel/vmlinux.lds.S | 1 > linux-2.6.13-rc1-mm1-prasanna/arch/ppc64/mm/fault.c | 5 + > linux-2.6.13-rc1-mm1-prasanna/include/asm-ppc64/processor.h | 14 ++++ > 6 files changed, 38 insertions(+), 20 deletions(-) > > diff -puN arch/ppc64/kernel/kprobes.c~kprobes-exclude-functions-ppc64 arch/ppc64/kernel/kprobes.c > --- linux-2.6.13-rc1-mm1/arch/ppc64/kernel/kprobes.c~kprobes-exclude-functions-ppc64 2005-07-06 20:07:22.000000000 +0530 > +++ linux-2.6.13-rc1-mm1-prasanna/arch/ppc64/kernel/kprobes.c 2005-07-06 20:07:22.000000000 +0530 > @@ -44,7 +44,7 @@ static struct kprobe *kprobe_prev; > static unsigned long kprobe_status_prev, kprobe_saved_msr_prev; > static struct pt_regs jprobe_saved_regs; > > -int arch_prepare_kprobe(struct kprobe *p) > +int __kprobes arch_prepare_kprobe(struct kprobe *p) > { > int ret = 0; > kprobe_opcode_t insn = *p->addr; > @@ -68,27 +68,27 @@ int arch_prepare_kprobe(struct kprobe *p > return ret; > } > > -void arch_copy_kprobe(struct kprobe *p) > +void __kprobes arch_copy_kprobe(struct kprobe *p) > { > memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t)); > p->opcode = *p->addr; > } > > -void arch_arm_kprobe(struct kprobe *p) > +void __kprobes arch_arm_kprobe(struct kprobe *p) > { > *p->addr = BREAKPOINT_INSTRUCTION; > flush_icache_range((unsigned long) p->addr, > (unsigned long) p->addr + sizeof(kprobe_opcode_t)); > } > > -void arch_disarm_kprobe(struct kprobe *p) > +void __kprobes arch_disarm_kprobe(struct kprobe *p) > { > *p->addr = p->opcode; > flush_icache_range((unsigned long) p->addr, > (unsigned long) p->addr + sizeof(kprobe_opcode_t)); > } > > -void arch_remove_kprobe(struct kprobe *p) > +void __kprobes arch_remove_kprobe(struct kprobe *p) > { > up(&kprobe_mutex); > free_insn_slot(p->ainsn.insn); > @@ -122,7 +122,8 @@ static inline void restore_previous_kpro > kprobe_saved_msr = kprobe_saved_msr_prev; > } > > -void arch_prepare_kretprobe(struct kretprobe *rp, struct pt_regs *regs) > +void __kprobes arch_prepare_kretprobe(struct kretprobe *rp, > + struct pt_regs *regs) > { > struct kretprobe_instance *ri; > > @@ -244,7 +245,7 @@ void kretprobe_trampoline_holder(void) > /* > * Called when the probe at kretprobe trampoline is hit > */ > -int trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) > +int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) > { > struct kretprobe_instance *ri = NULL; > struct hlist_head *head; > @@ -308,7 +309,7 @@ int trampoline_probe_handler(struct kpro > * single-stepped a copy of the instruction. The address of this > * copy is p->ainsn.insn. > */ > -static void resume_execution(struct kprobe *p, struct pt_regs *regs) > +static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs) > { > int ret; > unsigned int insn = *p->ainsn.insn; > @@ -373,8 +374,8 @@ static inline int kprobe_fault_handler(s > /* > * Wrapper routine to for handling exceptions. > */ > -int kprobe_exceptions_notify(struct notifier_block *self, unsigned long val, > - void *data) > +int __kprobes kprobe_exceptions_notify(struct notifier_block *self, > + unsigned long val, void *data) > { > struct die_args *args = (struct die_args *)data; > int ret = NOTIFY_DONE; > @@ -406,7 +407,7 @@ int kprobe_exceptions_notify(struct noti > return ret; > } > > -int setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) > +int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) > { > struct jprobe *jp = container_of(p, struct jprobe, kp); > > @@ -419,16 +420,16 @@ int setjmp_pre_handler(struct kprobe *p, > return 1; > } > > -void jprobe_return(void) > +void __kprobes jprobe_return(void) > { > asm volatile("trap" ::: "memory"); > } > > -void jprobe_return_end(void) > +void __kprobes jprobe_return_end(void) > { > }; > > -int longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) > +int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) > { > /* > * FIXME - we should ideally be validating that we got here 'cos > diff -puN arch/ppc64/kernel/traps.c~kprobes-exclude-functions-ppc64 arch/ppc64/kernel/traps.c > --- linux-2.6.13-rc1-mm1/arch/ppc64/kernel/traps.c~kprobes-exclude-functions-ppc64 2005-07-06 20:07:22.000000000 +0530 > +++ linux-2.6.13-rc1-mm1-prasanna/arch/ppc64/kernel/traps.c 2005-07-06 20:07:22.000000000 +0530 > @@ -30,6 +30,7 @@ > #include <linux/init.h> > #include <linux/module.h> > #include <linux/delay.h> > +#include <linux/kprobes.h> > #include <asm/kdebug.h> > > #include <asm/pgtable.h> > @@ -220,7 +221,7 @@ void instruction_breakpoint_exception(st > _exception(SIGTRAP, regs, TRAP_BRKPT, regs->nip); > } > > -void single_step_exception(struct pt_regs *regs) > +void __kprobes single_step_exception(struct pt_regs *regs) > { > regs->msr &= ~MSR_SE; /* Turn off 'trace' bit */ > > @@ -398,7 +399,7 @@ check_bug_trap(struct pt_regs *regs) > return 0; > } > > -void program_check_exception(struct pt_regs *regs) > +void __kprobes program_check_exception(struct pt_regs *regs) > { > if (debugger_fault_handler(regs)) > return; > diff -puN arch/ppc64/kernel/vmlinux.lds.S~kprobes-exclude-functions-ppc64 arch/ppc64/kernel/vmlinux.lds.S > --- linux-2.6.13-rc1-mm1/arch/ppc64/kernel/vmlinux.lds.S~kprobes-exclude-functions-ppc64 2005-07-06 20:07:22.000000000 +0530 > +++ linux-2.6.13-rc1-mm1-prasanna/arch/ppc64/kernel/vmlinux.lds.S 2005-07-06 20:07:22.000000000 +0530 > @@ -15,6 +15,7 @@ SECTIONS > *(.text .text.*) > SCHED_TEXT > LOCK_TEXT > + KPROBES_TEXT > *(.fixup) > . = ALIGN(4096); > _etext = .; > diff -puN arch/ppc64/mm/fault.c~kprobes-exclude-functions-ppc64 arch/ppc64/mm/fault.c > --- linux-2.6.13-rc1-mm1/arch/ppc64/mm/fault.c~kprobes-exclude-functions-ppc64 2005-07-06 20:07:22.000000000 +0530 > +++ linux-2.6.13-rc1-mm1-prasanna/arch/ppc64/mm/fault.c 2005-07-06 20:07:22.000000000 +0530 > @@ -29,6 +29,7 @@ > #include <linux/interrupt.h> > #include <linux/smp_lock.h> > #include <linux/module.h> > +#include <linux/kprobes.h> > > #include <asm/page.h> > #include <asm/pgtable.h> > @@ -84,8 +85,8 @@ static int store_updates_sp(struct pt_re > * The return value is 0 if the fault was handled, or the signal > * number if this is a kernel fault that can't be handled here. > */ > -int do_page_fault(struct pt_regs *regs, unsigned long address, > - unsigned long error_code) > +int __kprobes do_page_fault(struct pt_regs *regs, unsigned long address, > + unsigned long error_code) > { > struct vm_area_struct * vma; > struct mm_struct *mm = current->mm; > diff -puN arch/ppc64/kernel/misc.S~kprobes-exclude-functions-ppc64 arch/ppc64/kernel/misc.S > --- linux-2.6.13-rc1-mm1/arch/ppc64/kernel/misc.S~kprobes-exclude-functions-ppc64 2005-07-06 20:07:22.000000000 +0530 > +++ linux-2.6.13-rc1-mm1-prasanna/arch/ppc64/kernel/misc.S 2005-07-07 10:24:00.000000000 +0530 > @@ -183,7 +183,7 @@ PPC64_CACHES: > * flush all bytes from start through stop-1 inclusive > */ > > -_GLOBAL(__flush_icache_range) > +_KPROBE(__flush_icache_range) > > /* > * Flush the data cache to memory > @@ -223,7 +223,7 @@ _GLOBAL(__flush_icache_range) > bdnz 2b > isync > blr > - > + .previous .text > /* > * Like above, but only do the D-cache. > * > diff -puN include/asm-ppc64/processor.h~kprobes-exclude-functions-ppc64 include/asm-ppc64/processor.h > --- linux-2.6.13-rc1-mm1/include/asm-ppc64/processor.h~kprobes-exclude-functions-ppc64 2005-07-06 20:07:22.000000000 +0530 > +++ linux-2.6.13-rc1-mm1-prasanna/include/asm-ppc64/processor.h 2005-07-07 10:22:29.000000000 +0530 > @@ -309,6 +309,20 @@ name: \ > .type GLUE(.,name),@function; \ > GLUE(.,name): > > +#define _KPROBE(name) \ > + .section ".kprobes.text","a"; \ > + .align 2 ; \ > + .globl name; \ > + .globl GLUE(.,name); \ > + .section ".opd","aw"; \ > +name: \ > + .quad GLUE(.,name); \ > + .quad .TOC.@tocbase; \ > + .quad 0; \ > + .previous; \ > + .type GLUE(.,name),@function; \ > +GLUE(.,name): > + > #define _STATIC(name) \ > .section ".text"; \ > .align 2 ; \ > > _ > -- > > Prasanna S Panchamukhi > Linux Technology Center > India Software Labs, IBM Bangalore > Ph: 91-80-25044636 > <prasanna@in.ibm.com> ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [3/6 PATCH] Kprobes : Prevent possible race conditions x86_64 changes 2005-07-07 10:14 ` [3/6 PATCH] Kprobes : Prevent possible race conditions x86_64 changes Prasanna S Panchamukhi 2005-07-07 10:16 ` [4/6 PATCH] Kprobes : Prevent possible race conditions ppc64 changes Prasanna S Panchamukhi @ 2005-07-08 11:07 ` Prasanna S Panchamukhi 1 sibling, 0 replies; 19+ messages in thread From: Prasanna S Panchamukhi @ 2005-07-08 11:07 UTC (permalink / raw) To: akpm, Andi Kleen, David S. Miller, systemtap; +Cc: linux-kernel Hi Andi, I have updated the patch as per your comments to move int3,debug, page_fault, general_protection routines to .kprobes.text section. Please let me know if you any issues. Thanks Prasanna This patch contains the x86_64 architecture specific changes to prevent the possible race conditions. Signed-off-by: Prasanna S Panchamukhi <prasanna@in.ibm.com> --- linux-2.6.13-rc1-mm1-prasanna/arch/x86_64/kernel/entry.S | 12 ++- linux-2.6.13-rc1-mm1-prasanna/arch/x86_64/kernel/kprobes.c | 35 +++++----- linux-2.6.13-rc1-mm1-prasanna/arch/x86_64/kernel/traps.c | 14 ++-- linux-2.6.13-rc1-mm1-prasanna/arch/x86_64/kernel/vmlinux.lds.S | 1 linux-2.6.13-rc1-mm1-prasanna/arch/x86_64/mm/fault.c | 3 5 files changed, 38 insertions(+), 27 deletions(-) diff -puN arch/x86_64/kernel/kprobes.c~kprobes-exclude-functions-x86_64 arch/x86_64/kernel/kprobes.c --- linux-2.6.13-rc1-mm1/arch/x86_64/kernel/kprobes.c~kprobes-exclude-functions-x86_64 2005-07-08 11:14:01.000000000 +0530 +++ linux-2.6.13-rc1-mm1-prasanna/arch/x86_64/kernel/kprobes.c 2005-07-08 11:14:01.000000000 +0530 @@ -74,7 +74,7 @@ static inline int is_IF_modifier(kprobe_ return 0; } -int arch_prepare_kprobe(struct kprobe *p) +int __kprobes arch_prepare_kprobe(struct kprobe *p) { /* insn: must be on special executable page on x86_64. */ up(&kprobe_mutex); @@ -189,7 +189,7 @@ static inline s32 *is_riprel(u8 *insn) return NULL; } -void arch_copy_kprobe(struct kprobe *p) +void __kprobes arch_copy_kprobe(struct kprobe *p) { s32 *ripdisp; memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE); @@ -215,21 +215,21 @@ void arch_copy_kprobe(struct kprobe *p) p->opcode = *p->addr; } -void arch_arm_kprobe(struct kprobe *p) +void __kprobes arch_arm_kprobe(struct kprobe *p) { *p->addr = BREAKPOINT_INSTRUCTION; flush_icache_range((unsigned long) p->addr, (unsigned long) p->addr + sizeof(kprobe_opcode_t)); } -void arch_disarm_kprobe(struct kprobe *p) +void __kprobes arch_disarm_kprobe(struct kprobe *p) { *p->addr = p->opcode; flush_icache_range((unsigned long) p->addr, (unsigned long) p->addr + sizeof(kprobe_opcode_t)); } -void arch_remove_kprobe(struct kprobe *p) +void __kprobes arch_remove_kprobe(struct kprobe *p) { up(&kprobe_mutex); free_insn_slot(p->ainsn.insn); @@ -261,7 +261,7 @@ static inline void set_current_kprobe(st kprobe_saved_rflags &= ~IF_MASK; } -static void prepare_singlestep(struct kprobe *p, struct pt_regs *regs) +static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs) { regs->eflags |= TF_MASK; regs->eflags &= ~IF_MASK; @@ -272,7 +272,8 @@ static void prepare_singlestep(struct kp regs->rip = (unsigned long)p->ainsn.insn; } -void arch_prepare_kretprobe(struct kretprobe *rp, struct pt_regs *regs) +void __kprobes arch_prepare_kretprobe(struct kretprobe *rp, + struct pt_regs *regs) { unsigned long *sara = (unsigned long *)regs->rsp; struct kretprobe_instance *ri; @@ -295,7 +296,7 @@ void arch_prepare_kretprobe(struct kretp * Interrupts are disabled on entry as trap3 is an interrupt gate and they * remain disabled thorough out this function. */ -int kprobe_handler(struct pt_regs *regs) +int __kprobes kprobe_handler(struct pt_regs *regs) { struct kprobe *p; int ret = 0; @@ -399,7 +400,7 @@ no_kprobe: /* * Called when we hit the probe point at kretprobe_trampoline */ -int trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) +int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) { struct kretprobe_instance *ri = NULL; struct hlist_head *head; @@ -478,7 +479,7 @@ int trampoline_probe_handler(struct kpro * that is atop the stack is the address following the copied instruction. * We need to make it the address following the original instruction. */ -static void resume_execution(struct kprobe *p, struct pt_regs *regs) +static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs) { unsigned long *tos = (unsigned long *)regs->rsp; unsigned long next_rip = 0; @@ -536,7 +537,7 @@ static void resume_execution(struct kpro * Interrupts are disabled on entry as trap1 is an interrupt gate and they * remain disabled thoroughout this function. And we hold kprobe lock. */ -int post_kprobe_handler(struct pt_regs *regs) +int __kprobes post_kprobe_handler(struct pt_regs *regs) { if (!kprobe_running()) return 0; @@ -571,7 +572,7 @@ out: } /* Interrupts disabled, kprobe_lock held. */ -int kprobe_fault_handler(struct pt_regs *regs, int trapnr) +int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr) { if (current_kprobe->fault_handler && current_kprobe->fault_handler(current_kprobe, regs, trapnr)) @@ -590,8 +591,8 @@ int kprobe_fault_handler(struct pt_regs /* * Wrapper routine for handling exceptions. */ -int kprobe_exceptions_notify(struct notifier_block *self, unsigned long val, - void *data) +int __kprobes kprobe_exceptions_notify(struct notifier_block *self, + unsigned long val, void *data) { struct die_args *args = (struct die_args *)data; switch (val) { @@ -619,7 +620,7 @@ int kprobe_exceptions_notify(struct noti return NOTIFY_DONE; } -int setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) +int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) { struct jprobe *jp = container_of(p, struct jprobe, kp); unsigned long addr; @@ -640,7 +641,7 @@ int setjmp_pre_handler(struct kprobe *p, return 1; } -void jprobe_return(void) +void __kprobes jprobe_return(void) { preempt_enable_no_resched(); asm volatile (" xchg %%rbx,%%rsp \n" @@ -651,7 +652,7 @@ void jprobe_return(void) (jprobe_saved_rsp):"memory"); } -int longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) +int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) { u8 *addr = (u8 *) (regs->rip - 1); unsigned long stack_addr = (unsigned long)jprobe_saved_rsp; diff -puN arch/x86_64/kernel/traps.c~kprobes-exclude-functions-x86_64 arch/x86_64/kernel/traps.c --- linux-2.6.13-rc1-mm1/arch/x86_64/kernel/traps.c~kprobes-exclude-functions-x86_64 2005-07-08 11:14:01.000000000 +0530 +++ linux-2.6.13-rc1-mm1-prasanna/arch/x86_64/kernel/traps.c 2005-07-08 11:14:01.000000000 +0530 @@ -29,6 +29,7 @@ #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/nmi.h> +#include <linux/kprobes.h> #include <asm/system.h> #include <asm/uaccess.h> @@ -422,8 +423,9 @@ void die_nmi(char *str, struct pt_regs * do_exit(SIGSEGV); } -static void do_trap(int trapnr, int signr, char *str, - struct pt_regs * regs, long error_code, siginfo_t *info) +static void __kprobes do_trap(int trapnr, int signr, char *str, + struct pt_regs * regs, long error_code, + siginfo_t *info) { conditional_sti(regs); @@ -507,7 +509,8 @@ DO_ERROR(18, SIGSEGV, "reserved", reserv DO_ERROR(12, SIGBUS, "stack segment", stack_segment) DO_ERROR( 8, SIGSEGV, "double fault", double_fault) -asmlinkage void do_general_protection(struct pt_regs * regs, long error_code) +asmlinkage void __kprobes do_general_protection(struct pt_regs * regs, + long error_code) { conditional_sti(regs); @@ -628,7 +631,7 @@ asmlinkage void default_do_nmi(struct pt io_check_error(reason, regs); } -asmlinkage void do_int3(struct pt_regs * regs, long error_code) +asmlinkage void __kprobes do_int3(struct pt_regs * regs, long error_code) { if (notify_die(DIE_INT3, "int3", regs, error_code, 3, SIGTRAP) == NOTIFY_STOP) { return; @@ -659,7 +662,8 @@ asmlinkage struct pt_regs *sync_regs(str } /* runs on IST stack. */ -asmlinkage void do_debug(struct pt_regs * regs, unsigned long error_code) +asmlinkage void __kprobes do_debug(struct pt_regs * regs, + unsigned long error_code) { unsigned long condition; struct task_struct *tsk = current; diff -puN arch/x86_64/kernel/vmlinux.lds.S~kprobes-exclude-functions-x86_64 arch/x86_64/kernel/vmlinux.lds.S --- linux-2.6.13-rc1-mm1/arch/x86_64/kernel/vmlinux.lds.S~kprobes-exclude-functions-x86_64 2005-07-08 11:14:01.000000000 +0530 +++ linux-2.6.13-rc1-mm1-prasanna/arch/x86_64/kernel/vmlinux.lds.S 2005-07-08 11:14:01.000000000 +0530 @@ -21,6 +21,7 @@ SECTIONS *(.text) SCHED_TEXT LOCK_TEXT + KPROBES_TEXT *(.fixup) *(.gnu.warning) } = 0x9090 diff -puN arch/x86_64/mm/fault.c~kprobes-exclude-functions-x86_64 arch/x86_64/mm/fault.c --- linux-2.6.13-rc1-mm1/arch/x86_64/mm/fault.c~kprobes-exclude-functions-x86_64 2005-07-08 11:14:01.000000000 +0530 +++ linux-2.6.13-rc1-mm1-prasanna/arch/x86_64/mm/fault.c 2005-07-08 11:14:01.000000000 +0530 @@ -297,7 +297,8 @@ int exception_trace = 1; * bit 2 == 0 means kernel, 1 means user-mode * bit 3 == 1 means fault was an instruction fetch */ -asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code) +asmlinkage void __kprobes do_page_fault(struct pt_regs *regs, + unsigned long error_code) { struct task_struct *tsk; struct mm_struct *mm; diff -puN arch/x86_64/kernel/entry.S~kprobes-exclude-functions-x86_64 arch/x86_64/kernel/entry.S --- linux-2.6.13-rc1-mm1/arch/x86_64/kernel/entry.S~kprobes-exclude-functions-x86_64 2005-07-08 11:14:01.000000000 +0530 +++ linux-2.6.13-rc1-mm1-prasanna/arch/x86_64/kernel/entry.S 2005-07-08 11:17:03.000000000 +0530 @@ -789,8 +789,9 @@ ENTRY(execve) ret CFI_ENDPROC -ENTRY(page_fault) +KPROBE_ENTRY(page_fault) errorentry do_page_fault + .previous .text ENTRY(coprocessor_error) zeroentry do_coprocessor_error @@ -802,13 +803,14 @@ ENTRY(device_not_available) zeroentry math_state_restore /* runs on exception stack */ -ENTRY(debug) +KPROBE_ENTRY(debug) CFI_STARTPROC pushq $0 CFI_ADJUST_CFA_OFFSET 8 paranoidentry do_debug jmp paranoid_exit CFI_ENDPROC + .previous .text /* runs on exception stack */ ENTRY(nmi) @@ -859,8 +861,9 @@ paranoid_schedule: jmp paranoid_userspace CFI_ENDPROC -ENTRY(int3) +KPROBE_ENTRY(int3) zeroentry do_int3 + .previous .text ENTRY(overflow) zeroentry do_overflow @@ -897,8 +900,9 @@ ENTRY(stack_segment) jmp paranoid_exit CFI_ENDPROC -ENTRY(general_protection) +KPROBE_ENTRY(general_protection) errorentry do_general_protection + .previous .text ENTRY(alignment_check) errorentry do_alignment_check _ -- Prasanna S Panchamukhi Linux Technology Center India Software Labs, IBM Bangalore Ph: 91-80-25044636 <prasanna@in.ibm.com> ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [2/6 PATCH] Kprobes : Prevent possible race conditions i386 changes 2005-07-07 10:11 ` [2/6 PATCH] Kprobes : Prevent possible race conditions i386 changes Prasanna S Panchamukhi 2005-07-07 10:14 ` [3/6 PATCH] Kprobes : Prevent possible race conditions x86_64 changes Prasanna S Panchamukhi @ 2005-07-07 13:19 ` Andi Kleen 2005-07-08 11:05 ` Prasanna S Panchamukhi 1 sibling, 1 reply; 19+ messages in thread From: Andi Kleen @ 2005-07-07 13:19 UTC (permalink / raw) To: Prasanna S Panchamukhi Cc: akpm, Andi Kleen, David S. Miller, systemtap, linux-kernel > -fastcall void do_page_fault(struct pt_regs *regs, unsigned long error_code) > +fastcall void __kprobes do_page_fault(struct pt_regs *regs, > + unsigned long error_code) That's not enough. You would need to change entry.S too. Same on x86-64. And how about general protection fault? -Andi ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [2/6 PATCH] Kprobes : Prevent possible race conditions i386 changes 2005-07-07 13:19 ` [2/6 PATCH] Kprobes : Prevent possible race conditions i386 changes Andi Kleen @ 2005-07-08 11:05 ` Prasanna S Panchamukhi 0 siblings, 0 replies; 19+ messages in thread From: Prasanna S Panchamukhi @ 2005-07-08 11:05 UTC (permalink / raw) To: Andi Kleen; +Cc: akpm, David S. Miller, systemtap, linux-kernel Hi Andi, I have updated the patch as per your comments to move int3,debug, page_fault, general_protection routines to .kprobes.text section. Please let me know if you any issues. Thanks Prasanna This patch contains the i386 architecture specific changes to prevent the possible race conditions. Signed-off-by: Prasanna S Panchamukhi <prasanna@in.ibm.com> --- linux-2.6.13-rc1-mm1-prasanna/arch/i386/kernel/entry.S | 13 +++- linux-2.6.13-rc1-mm1-prasanna/arch/i386/kernel/kprobes.c | 29 +++++------ linux-2.6.13-rc1-mm1-prasanna/arch/i386/kernel/traps.c | 12 ++-- linux-2.6.13-rc1-mm1-prasanna/arch/i386/kernel/vmlinux.lds.S | 1 linux-2.6.13-rc1-mm1-prasanna/arch/i386/mm/fault.c | 4 + 5 files changed, 34 insertions(+), 25 deletions(-) diff -puN arch/i386/kernel/kprobes.c~kprobes-exclude-functions-i386 arch/i386/kernel/kprobes.c --- linux-2.6.13-rc1-mm1/arch/i386/kernel/kprobes.c~kprobes-exclude-functions-i386 2005-07-08 12:09:51.000000000 +0530 +++ linux-2.6.13-rc1-mm1-prasanna/arch/i386/kernel/kprobes.c 2005-07-08 12:09:51.000000000 +0530 @@ -62,32 +62,32 @@ static inline int is_IF_modifier(kprobe_ return 0; } -int arch_prepare_kprobe(struct kprobe *p) +int __kprobes arch_prepare_kprobe(struct kprobe *p) { return 0; } -void arch_copy_kprobe(struct kprobe *p) +void __kprobes arch_copy_kprobe(struct kprobe *p) { memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t)); p->opcode = *p->addr; } -void arch_arm_kprobe(struct kprobe *p) +void __kprobes arch_arm_kprobe(struct kprobe *p) { *p->addr = BREAKPOINT_INSTRUCTION; flush_icache_range((unsigned long) p->addr, (unsigned long) p->addr + sizeof(kprobe_opcode_t)); } -void arch_disarm_kprobe(struct kprobe *p) +void __kprobes arch_disarm_kprobe(struct kprobe *p) { *p->addr = p->opcode; flush_icache_range((unsigned long) p->addr, (unsigned long) p->addr + sizeof(kprobe_opcode_t)); } -void arch_remove_kprobe(struct kprobe *p) +void __kprobes arch_remove_kprobe(struct kprobe *p) { } @@ -127,7 +127,8 @@ static inline void prepare_singlestep(st regs->eip = (unsigned long)&p->ainsn.insn; } -void arch_prepare_kretprobe(struct kretprobe *rp, struct pt_regs *regs) +void __kprobes arch_prepare_kretprobe(struct kretprobe *rp, + struct pt_regs *regs) { unsigned long *sara = (unsigned long *)®s->esp; struct kretprobe_instance *ri; @@ -150,7 +151,7 @@ void arch_prepare_kretprobe(struct kretp * Interrupts are disabled on entry as trap3 is an interrupt gate and they * remain disabled thorough out this function. */ -static int kprobe_handler(struct pt_regs *regs) +static int __kprobes kprobe_handler(struct pt_regs *regs) { struct kprobe *p; int ret = 0; @@ -259,7 +260,7 @@ no_kprobe: /* * Called when we hit the probe point at kretprobe_trampoline */ -int trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) +int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) { struct kretprobe_instance *ri = NULL; struct hlist_head *head; @@ -338,7 +339,7 @@ int trampoline_probe_handler(struct kpro * that is atop the stack is the address following the copied instruction. * We need to make it the address following the original instruction. */ -static void resume_execution(struct kprobe *p, struct pt_regs *regs) +static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs) { unsigned long *tos = (unsigned long *)®s->esp; unsigned long next_eip = 0; @@ -444,8 +445,8 @@ static inline int kprobe_fault_handler(s /* * Wrapper routine to for handling exceptions. */ -int kprobe_exceptions_notify(struct notifier_block *self, unsigned long val, - void *data) +int __kprobes kprobe_exceptions_notify(struct notifier_block *self, + unsigned long val, void *data) { struct die_args *args = (struct die_args *)data; switch (val) { @@ -473,7 +474,7 @@ int kprobe_exceptions_notify(struct noti return NOTIFY_DONE; } -int setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) +int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) { struct jprobe *jp = container_of(p, struct jprobe, kp); unsigned long addr; @@ -495,7 +496,7 @@ int setjmp_pre_handler(struct kprobe *p, return 1; } -void jprobe_return(void) +void __kprobes jprobe_return(void) { preempt_enable_no_resched(); asm volatile (" xchgl %%ebx,%%esp \n" @@ -506,7 +507,7 @@ void jprobe_return(void) (jprobe_saved_esp):"memory"); } -int longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) +int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) { u8 *addr = (u8 *) (regs->eip - 1); unsigned long stack_addr = (unsigned long)jprobe_saved_esp; diff -puN arch/i386/kernel/traps.c~kprobes-exclude-functions-i386 arch/i386/kernel/traps.c --- linux-2.6.13-rc1-mm1/arch/i386/kernel/traps.c~kprobes-exclude-functions-i386 2005-07-08 12:09:51.000000000 +0530 +++ linux-2.6.13-rc1-mm1-prasanna/arch/i386/kernel/traps.c 2005-07-08 12:09:51.000000000 +0530 @@ -408,8 +408,9 @@ static inline void die_if_kernel(const c die(str, regs, err); } -static void do_trap(int trapnr, int signr, char *str, int vm86, - struct pt_regs * regs, long error_code, siginfo_t *info) +static void __kprobes do_trap(int trapnr, int signr, char *str, int vm86, + struct pt_regs * regs, long error_code, + siginfo_t *info) { struct task_struct *tsk = current; tsk->thread.error_code = error_code; @@ -507,7 +508,8 @@ DO_ERROR(12, SIGBUS, "stack segment", s DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, 0) DO_ERROR_INFO(32, SIGSEGV, "iret exception", iret_error, ILL_BADSTK, 0) -fastcall void do_general_protection(struct pt_regs * regs, long error_code) +fastcall void __kprobes do_general_protection(struct pt_regs * regs, + long error_code) { int cpu = get_cpu(); struct tss_struct *tss = &per_cpu(init_tss, cpu); @@ -737,7 +739,7 @@ void unset_nmi_callback(void) EXPORT_SYMBOL_GPL(unset_nmi_callback); #ifdef CONFIG_KPROBES -fastcall void do_int3(struct pt_regs *regs, long error_code) +fastcall void __kprobes do_int3(struct pt_regs *regs, long error_code) { if (notify_die(DIE_INT3, "int3", regs, error_code, 3, SIGTRAP) == NOTIFY_STOP) @@ -771,7 +773,7 @@ fastcall void do_int3(struct pt_regs *re * find every occurrence of the TF bit that could be saved away even * by user code) */ -fastcall void do_debug(struct pt_regs * regs, long error_code) +fastcall void __kprobes do_debug(struct pt_regs * regs, long error_code) { unsigned int condition; struct task_struct *tsk = current; diff -puN arch/i386/kernel/vmlinux.lds.S~kprobes-exclude-functions-i386 arch/i386/kernel/vmlinux.lds.S --- linux-2.6.13-rc1-mm1/arch/i386/kernel/vmlinux.lds.S~kprobes-exclude-functions-i386 2005-07-08 12:09:51.000000000 +0530 +++ linux-2.6.13-rc1-mm1-prasanna/arch/i386/kernel/vmlinux.lds.S 2005-07-08 12:09:51.000000000 +0530 @@ -22,6 +22,7 @@ SECTIONS *(.text) SCHED_TEXT LOCK_TEXT + KPROBES_TEXT *(.fixup) *(.gnu.warning) } = 0x9090 diff -puN arch/i386/mm/fault.c~kprobes-exclude-functions-i386 arch/i386/mm/fault.c --- linux-2.6.13-rc1-mm1/arch/i386/mm/fault.c~kprobes-exclude-functions-i386 2005-07-08 12:09:51.000000000 +0530 +++ linux-2.6.13-rc1-mm1-prasanna/arch/i386/mm/fault.c 2005-07-08 12:09:51.000000000 +0530 @@ -21,6 +21,7 @@ #include <linux/vt_kern.h> /* For unblank_screen() */ #include <linux/highmem.h> #include <linux/module.h> +#include <linux/kprobes.h> #include <asm/system.h> #include <asm/uaccess.h> @@ -211,7 +212,8 @@ fastcall void do_invalid_op(struct pt_re * bit 1 == 0 means read, 1 means write * bit 2 == 0 means kernel, 1 means user-mode */ -fastcall void do_page_fault(struct pt_regs *regs, unsigned long error_code) +fastcall void __kprobes do_page_fault(struct pt_regs *regs, + unsigned long error_code) { struct task_struct *tsk; struct mm_struct *mm; diff -puN arch/i386/kernel/entry.S~kprobes-exclude-functions-i386 arch/i386/kernel/entry.S --- linux-2.6.13-rc1-mm1/arch/i386/kernel/entry.S~kprobes-exclude-functions-i386 2005-07-08 12:09:51.000000000 +0530 +++ linux-2.6.13-rc1-mm1-prasanna/arch/i386/kernel/entry.S 2005-07-08 12:09:51.000000000 +0530 @@ -532,7 +532,7 @@ label: \ pushl $__KERNEL_CS; \ pushl $sysenter_past_esp -ENTRY(debug) +KPROBE_ENTRY(debug) cmpl $sysenter_entry,(%esp) jne debug_stack_correct FIX_STACK(12, debug_stack_correct, debug_esp_fix_insn) @@ -543,7 +543,7 @@ debug_stack_correct: movl %esp,%eax # pt_regs pointer call do_debug jmp ret_from_exception - + .previous .text /* * NMI is doubly nasty. It can happen _while_ we're handling * a debug fault, and the debug fault hasn't yet been able to @@ -616,13 +616,14 @@ nmi_16bit_stack: .long 1b,iret_exc .previous -ENTRY(int3) +KPROBE_ENTRY(int3) pushl $-1 # mark this as an int SAVE_ALL xorl %edx,%edx # zero error code movl %esp,%eax # pt_regs pointer call do_int3 jmp ret_from_exception + .previous .text ENTRY(overflow) pushl $0 @@ -656,17 +657,19 @@ ENTRY(stack_segment) pushl $do_stack_segment jmp error_code -ENTRY(general_protection) +KPROBE_ENTRY(general_protection) pushl $do_general_protection jmp error_code + .previous .text ENTRY(alignment_check) pushl $do_alignment_check jmp error_code -ENTRY(page_fault) +KPROBE_ENTRY(page_fault) pushl $do_page_fault jmp error_code + .previous .text #ifdef CONFIG_X86_MCE ENTRY(machine_check) _ -- Prasanna S Panchamukhi Linux Technology Center India Software Labs, IBM Bangalore Ph: 91-80-25044636 <prasanna@in.ibm.com> ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [1/6 PATCH] Kprobes : Prevent possible race conditions generic changes 2005-07-07 10:10 [1/6 PATCH] Kprobes : Prevent possible race conditions generic changes Prasanna S Panchamukhi 2005-07-07 10:11 ` [2/6 PATCH] Kprobes : Prevent possible race conditions i386 changes Prasanna S Panchamukhi @ 2005-07-07 10:25 ` Andrew Morton 2005-07-07 10:34 ` Andi Kleen 1 sibling, 1 reply; 19+ messages in thread From: Andrew Morton @ 2005-07-07 10:25 UTC (permalink / raw) To: prasanna; +Cc: ak, davem, systemtap, linux-kernel Prasanna S Panchamukhi <prasanna@in.ibm.com> wrote: > > There are possible race conditions if probes are placed on routines within the > kprobes files and routines used by the kprobes. So... don't do that then? Is it likely that anyone would want to stick a probe on the kprobe code itself? > -kprobe_opcode_t *get_insn_slot(void) > +kprobe_opcode_t * __kprobes get_insn_slot(void) coding style regression... > -int register_kprobe(struct kprobe *p) > +static int __kprobes in_kprobes_functions(unsigned long addr) > +{ > + /* Linker adds these: start and end of __kprobes functions */ > + extern char __kprobes_text_start[], __kprobes_text_end[]; There's an old unix convention that section markers (start, end, edata, etc) are declared `int'. For some reason we don't do that in the kernel. Oh well. > + if ((ret = in_kprobes_functions((unsigned long) p->addr)) !=0) whitespace broke. Some people don't like the assign-then-test-it style. > + return ret; > if ((ret = arch_prepare_kprobe(p)) != 0) { > goto rm_kprobe; > } hm, who put the unneeded braces in there? > --- linux-2.6.13-rc1-mm1/include/linux/kprobes.h~kprobes-exclude-functions-generic 2005-07-06 18:51:16.000000000 +0530 > +++ linux-2.6.13-rc1-mm1-prasanna/include/linux/kprobes.h 2005-07-06 18:51:16.000000000 +0530 > @@ -42,6 +42,10 @@ > #define KPROBE_REENTER 0x00000004 > #define KPROBE_HIT_SSDONE 0x00000008 > > +/* Attach to insert probes on any functions which should be ignored*/ > +#define __kprobes __attribute__((__section__(".kprobes.text"))) > +/* Is this address in the __kprobes functions? */ > + What's that comment mean? ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [1/6 PATCH] Kprobes : Prevent possible race conditions generic changes 2005-07-07 10:25 ` [1/6 PATCH] Kprobes : Prevent possible race conditions generic changes Andrew Morton @ 2005-07-07 10:34 ` Andi Kleen 2005-07-07 13:01 ` Prasanna S Panchamukhi 2005-07-07 21:20 ` Vara Prasad 0 siblings, 2 replies; 19+ messages in thread From: Andi Kleen @ 2005-07-07 10:34 UTC (permalink / raw) To: Andrew Morton; +Cc: prasanna, ak, davem, systemtap, linux-kernel On Thu, Jul 07, 2005 at 03:25:37AM -0700, Andrew Morton wrote: > Prasanna S Panchamukhi <prasanna@in.ibm.com> wrote: > > > > There are possible race conditions if probes are placed on routines within the > > kprobes files and routines used by the kprobes. > > So... don't do that then? Is it likely that anyone would want to stick a > probe on the kprobe code itself? iirc one goal of systemtap (which uses kprobes) is to be provable safe so that an user cannot crash the kernel by adding probes. Basically to make it possible to use this on production systems safely. I have my doubts they will fully reach it, but at least it's a nice goal. > > -int register_kprobe(struct kprobe *p) > > +static int __kprobes in_kprobes_functions(unsigned long addr) > > +{ > > + /* Linker adds these: start and end of __kprobes functions */ > > + extern char __kprobes_text_start[], __kprobes_text_end[]; > > There's an old unix convention that section markers (start, end, edata, > etc) are declared `int'. For some reason we don't do that in the kernel. > Oh well. The Linux convention is to put it into asm-generic/sections.h at least. -Andi ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [1/6 PATCH] Kprobes : Prevent possible race conditions generic changes 2005-07-07 10:34 ` Andi Kleen @ 2005-07-07 13:01 ` Prasanna S Panchamukhi 2005-07-08 11:02 ` Prasanna S Panchamukhi 2005-07-07 21:20 ` Vara Prasad 1 sibling, 1 reply; 19+ messages in thread From: Prasanna S Panchamukhi @ 2005-07-07 13:01 UTC (permalink / raw) To: Andi Kleen; +Cc: Andrew Morton, davem, systemtap, linux-kernel Hi Andrew, I have modified the patch as per your comments. As Andi mentioned, this patch set provides safety for kprobes and avoids possible kernel crash I think this safety feature will helps tools like systemtap which are uses kprobes mechanism. Also kprobes cleanup patch to cleanup the codingstyle is on the way. Please let me know if you have any issues. Thanks Prasanna There are possible race conditions if probes are placed on routines within the kprobes files and routines used by the kprobes. For example if you put probe on get_kprobe() routines, the system can hang while inserting probes on any routine such as do_fork(). Because while inserting probes on do_fork(), register_kprobes() routine grabs the kprobes spin lock and executes get_kprobe() routine and to handle probe of get_kprobe(), kprobes_handler() gets executed and tries to grab kprobes spin lock, and spins forever. This patch avoids such possible race conditions by preventing probes on routines within the kprobes file and routines used by kprobes. Signed-off-by: Prasanna S Panchamukhi <prasanna@in.ibm.com> --- linux-2.6.13-rc1-mm1-prasanna/include/asm-generic/sections.h | 1 linux-2.6.13-rc1-mm1-prasanna/include/asm-generic/vmlinux.lds.h | 5 linux-2.6.13-rc1-mm1-prasanna/include/linux/kprobes.h | 3 linux-2.6.13-rc1-mm1-prasanna/kernel/kprobes.c | 72 +++++----- 4 files changed, 52 insertions(+), 29 deletions(-) diff -puN kernel/kprobes.c~kprobes-exclude-functions-generic kernel/kprobes.c --- linux-2.6.13-rc1-mm1/kernel/kprobes.c~kprobes-exclude-functions-generic 2005-07-07 17:13:26.000000000 +0530 +++ linux-2.6.13-rc1-mm1-prasanna/kernel/kprobes.c 2005-07-07 17:18:44.000000000 +0530 @@ -37,6 +37,7 @@ #include <linux/init.h> #include <linux/module.h> #include <linux/moduleloader.h> +#include <asm-generic/sections.h> #include <asm/cacheflush.h> #include <asm/errno.h> #include <asm/kdebug.h> @@ -72,7 +73,7 @@ static struct hlist_head kprobe_insn_pag * get_insn_slot() - Find a slot on an executable page for an instruction. * We allocate an executable page if there's no room on existing ones. */ -kprobe_opcode_t *get_insn_slot(void) +kprobe_opcode_t __kprobes *get_insn_slot(void) { struct kprobe_insn_page *kip; struct hlist_node *pos; @@ -117,7 +118,7 @@ kprobe_opcode_t *get_insn_slot(void) return kip->insns; } -void free_insn_slot(kprobe_opcode_t *slot) +void __kprobes free_insn_slot(kprobe_opcode_t *slot) { struct kprobe_insn_page *kip; struct hlist_node *pos; @@ -152,20 +153,20 @@ void free_insn_slot(kprobe_opcode_t *slo } /* Locks kprobe: irqs must be disabled */ -void lock_kprobes(void) +void __kprobes lock_kprobes(void) { spin_lock(&kprobe_lock); kprobe_cpu = smp_processor_id(); } -void unlock_kprobes(void) +void __kprobes unlock_kprobes(void) { kprobe_cpu = NR_CPUS; spin_unlock(&kprobe_lock); } /* You have to be holding the kprobe_lock */ -struct kprobe *get_kprobe(void *addr) +struct kprobe __kprobes *get_kprobe(void *addr) { struct hlist_head *head; struct hlist_node *node; @@ -183,7 +184,7 @@ struct kprobe *get_kprobe(void *addr) * Aggregate handlers for multiple kprobes support - these handlers * take care of invoking the individual kprobe handlers on p->list */ -static int aggr_pre_handler(struct kprobe *p, struct pt_regs *regs) +static int __kprobes aggr_pre_handler(struct kprobe *p, struct pt_regs *regs) { struct kprobe *kp; @@ -198,8 +199,8 @@ static int aggr_pre_handler(struct kprob return 0; } -static void aggr_post_handler(struct kprobe *p, struct pt_regs *regs, - unsigned long flags) +static void __kprobes aggr_post_handler(struct kprobe *p, struct pt_regs *regs, + unsigned long flags) { struct kprobe *kp; @@ -213,8 +214,8 @@ static void aggr_post_handler(struct kpr return; } -static int aggr_fault_handler(struct kprobe *p, struct pt_regs *regs, - int trapnr) +static int __kprobes aggr_fault_handler(struct kprobe *p, struct pt_regs *regs, + int trapnr) { /* * if we faulted "during" the execution of a user specified @@ -227,7 +228,7 @@ static int aggr_fault_handler(struct kpr return 0; } -static int aggr_break_handler(struct kprobe *p, struct pt_regs *regs) +static int __kprobes aggr_break_handler(struct kprobe *p, struct pt_regs *regs) { struct kprobe *kp = curr_kprobe; if (curr_kprobe && kp->break_handler) { @@ -240,7 +241,7 @@ static int aggr_break_handler(struct kpr return 0; } -struct kretprobe_instance *get_free_rp_inst(struct kretprobe *rp) +struct kretprobe_instance __kprobes *get_free_rp_inst(struct kretprobe *rp) { struct hlist_node *node; struct kretprobe_instance *ri; @@ -249,7 +250,8 @@ struct kretprobe_instance *get_free_rp_i return NULL; } -static struct kretprobe_instance *get_used_rp_inst(struct kretprobe *rp) +static struct kretprobe_instance __kprobes *get_used_rp_inst(struct kretprobe + *rp) { struct hlist_node *node; struct kretprobe_instance *ri; @@ -258,7 +260,7 @@ static struct kretprobe_instance *get_us return NULL; } -void add_rp_inst(struct kretprobe_instance *ri) +void __kprobes add_rp_inst(struct kretprobe_instance *ri) { /* * Remove rp inst off the free list - @@ -276,7 +278,7 @@ void add_rp_inst(struct kretprobe_instan hlist_add_head(&ri->uflist, &ri->rp->used_instances); } -void recycle_rp_inst(struct kretprobe_instance *ri) +void __kprobes recycle_rp_inst(struct kretprobe_instance *ri) { /* remove rp inst off the rprobe_inst_table */ hlist_del(&ri->hlist); @@ -291,7 +293,7 @@ void recycle_rp_inst(struct kretprobe_in kfree(ri); } -struct hlist_head * kretprobe_inst_table_head(struct task_struct *tsk) +struct hlist_head __kprobes *kretprobe_inst_table_head(struct task_struct *tsk) { return &kretprobe_inst_table[hash_ptr(tsk, KPROBE_HASH_BITS)]; } @@ -302,7 +304,7 @@ struct hlist_head * kretprobe_inst_table * instances associated with this task. These left over instances represent * probed functions that have been called but will never return. */ -void kprobe_flush_task(struct task_struct *tk) +void __kprobes kprobe_flush_task(struct task_struct *tk) { struct kretprobe_instance *ri; struct hlist_head *head; @@ -322,7 +324,8 @@ void kprobe_flush_task(struct task_struc * This kprobe pre_handler is registered with every kretprobe. When probe * hits it will set up the return probe. */ -static int pre_handler_kretprobe(struct kprobe *p, struct pt_regs *regs) +static int __kprobes pre_handler_kretprobe(struct kprobe *p, + struct pt_regs *regs) { struct kretprobe *rp = container_of(p, struct kretprobe, kp); @@ -353,7 +356,7 @@ static inline void copy_kprobe(struct kp * Add the new probe to old_p->list. Fail if this is the * second jprobe at the address - two jprobes can't coexist */ -static int add_new_kprobe(struct kprobe *old_p, struct kprobe *p) +static int __kprobes add_new_kprobe(struct kprobe *old_p, struct kprobe *p) { struct kprobe *kp; @@ -395,7 +398,8 @@ static inline void add_aggr_kprobe(struc * the intricacies * TODO: Move kcalloc outside the spinlock */ -static int register_aggr_kprobe(struct kprobe *old_p, struct kprobe *p) +static int __kprobes register_aggr_kprobe(struct kprobe *old_p, + struct kprobe *p) { int ret = 0; struct kprobe *ap; @@ -434,15 +438,25 @@ static inline void cleanup_aggr_kprobe(s spin_unlock_irqrestore(&kprobe_lock, flags); } -int register_kprobe(struct kprobe *p) +static int __kprobes in_kprobes_functions(unsigned long addr) +{ + if (addr >= (unsigned long)__kprobes_text_start + && addr < (unsigned long)__kprobes_text_end) + return -EINVAL; + return 0; +} + +int __kprobes register_kprobe(struct kprobe *p) { int ret = 0; unsigned long flags = 0; struct kprobe *old_p; - if ((ret = arch_prepare_kprobe(p)) != 0) { + if ((ret = in_kprobes_functions((unsigned long) p->addr)) != 0) + return ret; + if ((ret = arch_prepare_kprobe(p)) != 0) goto rm_kprobe; - } + spin_lock_irqsave(&kprobe_lock, flags); old_p = get_kprobe(p->addr); p->nmissed = 0; @@ -466,7 +480,7 @@ rm_kprobe: return ret; } -void unregister_kprobe(struct kprobe *p) +void __kprobes unregister_kprobe(struct kprobe *p) { unsigned long flags; struct kprobe *old_p; @@ -487,7 +501,7 @@ static struct notifier_block kprobe_exce .priority = 0x7fffffff /* we need to notified first */ }; -int register_jprobe(struct jprobe *jp) +int __kprobes register_jprobe(struct jprobe *jp) { /* Todo: Verify probepoint is a function entry point */ jp->kp.pre_handler = setjmp_pre_handler; @@ -496,14 +510,14 @@ int register_jprobe(struct jprobe *jp) return register_kprobe(&jp->kp); } -void unregister_jprobe(struct jprobe *jp) +void __kprobes unregister_jprobe(struct jprobe *jp) { unregister_kprobe(&jp->kp); } #ifdef ARCH_SUPPORTS_KRETPROBES -int register_kretprobe(struct kretprobe *rp) +int __kprobes register_kretprobe(struct kretprobe *rp) { int ret = 0; struct kretprobe_instance *inst; @@ -540,14 +554,14 @@ int register_kretprobe(struct kretprobe #else /* ARCH_SUPPORTS_KRETPROBES */ -int register_kretprobe(struct kretprobe *rp) +int __kprobes register_kretprobe(struct kretprobe *rp) { return -ENOSYS; } #endif /* ARCH_SUPPORTS_KRETPROBES */ -void unregister_kretprobe(struct kretprobe *rp) +void __kprobes unregister_kretprobe(struct kretprobe *rp) { unsigned long flags; struct kretprobe_instance *ri; diff -puN include/linux/kprobes.h~kprobes-exclude-functions-generic include/linux/kprobes.h --- linux-2.6.13-rc1-mm1/include/linux/kprobes.h~kprobes-exclude-functions-generic 2005-07-07 17:13:26.000000000 +0530 +++ linux-2.6.13-rc1-mm1-prasanna/include/linux/kprobes.h 2005-07-07 17:13:26.000000000 +0530 @@ -42,6 +42,9 @@ #define KPROBE_REENTER 0x00000004 #define KPROBE_HIT_SSDONE 0x00000008 +/* Attach to insert probes on any functions which should be ignored*/ +#define __kprobes __attribute__((__section__(".kprobes.text"))) + struct kprobe; struct pt_regs; struct kretprobe; diff -puN include/asm-generic/vmlinux.lds.h~kprobes-exclude-functions-generic include/asm-generic/vmlinux.lds.h --- linux-2.6.13-rc1-mm1/include/asm-generic/vmlinux.lds.h~kprobes-exclude-functions-generic 2005-07-07 17:13:26.000000000 +0530 +++ linux-2.6.13-rc1-mm1-prasanna/include/asm-generic/vmlinux.lds.h 2005-07-07 17:13:26.000000000 +0530 @@ -95,3 +95,8 @@ VMLINUX_SYMBOL(__lock_text_start) = .; \ *(.spinlock.text) \ VMLINUX_SYMBOL(__lock_text_end) = .; + +#define KPROBES_TEXT \ + VMLINUX_SYMBOL(__kprobes_text_start) = .; \ + *(.kprobes.text) \ + VMLINUX_SYMBOL(__kprobes_text_end) = .; diff -puN include/asm-generic/sections.h~kprobes-exclude-functions-generic include/asm-generic/sections.h --- linux-2.6.13-rc1-mm1/include/asm-generic/sections.h~kprobes-exclude-functions-generic 2005-07-07 17:13:26.000000000 +0530 +++ linux-2.6.13-rc1-mm1-prasanna/include/asm-generic/sections.h 2005-07-07 17:13:26.000000000 +0530 @@ -11,5 +11,6 @@ extern char _sinittext[], _einittext[]; extern char _sextratext[] __attribute__((weak)); extern char _eextratext[] __attribute__((weak)); extern char _end[]; +extern char __kprobes_text_start[], __kprobes_text_end[]; #endif /* _ASM_GENERIC_SECTIONS_H_ */ _ -- Prasanna S Panchamukhi Linux Technology Center India Software Labs, IBM Bangalore Ph: 91-80-25044636 <prasanna@in.ibm.com> ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [1/6 PATCH] Kprobes : Prevent possible race conditions generic changes 2005-07-07 13:01 ` Prasanna S Panchamukhi @ 2005-07-08 11:02 ` Prasanna S Panchamukhi 0 siblings, 0 replies; 19+ messages in thread From: Prasanna S Panchamukhi @ 2005-07-08 11:02 UTC (permalink / raw) To: Andi Kleen; +Cc: Andrew Morton, davem, systemtap, linux-kernel Hi Andrew, I have modified the patches as per your's and Andi's comments. Also modified entry.S for i386 and x86_64 architecture, to move few exception handlers page fault, general protection, int3, debug to .kprobes.text section. Also ia64 specific patch contains more routines from jprobes.S file as per Anil's comment. Please let me know if you have any issues. Thanks Prasanna There are possible race conditions if probes are placed on routines within the kprobes files and routines used by the kprobes. For example if you put probe on get_kprobe() routines, the system can hang while inserting probes on any routine such as do_fork(). Because while inserting probes on do_fork(), register_kprobes() routine grabs the kprobes spin lock and executes get_kprobe() routine and to handle probe of get_kprobe(), kprobes_handler() gets executed and tries to grab kprobes spin lock, and spins forever. This patch avoids such possible race conditions by preventing probes on routines within the kprobes file and routines used by kprobes. I have modified the patches as per Andi Kleen's suggestion to move kprobes routines and other routines used by kprobes to a seperate section .kprobes.text. Also moved page fault and exception handlers, general protection fault to .kprobes.text section. These patches have been tested on i386, x86_64 and ppc64 architectures, also compiled on ia64 and sparc64 architectures. Signed-off-by: Prasanna S Panchamukhi <prasanna@in.ibm.com> --- linux-2.6.13-rc1-mm1-prasanna/include/asm-generic/sections.h | 1 linux-2.6.13-rc1-mm1-prasanna/include/asm-generic/vmlinux.lds.h | 5 linux-2.6.13-rc1-mm1-prasanna/include/linux/kprobes.h | 3 linux-2.6.13-rc1-mm1-prasanna/include/linux/linkage.h | 7 linux-2.6.13-rc1-mm1-prasanna/kernel/kprobes.c | 72 +++++----- 5 files changed, 59 insertions(+), 29 deletions(-) diff -puN kernel/kprobes.c~kprobes-exclude-functions-generic kernel/kprobes.c --- linux-2.6.13-rc1-mm1/kernel/kprobes.c~kprobes-exclude-functions-generic 2005-07-08 14:05:14.000000000 +0530 +++ linux-2.6.13-rc1-mm1-prasanna/kernel/kprobes.c 2005-07-08 14:05:14.000000000 +0530 @@ -37,6 +37,7 @@ #include <linux/init.h> #include <linux/module.h> #include <linux/moduleloader.h> +#include <asm-generic/sections.h> #include <asm/cacheflush.h> #include <asm/errno.h> #include <asm/kdebug.h> @@ -72,7 +73,7 @@ static struct hlist_head kprobe_insn_pag * get_insn_slot() - Find a slot on an executable page for an instruction. * We allocate an executable page if there's no room on existing ones. */ -kprobe_opcode_t *get_insn_slot(void) +kprobe_opcode_t __kprobes *get_insn_slot(void) { struct kprobe_insn_page *kip; struct hlist_node *pos; @@ -117,7 +118,7 @@ kprobe_opcode_t *get_insn_slot(void) return kip->insns; } -void free_insn_slot(kprobe_opcode_t *slot) +void __kprobes free_insn_slot(kprobe_opcode_t *slot) { struct kprobe_insn_page *kip; struct hlist_node *pos; @@ -152,20 +153,20 @@ void free_insn_slot(kprobe_opcode_t *slo } /* Locks kprobe: irqs must be disabled */ -void lock_kprobes(void) +void __kprobes lock_kprobes(void) { spin_lock(&kprobe_lock); kprobe_cpu = smp_processor_id(); } -void unlock_kprobes(void) +void __kprobes unlock_kprobes(void) { kprobe_cpu = NR_CPUS; spin_unlock(&kprobe_lock); } /* You have to be holding the kprobe_lock */ -struct kprobe *get_kprobe(void *addr) +struct kprobe __kprobes *get_kprobe(void *addr) { struct hlist_head *head; struct hlist_node *node; @@ -183,7 +184,7 @@ struct kprobe *get_kprobe(void *addr) * Aggregate handlers for multiple kprobes support - these handlers * take care of invoking the individual kprobe handlers on p->list */ -static int aggr_pre_handler(struct kprobe *p, struct pt_regs *regs) +static int __kprobes aggr_pre_handler(struct kprobe *p, struct pt_regs *regs) { struct kprobe *kp; @@ -198,8 +199,8 @@ static int aggr_pre_handler(struct kprob return 0; } -static void aggr_post_handler(struct kprobe *p, struct pt_regs *regs, - unsigned long flags) +static void __kprobes aggr_post_handler(struct kprobe *p, struct pt_regs *regs, + unsigned long flags) { struct kprobe *kp; @@ -213,8 +214,8 @@ static void aggr_post_handler(struct kpr return; } -static int aggr_fault_handler(struct kprobe *p, struct pt_regs *regs, - int trapnr) +static int __kprobes aggr_fault_handler(struct kprobe *p, struct pt_regs *regs, + int trapnr) { /* * if we faulted "during" the execution of a user specified @@ -227,7 +228,7 @@ static int aggr_fault_handler(struct kpr return 0; } -static int aggr_break_handler(struct kprobe *p, struct pt_regs *regs) +static int __kprobes aggr_break_handler(struct kprobe *p, struct pt_regs *regs) { struct kprobe *kp = curr_kprobe; if (curr_kprobe && kp->break_handler) { @@ -240,7 +241,7 @@ static int aggr_break_handler(struct kpr return 0; } -struct kretprobe_instance *get_free_rp_inst(struct kretprobe *rp) +struct kretprobe_instance __kprobes *get_free_rp_inst(struct kretprobe *rp) { struct hlist_node *node; struct kretprobe_instance *ri; @@ -249,7 +250,8 @@ struct kretprobe_instance *get_free_rp_i return NULL; } -static struct kretprobe_instance *get_used_rp_inst(struct kretprobe *rp) +static struct kretprobe_instance __kprobes *get_used_rp_inst(struct kretprobe + *rp) { struct hlist_node *node; struct kretprobe_instance *ri; @@ -258,7 +260,7 @@ static struct kretprobe_instance *get_us return NULL; } -void add_rp_inst(struct kretprobe_instance *ri) +void __kprobes add_rp_inst(struct kretprobe_instance *ri) { /* * Remove rp inst off the free list - @@ -276,7 +278,7 @@ void add_rp_inst(struct kretprobe_instan hlist_add_head(&ri->uflist, &ri->rp->used_instances); } -void recycle_rp_inst(struct kretprobe_instance *ri) +void __kprobes recycle_rp_inst(struct kretprobe_instance *ri) { /* remove rp inst off the rprobe_inst_table */ hlist_del(&ri->hlist); @@ -291,7 +293,7 @@ void recycle_rp_inst(struct kretprobe_in kfree(ri); } -struct hlist_head * kretprobe_inst_table_head(struct task_struct *tsk) +struct hlist_head __kprobes *kretprobe_inst_table_head(struct task_struct *tsk) { return &kretprobe_inst_table[hash_ptr(tsk, KPROBE_HASH_BITS)]; } @@ -302,7 +304,7 @@ struct hlist_head * kretprobe_inst_table * instances associated with this task. These left over instances represent * probed functions that have been called but will never return. */ -void kprobe_flush_task(struct task_struct *tk) +void __kprobes kprobe_flush_task(struct task_struct *tk) { struct kretprobe_instance *ri; struct hlist_head *head; @@ -322,7 +324,8 @@ void kprobe_flush_task(struct task_struc * This kprobe pre_handler is registered with every kretprobe. When probe * hits it will set up the return probe. */ -static int pre_handler_kretprobe(struct kprobe *p, struct pt_regs *regs) +static int __kprobes pre_handler_kretprobe(struct kprobe *p, + struct pt_regs *regs) { struct kretprobe *rp = container_of(p, struct kretprobe, kp); @@ -353,7 +356,7 @@ static inline void copy_kprobe(struct kp * Add the new probe to old_p->list. Fail if this is the * second jprobe at the address - two jprobes can't coexist */ -static int add_new_kprobe(struct kprobe *old_p, struct kprobe *p) +static int __kprobes add_new_kprobe(struct kprobe *old_p, struct kprobe *p) { struct kprobe *kp; @@ -395,7 +398,8 @@ static inline void add_aggr_kprobe(struc * the intricacies * TODO: Move kcalloc outside the spinlock */ -static int register_aggr_kprobe(struct kprobe *old_p, struct kprobe *p) +static int __kprobes register_aggr_kprobe(struct kprobe *old_p, + struct kprobe *p) { int ret = 0; struct kprobe *ap; @@ -434,15 +438,25 @@ static inline void cleanup_aggr_kprobe(s spin_unlock_irqrestore(&kprobe_lock, flags); } -int register_kprobe(struct kprobe *p) +static int __kprobes in_kprobes_functions(unsigned long addr) +{ + if (addr >= (unsigned long)__kprobes_text_start + && addr < (unsigned long)__kprobes_text_end) + return -EINVAL; + return 0; +} + +int __kprobes register_kprobe(struct kprobe *p) { int ret = 0; unsigned long flags = 0; struct kprobe *old_p; - if ((ret = arch_prepare_kprobe(p)) != 0) { + if ((ret = in_kprobes_functions((unsigned long) p->addr)) != 0) + return ret; + if ((ret = arch_prepare_kprobe(p)) != 0) goto rm_kprobe; - } + spin_lock_irqsave(&kprobe_lock, flags); old_p = get_kprobe(p->addr); p->nmissed = 0; @@ -466,7 +480,7 @@ rm_kprobe: return ret; } -void unregister_kprobe(struct kprobe *p) +void __kprobes unregister_kprobe(struct kprobe *p) { unsigned long flags; struct kprobe *old_p; @@ -487,7 +501,7 @@ static struct notifier_block kprobe_exce .priority = 0x7fffffff /* we need to notified first */ }; -int register_jprobe(struct jprobe *jp) +int __kprobes register_jprobe(struct jprobe *jp) { /* Todo: Verify probepoint is a function entry point */ jp->kp.pre_handler = setjmp_pre_handler; @@ -496,14 +510,14 @@ int register_jprobe(struct jprobe *jp) return register_kprobe(&jp->kp); } -void unregister_jprobe(struct jprobe *jp) +void __kprobes unregister_jprobe(struct jprobe *jp) { unregister_kprobe(&jp->kp); } #ifdef ARCH_SUPPORTS_KRETPROBES -int register_kretprobe(struct kretprobe *rp) +int __kprobes register_kretprobe(struct kretprobe *rp) { int ret = 0; struct kretprobe_instance *inst; @@ -540,14 +554,14 @@ int register_kretprobe(struct kretprobe #else /* ARCH_SUPPORTS_KRETPROBES */ -int register_kretprobe(struct kretprobe *rp) +int __kprobes register_kretprobe(struct kretprobe *rp) { return -ENOSYS; } #endif /* ARCH_SUPPORTS_KRETPROBES */ -void unregister_kretprobe(struct kretprobe *rp) +void __kprobes unregister_kretprobe(struct kretprobe *rp) { unsigned long flags; struct kretprobe_instance *ri; diff -puN include/linux/kprobes.h~kprobes-exclude-functions-generic include/linux/kprobes.h --- linux-2.6.13-rc1-mm1/include/linux/kprobes.h~kprobes-exclude-functions-generic 2005-07-08 14:05:14.000000000 +0530 +++ linux-2.6.13-rc1-mm1-prasanna/include/linux/kprobes.h 2005-07-08 14:05:14.000000000 +0530 @@ -42,6 +42,9 @@ #define KPROBE_REENTER 0x00000004 #define KPROBE_HIT_SSDONE 0x00000008 +/* Attach to insert probes on any functions which should be ignored*/ +#define __kprobes __attribute__((__section__(".kprobes.text"))) + struct kprobe; struct pt_regs; struct kretprobe; diff -puN include/asm-generic/vmlinux.lds.h~kprobes-exclude-functions-generic include/asm-generic/vmlinux.lds.h --- linux-2.6.13-rc1-mm1/include/asm-generic/vmlinux.lds.h~kprobes-exclude-functions-generic 2005-07-08 14:05:14.000000000 +0530 +++ linux-2.6.13-rc1-mm1-prasanna/include/asm-generic/vmlinux.lds.h 2005-07-08 14:05:14.000000000 +0530 @@ -95,3 +95,8 @@ VMLINUX_SYMBOL(__lock_text_start) = .; \ *(.spinlock.text) \ VMLINUX_SYMBOL(__lock_text_end) = .; + +#define KPROBES_TEXT \ + VMLINUX_SYMBOL(__kprobes_text_start) = .; \ + *(.kprobes.text) \ + VMLINUX_SYMBOL(__kprobes_text_end) = .; diff -puN include/asm-generic/sections.h~kprobes-exclude-functions-generic include/asm-generic/sections.h --- linux-2.6.13-rc1-mm1/include/asm-generic/sections.h~kprobes-exclude-functions-generic 2005-07-08 14:05:14.000000000 +0530 +++ linux-2.6.13-rc1-mm1-prasanna/include/asm-generic/sections.h 2005-07-08 14:05:14.000000000 +0530 @@ -11,5 +11,6 @@ extern char _sinittext[], _einittext[]; extern char _sextratext[] __attribute__((weak)); extern char _eextratext[] __attribute__((weak)); extern char _end[]; +extern char __kprobes_text_start[], __kprobes_text_end[]; #endif /* _ASM_GENERIC_SECTIONS_H_ */ diff -puN arch/i386/kernel/entry.S~kprobes-exclude-functions-generic arch/i386/kernel/entry.S diff -puN include/linux/linkage.h~kprobes-exclude-functions-generic include/linux/linkage.h --- linux-2.6.13-rc1-mm1/include/linux/linkage.h~kprobes-exclude-functions-generic 2005-07-08 14:05:14.000000000 +0530 +++ linux-2.6.13-rc1-mm1-prasanna/include/linux/linkage.h 2005-07-08 14:05:27.000000000 +0530 @@ -33,6 +33,13 @@ ALIGN; \ name: +#define KPROBE_ENTRY(name) \ + .section .kprobes.text, "ax"; \ + .globl name; \ + ALIGN; \ + name: + + #endif #define NORET_TYPE /**/ _ -- Prasanna S Panchamukhi Linux Technology Center India Software Labs, IBM Bangalore Ph: 91-80-25044636 <prasanna@in.ibm.com> ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [1/6 PATCH] Kprobes : Prevent possible race conditions generic changes 2005-07-07 10:34 ` Andi Kleen 2005-07-07 13:01 ` Prasanna S Panchamukhi @ 2005-07-07 21:20 ` Vara Prasad 1 sibling, 0 replies; 19+ messages in thread From: Vara Prasad @ 2005-07-07 21:20 UTC (permalink / raw) To: Andi Kleen; +Cc: Andrew Morton, prasanna, davem, systemtap, linux-kernel Andi Kleen wrote: >On Thu, Jul 07, 2005 at 03:25:37AM -0700, Andrew Morton wrote: > > >>Prasanna S Panchamukhi <prasanna@in.ibm.com> wrote: >> >> >>>There are possible race conditions if probes are placed on routines within the >>>kprobes files and routines used by the kprobes. >>> >>> >>So... don't do that then? Is it likely that anyone would want to stick a >>probe on the kprobe code itself? >> >> > >iirc one goal of systemtap (which uses kprobes) is to be provable >safe so that an user cannot crash the kernel by adding probes. Basically >to make it possible to use this on production systems safely. I have my >doubts they will fully reach it, but at least it's a nice goal. > > Yes, you are right it is a lofty goal but we feel we can achieve this with safety features built into the system. To facilitate this we are providing two modes safe and guru. In safe mode we are trying to limit the user to do limited yet useful operations so that they don't compromise the integrity of the system. Guru mode is meant for power users where we expect the users to know what they are doing hence they can do more intrusive operations. Another feature we are doing is coming up with a library of routines for common needs. Users can activate these routines with a simple scripting language so that they don't write their own kernel modules, this limits their ability to compromise the integrity of the system. We expect users to use this method predominantly in the safe mode. > > >>>-int register_kprobe(struct kprobe *p) >>>+static int __kprobes in_kprobes_functions(unsigned long addr) >>>+{ >>>+ /* Linker adds these: start and end of __kprobes functions */ >>>+ extern char __kprobes_text_start[], __kprobes_text_end[]; >>> >>> >>There's an old unix convention that section markers (start, end, edata, >>etc) are declared `int'. For some reason we don't do that in the kernel. >>Oh well. >> >> > >The Linux convention is to put it into asm-generic/sections.h at least. > >-Andi > > > ^ permalink raw reply [flat|nested] 19+ messages in thread
end of thread, other threads:[~2005-07-08 19:20 UTC | newest] Thread overview: 19+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2005-07-07 10:10 [1/6 PATCH] Kprobes : Prevent possible race conditions generic changes Prasanna S Panchamukhi 2005-07-07 10:11 ` [2/6 PATCH] Kprobes : Prevent possible race conditions i386 changes Prasanna S Panchamukhi 2005-07-07 10:14 ` [3/6 PATCH] Kprobes : Prevent possible race conditions x86_64 changes Prasanna S Panchamukhi 2005-07-07 10:16 ` [4/6 PATCH] Kprobes : Prevent possible race conditions ppc64 changes Prasanna S Panchamukhi 2005-07-07 10:18 ` [5/6 PATCH] Kprobes : Prevent possible race conditions ia64 changes Prasanna S Panchamukhi 2005-07-07 10:20 ` [6/6 PATCH] Kprobes : Prevent possible race conditions sparc64 changes Prasanna S Panchamukhi 2005-07-08 2:06 ` [5/6 PATCH] Kprobes : Prevent possible race conditions ia64 changes Keshavamurthy Anil S 2005-07-08 11:10 ` Prasanna S Panchamukhi 2005-07-08 19:01 ` Keshavamurthy Anil S 2005-07-08 19:16 ` Prarit Bhargava 2005-07-08 14:13 ` [4/6 PATCH] Kprobes : Prevent possible race conditions ppc64 changes Ananth N Mavinakayanahalli 2005-07-08 11:07 ` [3/6 PATCH] Kprobes : Prevent possible race conditions x86_64 changes Prasanna S Panchamukhi 2005-07-07 13:19 ` [2/6 PATCH] Kprobes : Prevent possible race conditions i386 changes Andi Kleen 2005-07-08 11:05 ` Prasanna S Panchamukhi 2005-07-07 10:25 ` [1/6 PATCH] Kprobes : Prevent possible race conditions generic changes Andrew Morton 2005-07-07 10:34 ` Andi Kleen 2005-07-07 13:01 ` Prasanna S Panchamukhi 2005-07-08 11:02 ` Prasanna S Panchamukhi 2005-07-07 21:20 ` Vara Prasad
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox