kprobes for 2.5.50-bk2
PATCH 1/1 kprobes for 2.5.50-bk2
Linus,
Here is the kprobes patch for 2.5.50-bk2. This is the same patch Rusty Russell has been sending you for a while.
This has incorporated all your feedback and DaveM's (who wanted the arch-indep bits for sparc).
kprobes allows trapping at almost any kernel address, useful for various kernel-hacking tasks, and building on for more infrastructure. This patch is x86 only, but other archs can add support as required (s390 and ppc support is almost done, will be submitted once this patch is in).
Please apply.
Thanks,
Vamsi.
[vamsi@vamsiks] ~$ diffstat /patches/kprobes-2550-bk2-1.patch
arch/i386/Kconfig | 9 ++ arch/i386/kernel/Makefile | 1 arch/i386/kernel/entry.S | 22 +++++- arch/i386/kernel/kprobes.c | 160 +++++++++++++++++++++++++++++++++++++++++++++ arch/i386/kernel/traps.c | 36 ++++++++-- arch/i386/mm/fault.c | 4 + include/asm-i386/kprobes.h | 34 +++++++++ include/linux/kprobes.h | 60 ++++++++++++++++ kernel/Makefile | 3 kernel/kprobes.c | 89 +++++++++++++++++++++++++ 10 files changed, 406 insertions(+), 12 deletions(-)
--
arch/i386/Kconfig +9 -0
@@ -1551,6 +1551,15 @@ Say Y here if you are developing drivers or trying to debug and identify kernel problems. +config KPROBES + bool "Kprobes" + depends on DEBUG_KERNEL + help + Kprobes allows you to trap at almost any kernel address, using + register_kprobe(), and providing a callback function. This is useful + for kernel debugging, non-intrusive instrumentation and testing. If + in doubt, say "N". + config DEBUG_STACKOVERFLOW bool "Check for stack overflows" depends on DEBUG_KERNEL
arch/i386/kernel/entry.S +18 -4
@@ -403,9 +403,16 @@ jmp ret_from_exception ENTRY(debug) + pushl $-1 # mark this as an int + SAVE_ALL + movl %esp,%edx pushl $0 - pushl $do_debug - jmp error_code + pushl %edx + call do_debug + addl $8,%esp + testl %eax,%eax + jnz restore_all + jmp ret_from_exception ENTRY(nmi) pushl %eax
@@ -418,9 +425,16 @@ RESTORE_ALL ENTRY(int3) + pushl $-1 # mark this as an int + SAVE_ALL + movl %esp,%edx pushl $0 - pushl $do_int3 - jmp error_code + pushl %edx + call do_int3 + addl $8,%esp + testl %eax,%eax + jnz restore_all + jmp ret_from_exception ENTRY(overflow) pushl $0
arch/i386/kernel/kprobes.c +160 -0
160 lines not on this page · raw message
arch/i386/kernel/Makefile +1 -0
@@ -29,6 +29,7 @@ obj-$(CONFIG_PROFILING) += profile.o obj-$(CONFIG_EDD) += edd.o obj-$(CONFIG_MODULES) += module.o +obj-$(CONFIG_KPROBES) += kprobes.o EXTRA_AFLAGS := -traditional
arch/i386/kernel/traps.c +29 -7
@@ -24,6 +24,7 @@#include <linux/interrupt.h> #include <linux/highmem.h> #include <linux/kallsyms.h> +#include <linux/kprobes.h> #ifdef CONFIG_EISA #include <linux/ioport.h>
@@ -404,7 +405,6 @@ } DO_VM86_ERROR_INFO( 0, SIGFPE, "divide error", divide_error, FPE_INTDIV, regs->eip) -DO_VM86_ERROR( 3, SIGTRAP, "int3", int3) DO_VM86_ERROR( 4, SIGSEGV, "overflow", overflow) DO_VM86_ERROR( 5, SIGSEGV, "bounds", bounds)DO_ERROR_INFO (6 ,SIGILL ,"invalid operand" , invalid_op,ILL_ILLOPN , regs->eip)
@@ -420,6 +420,9 @@ {if (regs->eflags &VM_MASK ) goto gp_in_vm86; + +if (kprobe_running () &&kprobe_fault_handler (regs,13 )) +return ;if (!(regs->xcs &3 )) goto gp_in_kernel;
@@ -551,6 +554,17 @@ nmi_callback = dummy_nmi_callback; } +asmlinkage int do_int3(struct pt_regs *regs, long error_code) +{ +if (kprobe_handler (regs)) +return 1 ; +/* This is an interrupt gate, because kprobes wants interrupts +disabled. Normal trap handlers don't. */ +restore_interrupts (regs); +do_trap (3 ,SIGTRAP ,"int3" ,1 , regs, error_code,NULL ); +return 0 ; +} +/* * Our handling of the processor debug registers is non-trivial. * We do not clear them on entry and exit from the kernel. Therefore
@@ -573,7 +587,7 @@* find every occurrence of the TF bit that could be saved away even * by user code) */ -asmlinkage void do_debug(struct pt_regs * regs, long error_code) +asmlinkage int do_debug(struct pt_regs * regs, long error_code) {unsigned int condition;struct task_struct *tsk = current;
@@ -581,6 +595,12 @@ __asm__ __volatile__("movl %%db6,%0" :"=r" (condition)); +if (post_kprobe_handler (regs)) +return 1 ; + +/* Interrupts not disabled for normal trap handling. */ +restore_interrupts (regs); +/* Mask out spurious debug traps due to lazy DR7 setting */ if (condition & (DR_TRAP0 |DR_TRAP1 |DR_TRAP2 |DR_TRAP3 )) {if (!tsk->thread.debugreg[7 ])
@@ -631,15 +651,15 @@ __asm__("movl %0,%%db7" :/* no output */ :"r" (0 )); -return ; +return 0 ; debug_vm86:handle_vm86_trap ((struct kernel_vm86_regs *) regs, error_code,1 ); -return ; +return 0 ; clear_TF: regs->eflags &= ~TF_MASK ; -return ; +return 0 ; }/*
@@ -803,6 +823,8 @@struct task_struct *tsk = current;clts ();/* Allow maths ops (or we recurse) */ +if (kprobe_running () &&kprobe_fault_handler (®s,7 )) +return ;if (!tsk->used_math)init_fpu (tsk);restore_fpu (tsk);
@@ -896,9 +918,9 @@#endif set_trap_gate (0 ,÷_error); -set_trap_gate (1 ,&debug); +_set_gate (idt_table+1 ,14 ,3 ,&debug);/* debug trap for kprobes */ set_intr_gate (2 ,&nmi); -set_system_gate (3 ,&int3);/* int3-5 can be called from all */ +_set_gate (idt_table+3 ,14 ,3 ,&int3);/* int3-5 can be called from all */ set_system_gate (4 ,&overflow);set_system_gate (5 ,&bounds);set_trap_gate (6 ,&invalid_op);
arch/i386/mm/fault.c +4 -0
@@ -19,6 +19,7 @@#include <linux/init.h> #include <linux/tty.h> #include <linux/vt_kern.h> /* For unblank_screen() */ +#include <linux/kprobes.h> #include <asm/system.h> #include <asm/uaccess.h>
@@ -163,6 +164,9 @@/* get the address */ __asm__("movl %%cr2,%0" :"=r" (address)); +if (kprobe_running () &&kprobe_fault_handler (regs,14 )) +return ; +/* It's safe to allow irq's after cr2 has been saved */ if (regs->eflags &X86_EFLAGS_IF )local_irq_enable ();
include/asm-i386/kprobes.h +34 -0
@@ -0,0 +1,34 @@ +#ifndef _ASM_KPROBES_H +#define _ASM_KPROBES_H +/* +* Dynamic Probes (kprobes) support +* Vamsi Krishna S <[email protected]>, July, 2002 +* Mailing list: [email protected] +*/ +#include <linux/types.h> +#include <linux/ptrace.h> + +struct pt_regs ; + +typedef u8 kprobe_opcode_t ; +#define BREAKPOINT_INSTRUCTION 0xcc + +/* trap3/1 are intr gates for kprobes. So, restore the status of IF, +* if necessary, before executing the original int3/1 (trap) handler. +*/ +static inline void restore_interrupts (struct pt_regs *regs) +{ +if (regs->eflags &IF_MASK ) + __asm__ __volatile__ ("sti" ); +} + +#ifdef CONFIG_KPROBES +extern int kprobe_fault_handler (struct pt_regs *regs,int trapnr); +extern int post_kprobe_handler (struct pt_regs *regs); +extern int kprobe_handler (struct pt_regs *regs); +#else /* !CONFIG_KPROBES */ +static inline int kprobe_fault_handler (struct pt_regs *regs,int trapnr) {return 0 ; } +static inline int post_kprobe_handler (struct pt_regs *regs) {return 0 ; } +static inline int kprobe_handler (struct pt_regs *regs) {return 0 ; } +#endif +#endif /* _ASM_KPROBES_H */
include/linux/kprobes.h +60 -0
60 lines not on this page · raw message
kernel/kprobes.c +89 -0
89 lines not on this page · raw message
kernel/Makefile +2 -1
@@ -4,7 +4,7 @@ export-objs = signal.o sys.o kmod.o workqueue.o ksyms.o pm.o exec_domain.o \ printk.o platform.o suspend.o dma.o module.o cpufreq.o \ - profile.o rcupdate.o intermodule.o + profile.o rcupdate.o intermodule.o kprobes.o obj-y = sched.o fork.o exec_domain.o panic.o printk.o profile.o \ exit.o itimer.o time.o softirq.o resource.o \
@@ -21,6 +21,7 @@ obj-$(CONFIG_CPU_FREQ) += cpufreq.o obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o obj-$(CONFIG_SOFTWARE_SUSPEND) += suspend.o +obj-$(CONFIG_KPROBES) += kprobes.o ifneq ($(CONFIG_IA64),y) # According to Alan Modra <[email protected]>, the -fno-omit-frame-pointer is
Quoted 3 lines · Vamsi Krishna S .
kprobes allows trapping at almost any kernel address, useful for various kernel-hacking tasks, and building on for more infrastructure.
This last part just got me thinking.
What stops someone for example using this to implement a binary only replacement of the TCP/IP stack, or any other part of the kernel for that matter ?
Dave
Signature · 2 lines
| Dave Jones. http://www.codemonkey.org.uk | SuSE Labs