[PATCH] Kprobes causes NX protection fault on i686 SMP

From: Prasanna S Panchamukhi
Date: Tue Feb 21 2006 - 23:21:32 EST



This patch fixes the problem seen on i686 machine with NX support,
where the instruction could not be single stepped because of NX
bit set on the memory pages allocated by kprobes module. This patch
provides allocation of instruction solt so that the processor can
execute the instruction from that location similar to x86_64
architecture. Thanks to Bibo and Masami for testing this patch.

Signed-off-by: Prasanna S Panchamukhi <prasanna@xxxxxxxxxx>


arch/i386/kernel/kprobes.c | 19 ++++++++++++++++---
include/asm-i386/kprobes.h | 7 +++++--
2 files changed, 21 insertions(+), 5 deletions(-)

diff -puN arch/i386/kernel/kprobes.c~kprobes-i386-fix-nx-protection-fault arch/i386/kernel/kprobes.c
--- linux-2.6.16-rc4-mm1/arch/i386/kernel/kprobes.c~kprobes-i386-fix-nx-protection-fault 2006-02-22 09:45:37.000000000 +0530
+++ linux-2.6.16-rc4-mm1-prasanna/arch/i386/kernel/kprobes.c 2006-02-22 09:45:37.000000000 +0530
@@ -101,6 +101,12 @@ static inline int is_IF_modifier(kprobe_

int __kprobes arch_prepare_kprobe(struct kprobe *p)
{
+
+ /* insn: must be on special executable page on i386. */
+ p->ainsn.insn = get_insn_slot();
+ if (!p->ainsn.insn)
+ return -ENOMEM;
+
memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t));
p->opcode = *p->addr;
if (can_boost(p->opcode)) {
@@ -125,6 +131,13 @@ void __kprobes arch_disarm_kprobe(struct
(unsigned long) p->addr + sizeof(kprobe_opcode_t));
}

+void __kprobes arch_remove_kprobe(struct kprobe *p)
+{
+ mutex_lock(&kprobe_mutex);
+ free_insn_slot(p->ainsn.insn);
+ mutex_unlock(&kprobe_mutex);
+}
+
static inline void save_previous_kprobe(struct kprobe_ctlblk *kcb)
{
kcb->prev_kprobe.kp = kprobe_running();
@@ -159,7 +172,7 @@ static inline void prepare_singlestep(st
if (p->opcode == BREAKPOINT_INSTRUCTION)
regs->eip = (unsigned long)p->addr;
else
- regs->eip = (unsigned long)&p->ainsn.insn;
+ regs->eip = (unsigned long)p->ainsn.insn;
}

/* Called with kretprobe_lock held */
@@ -301,7 +314,7 @@ static int __kprobes kprobe_handler(stru
!p->post_handler && !p->break_handler ) {
/* Boost up -- we can execute copied instructions directly */
reset_current_kprobe();
- regs->eip = (unsigned long)&p->ainsn.insn;
+ regs->eip = (unsigned long)p->ainsn.insn;
preempt_enable_no_resched();
return 1;
}
@@ -437,7 +450,7 @@ static void __kprobes resume_execution(s
struct pt_regs *regs, struct kprobe_ctlblk *kcb)
{
unsigned long *tos = (unsigned long *)&regs->esp;
- unsigned long copy_eip = (unsigned long)&p->ainsn.insn;
+ unsigned long copy_eip = (unsigned long)p->ainsn.insn;
unsigned long orig_eip = (unsigned long)p->addr;

regs->eflags &= ~TF_MASK;
diff -puN include/asm-i386/kprobes.h~kprobes-i386-fix-nx-protection-fault include/asm-i386/kprobes.h
--- linux-2.6.16-rc4-mm1/include/asm-i386/kprobes.h~kprobes-i386-fix-nx-protection-fault 2006-02-22 09:45:37.000000000 +0530
+++ linux-2.6.16-rc4-mm1-prasanna/include/asm-i386/kprobes.h 2006-02-22 09:45:37.000000000 +0530
@@ -27,6 +27,9 @@
#include <linux/types.h>
#include <linux/ptrace.h>

+#define __ARCH_WANT_KPROBES_INSN_SLOT
+
+struct kprobe;
struct pt_regs;

typedef u8 kprobe_opcode_t;
@@ -41,14 +44,14 @@ typedef u8 kprobe_opcode_t;

#define JPROBE_ENTRY(pentry) (kprobe_opcode_t *)pentry
#define ARCH_SUPPORTS_KRETPROBES
-#define arch_remove_kprobe(p) do {} while (0)

+void arch_remove_kprobe(struct kprobe *p);
void kretprobe_trampoline(void);

/* Architecture specific copy of original instruction*/
struct arch_specific_insn {
/* copy of the original instruction */
- kprobe_opcode_t insn[MAX_INSN_SIZE];
+ kprobe_opcode_t *insn;
/*
* If this flag is not 0, this kprobe can be boost when its
* post_handler and break_handler is not set.

_
--
Prasanna S Panchamukhi
Linux Technology Center
India Software Labs, IBM Bangalore
Email: prasanna@xxxxxxxxxx
Ph: 91-80-51776329
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/