Skip to contentSkip to conversation

FInal kprobes rollup patches

PATCH New Harvey Harrison 4 participants 23 messages Dec 15, 2007 – Dec 18, 2007 x86

lore
Share & tools
lore
#0 lore raw
Quoted 1 line

From f87fb3155500f85ffbafc01d6f5b8dc2a3f6184c Mon Sep 17 00:00:00 2001

From: Harvey Harrison <[email protected]>
Date: Fri, 14 Dec 2007 22:02:51 -0800
Subject: [PATCH] [RFC] x86: kprobes unification

Further unification work. There is a possible behavior change on X86_32 here.

is_IF_modifier(p->opcode)

to

is_IF_modifier(p->ainsn.insn)

Which should be equivalent, but is not purely cosmetic as the rest of the unification so far.

---
 arch/x86/kernel/kprobes_32.c |   43 +++++++++++++++++++++--------
 arch/x86/kernel/kprobes_64.c |   60 +++++++++++++++++++++++++++++++++++-------
 2 files changed, 81 insertions(+), 22 deletions(-)
arch/x86/kernel/kprobes_32.c +31 -12
index 878b0c4..21ac86f 100644
@@ -220,15 +220,21 @@ retry:
 /*
  * returns non-zero if opcode modifies the interrupt flag.
  */
-static int __kprobes is_IF_modifier(kprobe_opcode_t opcode)
+static int __kprobes is_IF_modifier(kprobe_opcode_t *insn)
 {
-	switch (opcode) {
+	switch (*insn) {
 	case 0xfa:		/* cli */
 	case 0xfb:		/* sti */
 	case 0xcf:		/* iret/iretd */
 	case 0x9d:		/* popf/popfd */
 		return 1;
 	}
+
+#ifdef CONFIG_X86_64
+	/* REX prefix */
+	if (*insn  >= 0x40 && *insn <= 0x4f && *++insn == 0xcf)
+		return 1;
+#endif
 	return 0;
 }
 
@@ -370,7 +376,7 @@ static void __kprobes set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
 	__get_cpu_var(current_kprobe) = p;
 	kcb->kprobe_saved_flags = kcb->kprobe_old_flags
 		= (regs->flags & (TF_MASK | IF_MASK));
-	if (is_IF_modifier(p->opcode))
+	if (is_IF_modifier(p->ainsn.insn))
 		kcb->kprobe_saved_flags &= ~IF_MASK;
 }
 
@@ -410,10 +416,9 @@ static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
 void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri,
 				      struct pt_regs *regs)
 {
-	unsigned long *sara = (unsigned long *)&regs->sp;
+	unsigned long *sara = &regs->sp;
 
 	ri->ret_addr = (kprobe_opcode_t *) *sara;
-
 	/* Replace the return addr with trampoline addr */
 	*sara = (unsigned long) &kretprobe_trampoline;
 }
@@ -528,8 +533,9 @@ no_kprobe:
  * here. When a retprobed function returns, this probe is hit and
  * trampoline_probe_handler() runs, calling the kretprobe's handler.
  */
- void __kprobes kretprobe_trampoline_holder(void)
- {
+void __kprobes kretprobe_trampoline_holder(void)
+{
+#ifdef CONFIG_X86_32
 	asm volatile ( ".global kretprobe_trampoline\n"
 			"kretprobe_trampoline: \n"
 			"	pushf\n"
@@ -563,6 +569,11 @@ no_kprobe:
 			"	addl $20, %esp\n"
 			"	popf\n"
 			"	ret\n");
+#else
+	asm volatile (  ".global kretprobe_trampoline\n"
+			"kretprobe_trampoline: \n"
+			"nop\n");
+#endif
 }
 
 /*
@@ -658,12 +669,20 @@ void *__kprobes trampoline_handler(struct pt_regs *regs)
 static void __kprobes resume_execution(struct kprobe *p,
 		struct pt_regs *regs, struct kprobe_ctlblk *kcb)
 {
-	unsigned long *tos = (unsigned long *)&regs->sp;
+	unsigned long *tos = &regs->sp;
+	unsigned long next_rip = 0;
 	unsigned long copy_ip = (unsigned long)p->ainsn.insn;
 	unsigned long orig_ip = (unsigned long)p->addr;
+	kprobe_opcode_t *insn = p->ainsn.insn;
+
+#ifdef CONFIG_X86_64
+	/*skip the REX prefix*/
+	if (*insn >= 0x40 && *insn <= 0x4f)
+		insn++;
+#endif
 
 	regs->flags &= ~TF_MASK;
-	switch (p->ainsn.insn[0]) {
+	switch (*insn) {
 	case 0x9c:		/* pushfl */
 		*tos &= ~(TF_MASK | IF_MASK);
 		*tos |= kcb->kprobe_old_flags;
@@ -684,7 +703,7 @@ static void __kprobes resume_execution(struct kprobe *p,
 		*tos = orig_ip + (*tos - copy_ip);
 		goto no_change;
 	case 0xff:
-		if ((p->ainsn.insn[1] & 0x30) == 0x10) {
+		if ((insn[1] & 0x30) == 0x10) {
 			/*
 			 * call absolute, indirect
 			 * Fix return addr; ip is correct.
@@ -692,8 +711,8 @@ static void __kprobes resume_execution(struct kprobe *p,
 			 */
 			*tos = orig_ip + (*tos - copy_ip);
 			goto no_change;
-		} else if (((p->ainsn.insn[1] & 0x31) == 0x20) ||	/* jmp near, absolute indirect */
-			   ((p->ainsn.insn[1] & 0x31) == 0x21)) {	/* jmp far, absolute indirect */
+		} else if (((insn[1] & 0x31) == 0x20) ||	/* jmp near, absolute indirect */
+			   ((insn[1] & 0x31) == 0x21)) {	/* jmp far, absolute indirect */
 			/* ip is correct. And this is boostable */
 			p->ainsn.boostable = 1;
 			goto no_change;
arch/x86/kernel/kprobes_64.c +50 -10

107 lines not on this page · raw message

Signature · 1 line
1.5.4.rc0.1083.gf568
Quoted 1 line

From 4a048bf0c67558b8170dcde7c8395f6c35592f0b Mon Sep 17 00:00:00 2001

From: Harvey Harrison <[email protected]>
Date: Fri, 14 Dec 2007 22:52:44 -0800
Subject: [PATCH] x86: Move some exception fixup logic in kprobes_{32|64}.c

---
 arch/x86/kernel/kprobes_32.c |   21 ++++++++++++++++++---
 arch/x86/kernel/kprobes_64.c |   21 ++++++++++++++++-----
 2 files changed, 34 insertions(+), 8 deletions(-)
arch/x86/kernel/kprobes_32.c +18 -3
index 21ac86f..a2b5ca7 100644
@@ -533,7 +533,7 @@ no_kprobe:
  * here. When a retprobed function returns, this probe is hit and
  * trampoline_probe_handler() runs, calling the kretprobe's handler.
  */
-void __kprobes kretprobe_trampoline_holder(void)
+void kretprobe_trampoline_holder(void)
 {
 #ifdef CONFIG_X86_32
 	asm volatile ( ".global kretprobe_trampoline\n"
@@ -787,6 +787,9 @@ int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
 {
 	struct kprobe *cur = kprobe_running();
 	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+#ifdef CONFIG_X86_64
+	const struct exception_table_entry *fixup;
+#endif
 
 	switch(kcb->kprobe_status) {
 	case KPROBE_HIT_SS:
@@ -829,11 +832,18 @@ int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
 		 * In case the user-specified fault handler returned
 		 * zero, try to fix up.
 		 */
+#ifdef CONFIG_X86_32
 		if (fixup_exception(regs))
 			return 1;
-
+#else
+		fixup = search_exception_tables(regs->ip);
+		if (fixup) {
+			regs->ip = fixup->fixup;
+			return 1;
+		}
+#endif
 		/*
-		 * fixup_exception() could not handle it,
+		 * Exception couldn't be fixed up,
 		 * Let do_page_fault() fix it.
 		 */
 		break;
@@ -852,8 +862,13 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
 	struct die_args *args = (struct die_args *)data;
 	int ret = NOTIFY_DONE;
 
+#ifdef CONFIG_X86_32
 	if (args->regs && user_mode_vm(args->regs))
 		return ret;
+#else
+	if (args->regs && user_mode(args->regs))
+		return ret;
+#endif
 
 	switch (val) {
 	case DIE_INT3:
arch/x86/kernel/kprobes_64.c +16 -5
index 9bf6ebe..705cb99 100644
@@ -769,7 +769,9 @@ int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
 {
 	struct kprobe *cur = kprobe_running();
 	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+#ifdef CONFIG_X86_64
 	const struct exception_table_entry *fixup;
+#endif
 
 	switch(kcb->kprobe_status) {
 	case KPROBE_HIT_SS:
@@ -812,14 +814,18 @@ int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
 		 * In case the user-specified fault handler returned
 		 * zero, try to fix up.
 		 */
+#ifdef CONFIG_X86_32
+		if (fixup_exception(regs))
+			return 1;
+#else
 		fixup = search_exception_tables(regs->ip);
 		if (fixup) {
 			regs->ip = fixup->fixup;
 			return 1;
 		}
-
+#endif
 		/*
-		 * fixup() could not handle it,
+		 * Exception couldn't be fixed up,
 		 * Let do_page_fault() fix it.
 		 */
 		break;
@@ -838,8 +844,13 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
 	struct die_args *args = (struct die_args *)data;
 	int ret = NOTIFY_DONE;
 
+#ifdef CONFIG_X86_32
+	if (args->regs && user_mode_vm(args->regs))
+		return ret;
+#else
 	if (args->regs && user_mode(args->regs))
 		return ret;
+#endif
 
 	switch (val) {
 	case DIE_INT3:
@@ -871,7 +882,7 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
 	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
 
 	kcb->jprobe_saved_regs = *regs;
-	kcb->jprobe_saved_sp = (long *) regs->sp;
+	kcb->jprobe_saved_sp = &regs->sp;
 	addr = (unsigned long)(kcb->jprobe_saved_sp);
 	/*
 	 * As Linus pointed out, gcc assumes that the callee
@@ -916,12 +927,12 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
 	struct jprobe *jp = container_of(p, struct jprobe, kp);
 
 	if ((addr > (u8 *) jprobe_return) && (addr < (u8 *) jprobe_return_end)) {
-		if ((long *)regs->sp != kcb->jprobe_saved_sp) {
+		if (&regs->sp != kcb->jprobe_saved_sp) {
 			struct pt_regs *saved_regs =
 			    container_of(kcb->jprobe_saved_sp,
 					    struct pt_regs, sp);
 			printk("current sp %p does not match saved sp %p\n",
-			       (long *)regs->sp, kcb->jprobe_saved_sp);
+			       &regs->sp, kcb->jprobe_saved_sp);
 			printk("Saved registers for jprobe %p\n", jp);
 			show_registers(saved_regs);
 			printk("Current registers\n");
Signature · 1 line
1.5.4.rc0.1083.gf568
Quoted 1 line

From 83fde2864abcc34ef8bc575a22b5f8e76477b64b Mon Sep 17 00:00:00 2001

From: Harvey Harrison <[email protected]>
Date: Fri, 14 Dec 2007 22:56:50 -0800
Subject: [PATCH] x86: Duplicate some instruction IP logic

---
 arch/x86/kernel/kprobes_32.c |    8 ++++++++
 arch/x86/kernel/kprobes_64.c |   22 +++++++++++++++++++++-
 2 files changed, 29 insertions(+), 1 deletions(-)
arch/x86/kernel/kprobes_32.c +8 -0
index a2b5ca7..23fb9ae 100644
@@ -721,6 +721,7 @@ static void __kprobes resume_execution(struct kprobe *p,
 		break;
 	}
 
+#ifdef CONFIG_X86_32
 	if (p->ainsn.boostable == 0) {
 		if ((regs->ip > copy_ip) &&
 		    (regs->ip - copy_ip) + 5 < (MAX_INSN_SIZE + 1)) {
@@ -739,6 +740,13 @@ static void __kprobes resume_execution(struct kprobe *p,
 	regs->ip = orig_ip + (regs->ip - copy_ip);
 
 no_change:
+#else
+	if (next_rip) {
+		regs->ip = next_rip;
+	} else {
+		regs->ip = orig_ip + (regs->ip - copy_ip);
+	}
+#endif
 	restore_btf();
 }
 
arch/x86/kernel/kprobes_64.c +21 -1
index 705cb99..f9cede4 100644
@@ -719,12 +719,32 @@ static void __kprobes resume_execution(struct kprobe *p,
 		break;
 	}
 
+#ifdef CONFIG_X86_32
+	if (p->ainsn.boostable == 0) {
+		if ((regs->ip > copy_ip) &&
+		    (regs->ip - copy_ip) + 5 < (MAX_INSN_SIZE + 1)) {
+			/*
+			 * These instructions can be executed directly if it
+			 * jumps back to correct address.
+			 */
+			set_jmp_op((void *)regs->ip,
+				   (void *)orig_ip + (regs->ip - copy_ip));
+			p->ainsn.boostable = 1;
+		} else {
+			p->ainsn.boostable = -1;
+		}
+	}
+
+	regs->ip = orig_ip + (regs->ip - copy_ip);
+
+no_change:
+#else
 	if (next_rip) {
 		regs->ip = next_rip;
 	} else {
 		regs->ip = orig_ip + (regs->ip - copy_ip);
 	}
-
+#endif
 	restore_btf();
 }
 
Signature · 1 line
1.5.4.rc0.1083.gf568
Quoted 1 line

From 323525be495dc545158fe43e072523d994253c39 Mon Sep 17 00:00:00 2001

From: Harvey Harrison <[email protected]>
Date: Sat, 15 Dec 2007 00:28:58 -0800
Subject: [PATCH] x86: Uglify kprobes_{32|64}.c before final unification

---
 arch/x86/kernel/kprobes_32.c |   92 ++++++++++++++++++++++++++------
 arch/x86/kernel/kprobes_64.c |  118 ++++++++++++++++++++++++++++++++++-------
 2 files changed, 172 insertions(+), 38 deletions(-)
arch/x86/kernel/kprobes_32.c +74 -18

190 lines not on this page · raw message

arch/x86/kernel/kprobes_64.c +98 -20

239 lines not on this page · raw message

Signature · 1 line
1.5.4.rc0.1083.gf568
Quoted 1 line

From e7fd0efa2e7860012d0a625c1fda3174ae200dc5 Mon Sep 17 00:00:00 2001

From: Harvey Harrison <[email protected]>
Date: Sat, 15 Dec 2007 00:36:37 -0800
Subject: [PATCH] x86: Final kprobes_{32|64}.c unification

Sure, it's ugly, but it can only get better from here.

---
 arch/x86/kernel/kprobes_32.c |   33 +++++++++++++++++++++++++++++++++
 arch/x86/kernel/kprobes_64.c |   18 ++++++++++++++++++
 2 files changed, 51 insertions(+), 0 deletions(-)
arch/x86/kernel/kprobes_32.c +33 -0
index cb836ce..f195348 100644
@@ -20,10 +20,15 @@
 
 #include <linux/kprobes.h>
 #include <linux/ptrace.h>
+#include <linux/string.h>
+#include <linux/slab.h>
 #include <linux/preempt.h>
+#include <linux/module.h>
 #include <linux/kdebug.h>
+
 #include <asm/cacheflush.h>
 #include <asm/desc.h>
+#include <asm/pgtable.h>
 #include <asm/uaccess.h>
 #include <asm/alternative.h>
 
@@ -447,6 +452,7 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
 				regs->flags &= ~TF_MASK;
 				regs->flags |= kcb->kprobe_saved_flags;
 				goto no_kprobe;
+#ifdef CONFIG_X86_32
 			}
 			/* We have reentered the kprobe_handler(), since
 			 * another probe was hit while within the handler.
@@ -460,6 +466,33 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
 			prepare_singlestep(p, regs);
 			kcb->kprobe_status = KPROBE_REENTER;
 			return 1;
+#else
+			} else if (kcb->kprobe_status == KPROBE_HIT_SSDONE) {
+				/* TODO: Provide re-entrancy from
+				 * post_kprobes_handler() and avoid exception
+				 * stack corruption while single-stepping on
+				 * the instruction of the new probe.
+				 */
+				arch_disarm_kprobe(p);
+				regs->ip = (unsigned long)p->addr;
+				reset_current_kprobe();
+				ret = 1;
+			} else {
+				/* We have reentered the kprobe_handler(), since
+				 * another probe was hit while within the
+				 * handler. We here save the original kprobe
+				 * variables and just single step on instruction
+				 * of the new probe without calling any user
+				 * handlers.
+				 */
+				save_previous_kprobe(kcb);
+				set_current_kprobe(p, regs, kcb);
+				kprobes_inc_nmissed_count(p);
+				prepare_singlestep(p, regs);
+				kcb->kprobe_status = KPROBE_REENTER;
+				return 1;
+			}
+#endif
 		} else {
 			if (*addr != BREAKPOINT_INSTRUCTION) {
 			/* The breakpoint instruction was removed by
arch/x86/kernel/kprobes_64.c +18 -0
index 6761a80..f195348 100644
@@ -26,6 +26,8 @@
 #include <linux/module.h>
 #include <linux/kdebug.h>
 
+#include <asm/cacheflush.h>
+#include <asm/desc.h>
 #include <asm/pgtable.h>
 #include <asm/uaccess.h>
 #include <asm/alternative.h>
@@ -450,6 +452,21 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
 				regs->flags &= ~TF_MASK;
 				regs->flags |= kcb->kprobe_saved_flags;
 				goto no_kprobe;
+#ifdef CONFIG_X86_32
+			}
+			/* We have reentered the kprobe_handler(), since
+			 * another probe was hit while within the handler.
+			 * We here save the original kprobes variables and
+			 * just single step on the instruction of the new probe
+			 * without calling any user handlers.
+			 */
+			save_previous_kprobe(kcb);
+			set_current_kprobe(p, regs, kcb);
+			kprobes_inc_nmissed_count(p);
+			prepare_singlestep(p, regs);
+			kcb->kprobe_status = KPROBE_REENTER;
+			return 1;
+#else
 			} else if (kcb->kprobe_status == KPROBE_HIT_SSDONE) {
 				/* TODO: Provide re-entrancy from
 				 * post_kprobes_handler() and avoid exception
@@ -475,6 +492,7 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
 				kcb->kprobe_status = KPROBE_REENTER;
 				return 1;
 			}
+#endif
 		} else {
 			if (*addr != BREAKPOINT_INSTRUCTION) {
 			/* The breakpoint instruction was removed by
Signature · 1 line
1.5.4.rc0.1083.gf568
Quoted 1 line

From 7fe6bd404ae0c51ec0bd334ca28a1f17f247a099 Mon Sep 17 00:00:00 2001

From: Harvey Harrison <[email protected]>
Date: Sat, 15 Dec 2007 00:39:44 -0800
Subject: [PATCH] x86: Eliminate kprobes_{32|64}.c

Now that the files are the same, unify the makefiles and eliminate the duplicates.

---
 arch/x86/kernel/Makefile_32  |    2 +-
 arch/x86/kernel/Makefile_64  |    2 +-
 arch/x86/kernel/kprobes.c    | 1090 ++++++++++++++++++++++++++++++++++++++++++
 arch/x86/kernel/kprobes_32.c | 1090 ------------------------------------------
 arch/x86/kernel/kprobes_64.c | 1090 ------------------------------------------
 5 files changed, 1092 insertions(+), 2182 deletions(-)
arch/x86/kernel/Makefile_32 +1 -1
index db8cada..62a8120 100644
@@ -35,7 +35,7 @@ obj-$(CONFIG_KEXEC)		+= machine_kexec_32.o relocate_kernel_32.o crash.o
 obj-$(CONFIG_CRASH_DUMP)	+= crash_dump_32.o
 obj-$(CONFIG_X86_NUMAQ)		+= numaq_32.o
 obj-$(CONFIG_X86_SUMMIT_NUMA)	+= summit_32.o
-obj-$(CONFIG_KPROBES)		+= kprobes_32.o
+obj-$(CONFIG_KPROBES)		+= kprobes.o
 obj-$(CONFIG_MODULES)		+= module_32.o
 obj-$(CONFIG_ACPI_SRAT) 	+= srat_32.o
 obj-$(CONFIG_EFI) 		+= efi.o efi_32.o efi_stub_32.o
arch/x86/kernel/Makefile_64 +1 -1
index a961f5c..79e335c 100644
@@ -34,7 +34,7 @@ obj-$(CONFIG_EARLY_PRINTK)	+= early_printk.o
 obj-$(CONFIG_GART_IOMMU)	+= pci-gart_64.o aperture_64.o
 obj-$(CONFIG_CALGARY_IOMMU)	+= pci-calgary_64.o tce_64.o
 obj-$(CONFIG_SWIOTLB)		+= pci-swiotlb_64.o
-obj-$(CONFIG_KPROBES)		+= kprobes_64.o
+obj-$(CONFIG_KPROBES)		+= kprobes.o
 obj-$(CONFIG_X86_PM_TIMER)	+= pmtimer_64.o
 obj-$(CONFIG_X86_VSMP)		+= vsmp_64.o
 obj-$(CONFIG_K8_NB)		+= k8.o
arch/x86/kernel/kprobes.c new file +1090 -0

1,090 lines not on this page · raw message

arch/x86/kernel/kprobes_32.c deleted +0 -1090

996 lines not on this page · raw message

arch/x86/kernel/kprobes_64.c deleted +0 -1090

1,090 lines not on this page · raw message

The rest of this diff is not shown. View the raw message.

Signature · 1 line
1.5.4.rc0.1083.gf568

Part of the diff is not shown here. View the raw message.

#1 lore raw
Quoted 11 lines · Harvey Harrison

Further unification work. There is a possible behavior change on X86_32 here.

is_IF_modifier(p->opcode)

to

is_IF_modifier(p->ainsn.insn)

Which should be equivalent, but is not purely cosmetic as the rest of the unification so far.

hm, could you split this into two, the pure-equivalence and the possibly-modifying patch? (that way any potential breakage becomes bisectable) Same end result, just two commits instead of one.

also, did you manage to run/test kprobes (on 32-bit or 64-bit x86), and it worked fine?

Ingo

#2 lore raw
Quoted 9 lines · Ingo Molnar
Quoted 7 lines · Harvey Harrison

Further unification work. There is a possible behavior change on X86_32 here.

is_IF_modifier(p->opcode)

to

Quoted 9 lines
Quoted 4 lines

is_IF_modifier(p->ainsn.insn)

Which should be equivalent, but is not purely cosmetic as the rest of the unification so far.

hm, could you split this into two, the pure-equivalence and the possibly-modifying patch? (that way any potential breakage becomes bisectable) Same end result, just two commits instead of one.

Sure, I'll go back through and see if the series can be cleaned up a bit as well as expand the commit message a little bit.

Quoted 3 lines

also, did you manage to run/test kprobes (on 32-bit or 64-bit x86), and it worked fine?

Sorry, I should have predicated the whole series with RFC. Currently this is compile-tested only. There is only the one patch that has any behavioral change. I believe the series also pointed out an existing bug in the 32-bit version...which I've preserved but will note in the commit messages in the respun series.

In case you're interested, from the patch which unifies the definition of MAX_INSTRUCTION_SIZE:

memcpy(p->ainsn.insn, p->addr, (MAX_INSN_SIZE + 1) * sizeof(kprobe_opcode_t));

If you compare this memcpy from arch_prepare_kprobe in 32/64 bit I'm almost sure the X86_32 version should be

... + sizeof(kprobe_opcode_t)

not

... * sizeof(kprobe_opcode_t)

Cheers,

Harvey

#3 lore raw
Quoted 8 lines · Harvey Harrison

If you compare this memcpy from arch_prepare_kprobe in 32/64 bit I'm almost sure the X86_32 version should be

... + sizeof(kprobe_opcode_t)

not

... * sizeof(kprobe_opcode_t)

good point. I've Cc:-ed the top authors of kprobes.c. Could anyone confirm (or deny) that Harvey found a real kprobes bug here?

Ingo

#4 lore raw

Hi Harvey and Ingo,

I'm working on another version of patches for unification. Currently cleaning up the patches.
http://sources.redhat.com/ml/systemtap/2007-q4/msg00457.html
I'll cleanup and repost it today.

Quoted 20 lines · Ingo Molnar
Quoted 8 lines · Harvey Harrison

If you compare this memcpy from arch_prepare_kprobe in 32/64 bit I'm almost sure the X86_32 version should be

... + sizeof(kprobe_opcode_t)

not

... * sizeof(kprobe_opcode_t)

good point. I've Cc:-ed the top authors of kprobes.c. Could anyone confirm (or deny) that Harvey found a real kprobes bug here?

Ingo
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/

Signature · 7 lines
Masami Hiramatsu

Software Engineer
Hitachi Computer Products (America) Inc.
Software Solutions Division

e-mail: [email protected], [email protected]
#5 lore raw

Re: Final kprobes rollup patches

Masami,

Quoted 6 lines · Masami Hiramatsu

Hi Harvey and Ingo,

I'm working on another version of patches for unification. Currently cleaning up the patches.
http://sources.redhat.com/ml/systemtap/2007-q4/msg00457.html
I'll cleanup and repost it today.

cool! Please Cc: lkml and Harvey as well so that there's less overlap in unification work - Harvey spent quite some time unifying and cleaning up the kprobes code during the past week.

So i think we could/should use Harvey's latest series as a base, those are pretty finegrained already. Note that they break 64-bit kprobes though, with such a config:

CONFIG_KPROBES=y
CONFIG_NET_TCPPROBE=y

so it crashes with an int3 in the TCP code. It's probably some trivial typo somewhere, as 32-bit works fine.

the coordinates for x86.git#mm can be found below - that tree already includes Harvey's latest kprobes series. I'll try to bisect the 64-bit breakage now.

Ingo

------------------>
git-clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git linux-2.6.git cd linux-2.6.git
git-branch x86
git-checkout x86
git-pull git://git.kernel.org/pub/scm/linux/kernel/git/x86/linux-2.6-x86.git mm

(do subsequent pulls via "git-pull --force", as we frequently rebase the git tree. NOTE: this might override your own local changes, so do this only if you dont mind about losing thse changes in that tree.)

#6 lore raw

Re: Final kprobes rollup patches

Hi Ingo,

Quoted 6 lines · Ingo Molnar

Masami,

Quoted 2 lines · Masami Hiramatsu

Hi Harvey and Ingo,

Quoted 8 lines
Quoted 4 lines

I'm working on another version of patches for unification. Currently cleaning up the patches.
http://sources.redhat.com/ml/systemtap/2007-q4/msg00457.html
I'll cleanup and repost it today.

cool! Please Cc: lkml and Harvey as well so that there's less overlap in unification work - Harvey spent quite some time unifying and cleaning up the kprobes code during the past week.

Should I rewrite it based on current git tree?
My patch includes 3 part of patches.
- 2 Bugfix patches (which is not merged yet.)
- 2 booster patches (ditto)
- 2 unification patches (most of this patches are already done by Harvey's patch)

Quoted 28 lines

So i think we could/should use Harvey's latest series as a base, those are pretty finegrained already. Note that they break 64-bit kprobes though, with such a config:

CONFIG_KPROBES=y
CONFIG_NET_TCPPROBE=y

so it crashes with an int3 in the TCP code. It's probably some trivial typo somewhere, as 32-bit works fine.

the coordinates for x86.git#mm can be found below - that tree already includes Harvey's latest kprobes series. I'll try to bisect the 64-bit breakage now.

Ingo

------------------>
git-clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git linux-2.6.git cd linux-2.6.git
git-branch x86
git-checkout x86
git-pull git://git.kernel.org/pub/scm/linux/kernel/git/x86/linux-2.6-x86.git mm

(do subsequent pulls via "git-pull --force", as we frequently rebase the git tree. NOTE: this might override your own local changes, so do this only if you dont mind about losing thse changes in that tree.)

Signature · 7 lines
Masami Hiramatsu

Software Engineer
Hitachi Computer Products (America) Inc.
Software Solutions Division

e-mail: [email protected], [email protected]
#7 lore raw

Re: Final kprobes rollup patches

Quoted 9 lines · Masami Hiramatsu
Quoted 3 lines

cool! Please Cc: lkml and Harvey as well so that there's less overlap in unification work - Harvey spent quite some time unifying and cleaning up the kprobes code during the past week.

Should I rewrite it based on current git tree?
My patch includes 3 part of patches.
- 2 Bugfix patches (which is not merged yet.)
- 2 booster patches (ditto)
- 2 unification patches (most of this patches are already done by Harvey's patch)

would it be easier/more robust to first did the unification patches and then get the bugfixes and new features in? That would give us your bugfixes and new features on both 32-bit and 64-bit at the same time.

feel free to do whichever approach you prefer - but it would be nice to preserve the unification and cleanup work done by Harvey.

btw., is any of your bugfixes 2.6.24 material?

Ingo

#8 lore raw

Re: Final kprobes rollup patches

Hi Ingo,

Quoted 11 lines · Ingo Molnar
Quoted 8 lines · Masami Hiramatsu
Quoted 3 lines

cool! Please Cc: lkml and Harvey as well so that there's less overlap in unification work - Harvey spent quite some time unifying and cleaning up the kprobes code during the past week.

Should I rewrite it based on current git tree?
My patch includes 3 part of patches.
- 2 Bugfix patches (which is not merged yet.)
- 2 booster patches (ditto)
- 2 unification patches (most of this patches are already done by Harvey's patch)

Quoted 3 lines

would it be easier/more robust to first did the unification patches and then get the bugfixes and new features in? That would give us your bugfixes and new features on both 32-bit and 64-bit at the same time.

As far as I can see, my patches have less #ifdefs than Harvey's. However, that patch's granularity may be not so good currently.

Quoted 2 lines

feel free to do whichever approach you prefer - but it would be nice to preserve the unification and cleanup work done by Harvey.

OK, rewriting will take a while, so I sent a series of patches which I have just now.

Quoted 1 line

btw., is any of your bugfixes 2.6.24 material?

Yes, I'd like to fix first two bugs in 2.6.24.

Thank you very much,

Quoted 2 lines

Ingo

Signature · 7 lines
Masami Hiramatsu

Software Engineer
Hitachi Computer Products (America) Inc.
Software Solutions Division

e-mail: [email protected], [email protected]
#9 lore raw

Re: Final kprobes rollup patches

In reply to Ingo Molnar
Quoted 12 lines · Ingo Molnar
Quoted 9 lines · Masami Hiramatsu
Quoted 3 lines

cool! Please Cc: lkml and Harvey as well so that there's less overlap in unification work - Harvey spent quite some time unifying and cleaning up the kprobes code during the past week.

Should I rewrite it based on current git tree?
My patch includes 3 part of patches.
- 2 Bugfix patches (which is not merged yet.)
- 2 booster patches (ditto)
- 2 unification patches (most of this patches are already done by Harvey's patch)

Quoted 9 lines

would it be easier/more robust to first did the unification patches and then get the bugfixes and new features in? That would give us your bugfixes and new features on both 32-bit and 64-bit at the same time.

feel free to do whichever approach you prefer - but it would be nice to preserve the unification and cleanup work done by Harvey.

btw., is any of your bugfixes 2.6.24 material?

Well, I'll admit to being a little disappointed if my work doesn't make it in, but there are bugfixes here. I think my cleanup breakout is better in the more-finegrained changes sense. If you decide to keep mine I'll rebase Masami's patches 1-4 on top of that and send it by him for resubmittal. But I'll leave it to Ingo to decide how to procede.

Harvey

#10 lore raw
In reply to Ingo Molnar

* Ingo Molnar <[email protected]> [2007-12-15 14:12:04]:

Hi Ingo, Harvey

In file include/asm-x86/kprobes_32.h
typedef u8 kprobe_opcode_t;
hence sizeof(kprobe_opcode_t) turns out to be 1.

Hence

memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t)); is correct.

--
Regards
Srikar

Quoted 22 lines · Harvey Harrison
Quoted 9 lines

If you compare this memcpy from arch_prepare_kprobe in 32/64 bit I'm almost sure the X86_32 version should be

... + sizeof(kprobe_opcode_t)

not

... * sizeof(kprobe_opcode_t)

good point. I've Cc:-ed the top authors of kprobes.c. Could anyone confirm (or deny) that Harvey found a real kprobes bug here?

Ingo
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/

#11 lore raw
Quoted 5 lines · Srikar Dronamraju

* Ingo Molnar <[email protected]> [2007-12-15 14:12:04]:

Hi Ingo, Harvey

Quoted 9 lines

In file include/asm-x86/kprobes_32.h
typedef u8 kprobe_opcode_t;
hence sizeof(kprobe_opcode_t) turns out to be 1.

Hence

memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t)); is correct.

OK, but this would be much clearer to adopt the X86_64 way, define MAX_INSN_SIZE one smaller and make this line:

/* Copy original instruction plus space for 1 byte relative jump */ memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE + sizeof(kprobe_opcode_t));

See the first patch of my cleanup work that unified MAX_INSN_SIZE and you'll see why this jumped out.

Harvey

#12 lore raw

Hi Harvey,

Quoted 19 lines · Harvey Harrison
Quoted 5 lines · Srikar Dronamraju

* Ingo Molnar <[email protected]> [2007-12-15 14:12:04]:

Hi Ingo, Harvey

Quoted 9 lines

In file include/asm-x86/kprobes_32.h
typedef u8 kprobe_opcode_t;
hence sizeof(kprobe_opcode_t) turns out to be 1.

Hence

memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t)); is correct.

OK, but this would be much clearer to adopt the X86_64 way, define MAX_INSN_SIZE one smaller and make this line:

Quoted 7 lines

/* Copy original instruction plus space for 1 byte relative jump */ memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE + sizeof(kprobe_opcode_t));

See the first patch of my cleanup work that unified MAX_INSN_SIZE and you'll see why this jumped out.

Harvey

If you mention about a relative jump which is inserted by resume_execution(), I think you might misunderstand that relative jump.

The size of that relative jump, which will be embedded by kprobe-booster, is 5-bytes(not 1 byte). So it needs 5 bytes space.
And we decided not to expand MAX_INSN_SIZE when we developed the booster. The reasons are:
- it is supplemental feature(just accelerating kprobes), if we have no space, we can disable it.
- 5 bytes are big enough compared with 15(=MAX_INSN_SIZE)
- the lengths of most of instructions are less than 10 bytes.

Additionally, MAX_INSN_SIZE is used in kernel/kprobes.c to allocate an instruction buffer which will be assigned to p->ainsn.insn. Since the instruction buffer size is MAX_INSN_SIZE, you can not copy instructions more than MAX_INSN_SIZE.

BTW, in my patch, I unified MAX_INSN_SIZE to bigger one(16). I think it is enough for us.

Thanks,

Best Regards,

Signature · 7 lines
Masami Hiramatsu

Software Engineer
Hitachi Computer Products (America) Inc.
Software Solutions Division

e-mail: [email protected], [email protected]
#13 lore raw
Quoted 13 lines · Masami Hiramatsu

Hi Harvey,
If you mention about a relative jump which is inserted by resume_execution(), I think you might misunderstand that relative jump.

The size of that relative jump, which will be embedded by kprobe-booster, is 5-bytes(not 1 byte). So it needs 5 bytes space.
And we decided not to expand MAX_INSN_SIZE when we developed the booster. The reasons are:
- it is supplemental feature(just accelerating kprobes), if we have no space, we can disable it.
- 5 bytes are big enough compared with 15(=MAX_INSN_SIZE)
- the lengths of most of instructions are less than 10 bytes.

Quoted 8 lines

Additionally, MAX_INSN_SIZE is used in kernel/kprobes.c to allocate an instruction buffer which will be assigned to p->ainsn.insn. Since the instruction buffer size is MAX_INSN_SIZE, you can not copy instructions more than MAX_INSN_SIZE.

BTW, in my patch, I unified MAX_INSN_SIZE to bigger one(16). I think it is enough for us.

I went with 15 in mine, I thought it made the code a little more readable, but I will defer if you think 16 is better. If you want me to send the whole series to you, let me know.

I just sent out a series of 4 patches equivalent to your patches 1-4/6 but based on my already unified kprobes.c/h, You may want to check your handling of restored registers in trampoline_probe_handler which I found when rebasing yours on top of my cleanups. Not sure if this is important, but it was a difference I found.

X86_32:
regs->cs = __KERNEL_CS | get_kernel_rpl();

yours:
regs->cs = __KERNEL_CS;

Harvey

#14 lore raw

Hi Harvey,

Quoted 19 lines · Harvey Harrison
Quoted 18 lines · Masami Hiramatsu

Hi Harvey,
If you mention about a relative jump which is inserted by resume_execution(), I think you might misunderstand that relative jump.

The size of that relative jump, which will be embedded by kprobe-booster, is 5-bytes(not 1 byte). So it needs 5 bytes space.
And we decided not to expand MAX_INSN_SIZE when we developed the booster. The reasons are:
- it is supplemental feature(just accelerating kprobes), if we have no space, we can disable it.
- 5 bytes are big enough compared with 15(=MAX_INSN_SIZE)
- the lengths of most of instructions are less than 10 bytes.

Additionally, MAX_INSN_SIZE is used in kernel/kprobes.c to allocate an instruction buffer which will be assigned to p->ainsn.insn. Since the instruction buffer size is MAX_INSN_SIZE, you can not copy instructions more than MAX_INSN_SIZE.

Quoted 7 lines
Quoted 3 lines

BTW, in my patch, I unified MAX_INSN_SIZE to bigger one(16). I think it is enough for us.

I went with 15 in mine, I thought it made the code a little more readable, but I will defer if you think 16 is better. If you want me to send the whole series to you, let me know.

Before porting, could you tell me what differences are important to you? We can discuss about it.

Quoted 11 lines

I just sent out a series of 4 patches equivalent to your patches 1-4/6 but based on my already unified kprobes.c/h, You may want to check your handling of restored registers in trampoline_probe_handler which I found when rebasing yours on top of my cleanups. Not sure if this is important, but it was a difference I found.

X86_32:
regs->cs = __KERNEL_CS | get_kernel_rpl();

yours:
regs->cs = __KERNEL_CS;

Because of kretprobe's compatibility, on x86-32 cs should be set rpl(). But get_kernel_rpl() does not exist on x86-64.

Thanks,

Signature · 7 lines
Masami Hiramatsu

Software Engineer
Hitachi Computer Products (America) Inc.
Software Solutions Division

e-mail: [email protected], [email protected]
#15 lore raw
Quoted 10 lines · Masami Hiramatsu

Hi Harvey,
Before porting, could you tell me what differences are important to you? We can discuss about it.

Quoted 6 lines

I just sent out a series of 4 patches equivalent to your patches 1-4/6 but based on my already unified kprobes.c/h, You may want to check your handling of restored registers in trampoline_probe_handler which I found when rebasing yours on top of my cleanups. Not sure if this is important, but it was a difference I found.

Quoted 9 lines
Quoted 5 lines

X86_32:
regs->cs = __KERNEL_CS | get_kernel_rpl();

yours:
regs->cs = __KERNEL_CS;

Because of kretprobe's compatibility, on x86-32 cs should be set rpl(). But get_kernel_rpl() does not exist on x86-64.

I've already ported it and sent it to you. It's not really important to me I just think my fine-grained patches may be of some use to see where the differences between X86_32/64 ended up being. Your patches end up being just about entirely removal of ifdefs when rebased onto my patches, so it's at least a good secondary check of your patches even if mine don't go in. Your patches end up being much smaller against my version too.

I like my version slightly better because the remaining ifdefs (wrmsr, etc) and others could be done in a few more small patches that are more easily reviewable than your large final unification patch.

But, you know the code better than I....

Harvey

#16 lore raw

Hi Harvey,

Quoted 20 lines · Harvey Harrison
Quoted 10 lines · Masami Hiramatsu

Hi Harvey,
Before porting, could you tell me what differences are important to you? We can discuss about it.

Quoted 6 lines

I just sent out a series of 4 patches equivalent to your patches 1-4/6 but based on my already unified kprobes.c/h, You may want to check your handling of restored registers in trampoline_probe_handler which I found when rebasing yours on top of my cleanups. Not sure if this is important, but it was a difference I found.

Quoted 8 lines
Quoted 5 lines

X86_32:
regs->cs = __KERNEL_CS | get_kernel_rpl();

yours:
regs->cs = __KERNEL_CS;

Because of kretprobe's compatibility, on x86-32 cs should be set rpl(). But get_kernel_rpl() does not exist on x86-64.

Quoted 7 lines

I've already ported it and sent it to you. It's not really important to me I just think my fine-grained patches may be of some use to see where the differences between X86_32/64 ended up being. Your patches end up being just about entirely removal of ifdefs when rebased onto my patches, so it's at least a good secondary check of your patches even if mine don't go in. Your patches end up being much smaller against my version too.

OK, I'll review that.

Quoted 4 lines

I like my version slightly better because the remaining ifdefs (wrmsr, etc) and others could be done in a few more small patches that are more easily reviewable than your large final unification patch.

I agreed that your patches are including some goodness. So let us merge it into one.

Quoted 5 lines

But, you know the code better than I....

Harvey

Signature · 7 lines
Masami Hiramatsu

Software Engineer
Hitachi Computer Products (America) Inc.
Software Solutions Division

e-mail: [email protected], [email protected]
#17 lore raw
Quoted 19 lines · Masami Hiramatsu

Hi Harvey,

Quoted 5 lines · Harvey Harrison
Quoted 3 lines · Masami Hiramatsu

Hi Harvey,
Before porting, could you tell me what differences are important to you? We can discuss about it.

Quoted 7 lines

I've already ported it and sent it to you. It's not really important to me I just think my fine-grained patches may be of some use to see where the differences between X86_32/64 ended up being. Your patches end up being just about entirely removal of ifdefs when rebased onto my patches, so it's at least a good secondary check of your patches even if mine don't go in. Your patches end up being much smaller against my version too.

OK, I'll review that.

Quoted 1 line
Quoted 8 lines
Quoted 3 lines

I like my version slightly better because the remaining ifdefs (wrmsr, etc) and others could be done in a few more small patches that are more easily reviewable than your large final unification patch.

I agreed that your patches are including some goodness. So let us merge it into one.

OK, I'll take the last bits of your patches 5/6 that aren't already cleaned up and send out a unified patchset for you to add your acked/signed off by/reviewed by as appropriate.

These are:

-add stack_addr() macro
-I prefer the table defintion macros in mine as it avoids the need to cast the pointer passed to test_bit, but if you want them
to be u32 as in your patch, I can change it.
-wrmsr/wrmsrl - use wrmsr() for both
-call is_IF_modifier with p->ainsn.insn in both
-check casting of jprobe_saved_sp, I get some compile warnings currently with pointer comparisons to signed/unsigned types.

That will eliminate nearly all of the remaining ifdefs in my version, let me work through this and I'll send out a set for review.

CHeers,

Harvey

#18 lore raw

Hi Harvey,

Quoted 20 lines · Harvey Harrison
Quoted 19 lines · Masami Hiramatsu

Hi Harvey,

Quoted 11 lines · Harvey Harrison
Quoted 3 lines · Masami Hiramatsu

Hi Harvey,
Before porting, could you tell me what differences are important to you? We can discuss about it.

I've already ported it and sent it to you. It's not really important to me I just think my fine-grained patches may be of some use to see where the differences between X86_32/64 ended up being. Your patches end up being just about entirely removal of ifdefs when rebased onto my patches, so it's at least a good secondary check of your patches even if mine don't go in. Your patches end up being much smaller against my version too.

OK, I'll review that.

Quoted 3 lines

I like my version slightly better because the remaining ifdefs (wrmsr, etc) and others could be done in a few more small patches that are more easily reviewable than your large final unification patch.

Quoted 8 lines
Quoted 4 lines

I agreed that your patches are including some goodness. So let us merge it into one.

OK, I'll take the last bits of your patches 5/6 that aren't already cleaned up and send out a unified patchset for you to add your acked/signed off by/reviewed by as appropriate.

Sure, I'll review it. It is very helpful to me. Please Cc: or To: the parsons who are listed in this mail. Jim, if you can review the fixes which you've suggested, could you give him your signed-off?

Quoted 7 lines

These are:

(quoted diff) +0 -2
-add stack_addr() macro
-I prefer the table defintion macros in mine as it avoids the need to

cast the pointer passed to test_bit, but if you want them to be u32 as in your patch, I can change it.

please do so. we'd like to reduce ifdefs as less as possible:-)

Quoted 4 lines
(quoted diff) +0 -3
-wrmsr/wrmsrl - use wrmsr() for both
-call is_IF_modifier with p->ainsn.insn in both
-check casting of jprobe_saved_sp, I get some compile warnings currently

with pointer comparisons to signed/unsigned types.

Could you also add below?
- fix some comments (it clarifies the meanings of the code)
- add fix_riprel(). this useful to reduce ifdefs.
- expand reenter_kprobe(). I think it treat above two blocks.
- reassignment of regs->ip in kprobe_handler can be unified to "regs->ip = (unsigned long)addr;"

Quoted 9 lines

That will eliminate nearly all of the remaining ifdefs in my version, let me work through this and I'll send out a set for review.

CHeers,

Harvey

Best Regards,

Signature · 7 lines
Masami Hiramatsu

Software Engineer
Hitachi Computer Products (America) Inc.
Software Solutions Division

e-mail: [email protected], [email protected]
#19 lore raw
Quoted 9 lines · Masami Hiramatsu
Quoted 6 lines

These are:

(quoted diff) +0 -2
-add stack_addr() macro
-I prefer the table defintion macros in mine as it avoids the need to

cast the pointer passed to test_bit, but if you want them to be u32 as in your patch, I can change it.

please do so. we'd like to reduce ifdefs as less as possible:-)

Quoted 11 lines
Quoted 4 lines
(quoted diff) +0 -3
-wrmsr/wrmsrl - use wrmsr() for both
-call is_IF_modifier with p->ainsn.insn in both
-check casting of jprobe_saved_sp, I get some compile warnings currently

with pointer comparisons to signed/unsigned types.

Could you also add below?
- fix some comments (it clarifies the meanings of the code)
- add fix_riprel(). this useful to reduce ifdefs.
- expand reenter_kprobe(). I think it treat above two blocks.
- reassignment of regs->ip in kprobe_handler can be unified to "regs->ip = (unsigned long)addr;"

Oh, I forgot to point out important thing.
- please make bugfix patches first. I think my bugfix patches need to go upstream before unification. It would cause some crashes.

Thank you.

Signature · 7 lines
Masami Hiramatsu

Software Engineer
Hitachi Computer Products (America) Inc.
Software Solutions Division

e-mail: [email protected], [email protected]
#20 lore raw
Quoted 24 lines · Masami Hiramatsu
Quoted 4 lines · Masami Hiramatsu

Review

Quoted 4 lines

These are:

(quoted diff) +0 -2
-add stack_addr() macro
-I prefer the table defintion macros in mine as it avoids the need

to

Quoted 8 lines
Quoted 2 lines

cast the pointer passed to test_bit, but if you want them to be u32 as in your patch, I can change it.

please do so. we'd like to reduce ifdefs as less as possible:-)

Review

Quoted 3 lines
(quoted diff) +0 -3
-wrmsr/wrmsrl - use wrmsr() for both
-call is_IF_modifier with p->ainsn.insn in both
-check casting of jprobe_saved_sp, I get some compile warnings

currently

Quoted 8 lines
Quoted 1 line

with pointer comparisons to signed/unsigned types.

Could you also add below?
- fix some comments (it clarifies the meanings of the code)
- add fix_riprel(). this useful to reduce ifdefs.
- expand reenter_kprobe(). I think it treat above two blocks.
- reassignment of regs->ip in kprobe_handler can be unified to "regs->ip = (unsigned long)addr;"

Quoted 5 lines

Oh, I forgot to point out important thing.
- please make bugfix patches first. I think my bugfix patches need to go upstream before unification. It would cause some crashes.

It's pretty hard to move those bugfixes to the head of the queue.

Attached is an mbox of my unification work. Maybe you could get your two bugfixes applied to mainline kprobes_32/64.c, then my series could go in as a merge later on. Most of my stuff is in kprobes.c post-unify so the merge would be trivial later.

Ingo, what do you think? This rollup replaces all of my kprobes patches to date. So you could apply patched 1,2/6 from Masami into 2.6.24 and let mine come in during 2.6.25 as a merge, which would avoid the conflicts in kprobes_32|64.c?

Harvey

#21 lore raw

PATCH 1/1 x86: kprobes use stack_addr() macro

In reply to Masami Hiramatsu

---
Replacement for the last patch in the kprobes series I just sent.

 arch/x86/kernel/kprobes.c |   45 +++++++++++++++++++++------------------------
 1 files changed, 21 insertions(+), 24 deletions(-)
arch/x86/kernel/kprobes.c +21 -24
index 6f52c5e..c9df6fb 100644
@@ -44,6 +44,20 @@ struct kretprobe_blackpoint kretprobe_blacklist[] = {
 };
 const int kretprobe_blacklist_size = ARRAY_SIZE(kretprobe_blacklist);
 
+/*
+ * "&regs->sp" looks wrong, but it's correct for x86_32.  x86_32 CPUs
+ * don't save the ss and esp registers if the CPU is already in kernel
+ * mode when it traps.  So for kprobes, regs->sp and regs->ss are not
+ * the [nonexistent] saved stack pointer and ss register, but rather
+ * the top 8 bytes of the pre-int3 stack.  So &regs->sp happens to
+ * point to the top of the pre-int3 stack.
+ */
+#ifdef CONFIG_X86_32
+# define stack_addr(regs) ((unsigned long *)&regs->sp)
+#else
+# define stack_addr(regs) ((unsigned long *)regs->sp)
+#endif
+
 #define W(r, b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, ba, bb, bc, bd, be, bf)  \
 	(((b0##UL << 0x0)|(b1##UL << 0x1)|(b2##UL << 0x2)|(b3##UL << 0x3) |   \
 	  (b4##UL << 0x4)|(b5##UL << 0x5)|(b6##UL << 0x6)|(b7##UL << 0x7) |   \
@@ -409,11 +423,8 @@ static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
 void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri,
 				      struct pt_regs *regs)
 {
-#ifdef CONFIG_X86_32
-	unsigned long *sara = (unsigned long *)&regs->sp;
-#else
-	unsigned long *sara = (unsigned long *)regs->sp;
-#endif
+	unsigned long *sara = stack_addr(regs);
+
 	ri->ret_addr = (kprobe_opcode_t *) *sara;
 	/* Replace the return addr with trampoline addr */
 	*sara = (unsigned long) &kretprobe_trampoline;
@@ -751,11 +762,8 @@ void *__kprobes trampoline_handler(struct pt_regs *regs)
 static void __kprobes resume_execution(struct kprobe *p,
 		struct pt_regs *regs, struct kprobe_ctlblk *kcb)
 {
-#ifdef CONFIG_X86_32
-	unsigned long *tos = (unsigned long *)&regs->sp;
-#else
-	unsigned long *tos = (unsigned long *)regs->sp;
-#endif
+
+	unsigned long *tos = stack_addr(regs);
 	unsigned long copy_ip = (unsigned long)p->ainsn.insn;
 	unsigned long orig_ip = (unsigned long)p->addr;
 	kprobe_opcode_t *insn = p->ainsn.insn;
@@ -984,11 +992,7 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
 	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
 
 	kcb->jprobe_saved_regs = *regs;
-#ifdef CONFIG_X86_32
-	kcb->jprobe_saved_sp = &regs->sp;
-#else
-	kcb->jprobe_saved_sp = (long *) regs->sp;
-#endif
+	kcb->jprobe_saved_sp = (long *)stack_addr(regs);
 	addr = (unsigned long)(kcb->jprobe_saved_sp);
 	/*
 	 * As Linus pointed out, gcc assumes that the callee
@@ -1033,17 +1037,10 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
 	struct jprobe *jp = container_of(p, struct jprobe, kp);
 
 	if ((addr > (u8 *) jprobe_return) && (addr < (u8 *) jprobe_return_end)) {
-#ifdef CONFIG_X86_32
-		if (&regs->sp != kcb->jprobe_saved_sp) {
+		if (stack_addr(regs) != kcb->jprobe_saved_sp) {
 			struct pt_regs *saved_regs = &kcb->jprobe_saved_sp;
 			printk("current sp %p does not match saved sp %p\n",
-			       &regs->sp, kcb->jprobe_saved_sp);
-#else
-		if ((long *)regs->sp != kcb->jprobe_saved_sp) {
-			struct pt_regs *saved_regs = &kcb->jprobe_saved_sp;
-			printk("current sp %p does not match saved sp %p\n",
-			       (long *)regs->sp, kcb->jprobe_saved_sp);
-#endif
+			       stack_addr(regs), kcb->jprobe_saved_sp);
 			printk("Saved registers for jprobe %p\n", jp);
 			show_registers(saved_regs);
 			printk("Current registers\n");
Signature · 1 line
1.5.4.rc0.1083.gf568
#22 lore raw
In reply to Ingo Molnar

Hi Ingo, Harvey

In file include/asm-x86/kprobes_32.h
typedef u8 kprobe_opcode_t;
hence sizeof(kprobe_opcode_t) turns out to be 1.

Hence

memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t)); is correct.

--
Regards
Srikar

Quoted 22 lines · Harvey Harrison
Quoted 9 lines

If you compare this memcpy from arch_prepare_kprobe in 32/64 bit I'm almost sure the X86_32 version should be

... + sizeof(kprobe_opcode_t)

not

... * sizeof(kprobe_opcode_t)

good point. I've Cc:-ed the top authors of kprobes.c. Could anyone confirm (or deny) that Harvey found a real kprobes bug here?

Ingo
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/