This is the mail archive of the systemtap@sourceware.org mailing list for the systemtap project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [RFC PATCH 2/3] Djprobe improvement patches (Re: Dynamic djprobe)


Hi, Mathieu

Mathieu Desnoyers wrote:
If the stack inspection becomes considered too costy (push/pop at each interrupt
entry/exit) or too uncertain (looking at all the stack's data),

I developed a patch to check in the entire stack's data. It is attached in this mail.


I would suggest
a different approach for this interruption problem :

1 - Replace the first byte of the segment you want to modify with a int3
2 - Wait until each other CPU has reach a point where we know they are not in
    interrupt context anymore (interrupt or softirq). This could be done by
    spawning a kernel thread on each CPU which would inform us when it runs. If
    there is no kernel preemption, then we are sure there is no interruption
    having a wrong EIP saved on its stack.
3 - Write the jmp instruction.


In a context where there is no preemption, this should work.

It seems a good idea! Can I use a workqueue instead of a kernel thread?


Thanks.

Best regards,

--
Masami HIRAMATSU
2nd Research Dept.
Hitachi, Ltd., Systems Development Laboratory
E-mail: hiramatu@sdl.hitachi.co.jp

diff -Narup linux-2.6.12-djprobe.2/arch/i386/kernel/kprobes.c linux-2.6.12-djprobe.3/arch/i386/kernel/kprobes.c
--- linux-2.6.12-djprobe.2/arch/i386/kernel/kprobes.c	2005-08-01 22:00:17.000000000 +0900
+++ linux-2.6.12-djprobe.3/arch/i386/kernel/kprobes.c	2005-08-03 01:26:46.000000000 +0900
@@ -472,6 +472,26 @@ int arch_prepare_djprobe_instance(struct
 	return 0;
 }
 
+int arch_find_region_from_stack(unsigned long saddr, unsigned long eaddr)
+{
+	unsigned long * esp, *p;
+	struct pt_regs *pr_tmp;
+	esp = (unsigned long *)current_stack_pointer;
+	p = current_thread_info() + (THREAD_SIZE - 1) 
+	    - sizeof(struct pt_regs);
+	for (;p > esp; p--) { 
+		pr_tmp = (struct pt_regs *)p;
+		if (pr_tmp->xcs == __KERNEL_CS &&
+		    pr_tmp->xds == __KERNEL_DS) {
+			if (saddr < pr_tmp->eip &&
+			    pr_tmp->eip <= eaddr ){
+				return 1; //found
+			}
+		}
+	}
+	return 0;//not found
+}
+
 /* Insert "jmp" instruction into the probing point. */
 static void arch_install_djprobe_instance(struct djprobe_instance *djpi)
 {
@@ -497,7 +517,7 @@ int djprobe_bypass_handler(struct kprobe
 	kprobe_opcode_t *stub = djpi->stub.insn;
 	int cpu = smp_processor_id();
 
-	if (!DJPI_CHECKED(djpi)) {
+	if (!DJPI_CHECKED(djpi) && check_safety_djprobe_instance(djpi)) {
 		cpu_set(cpu, djpi->checked_cpus); /* check this cpu */
 		
 		if (DJPI_CHECKED(djpi)) { /* all cpus are checked */
diff -Narup linux-2.6.12-djprobe.2/include/linux/kprobes.h linux-2.6.12-djprobe.3/include/linux/kprobes.h
--- linux-2.6.12-djprobe.2/include/linux/kprobes.h	2005-08-02 20:29:44.000000000 +0900
+++ linux-2.6.12-djprobe.3/include/linux/kprobes.h	2005-08-03 01:29:19.000000000 +0900
@@ -155,7 +155,9 @@ extern int arch_prepare_djprobe_instance
 extern int djprobe_bypass_handler(struct kprobe * kp, struct pt_regs * regs);
 extern void arch_uninstall_djprobe_instance(struct djprobe_instance *djpi);
 extern void schdule_release_djprobe_instance(void);
-
+extern int check_safety_djprobe_instance(struct djprobe_instance *djpi);
+extern int arch_find_region_from_stack(unsigned long saddr, unsigned long eaddr);
+
 int register_djprobe(struct djprobe *p);
 void unregister_djprobe(struct djprobe *p);
 #else
diff -Narup linux-2.6.12-djprobe.2/kernel/kprobes.c linux-2.6.12-djprobe.3/kernel/kprobes.c
--- linux-2.6.12-djprobe.2/kernel/kprobes.c	2005-08-01 22:00:17.000000000 +0900
+++ linux-2.6.12-djprobe.3/kernel/kprobes.c	2005-08-03 01:32:01.000000000 +0900
@@ -269,6 +269,19 @@ static DEFINE_SPINLOCK(djprobe_lock);
 static LIST_HEAD(djprobe_list);
 static int nr_instances = 0;
 
+/* safety check routine */
+int check_safety_djprobe_instance(struct djprobe_instance *djpi)
+{
+	int sp;
+	preempt_disable();
+	if(arch_find_region_from_stack((unsigned long)djpi->kp.addr,
+				       (unsigned long)djpi->kp.addr
+				       + djpi->stub.size))
+		return 0; /*we find insertion address in the stack*/ 
+	preempt_enable();
+	return 1;
+}
+
 static void work_free_djprobe_instances(void *data)
 {
 	struct list_head *pos;

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]