From 726e53a50084b938f3a57197a3c6ced1d081c789 Mon Sep 17 00:00:00 2001 From: Ekaterina Gorelkina Date: Tue, 10 Aug 2010 14:12:34 +0400 Subject: [PATCH] Porting KProbe & build procedure for DTV environment (2.6.18 kernel version) --- driver/Makefile | 4 ++-- kprobe/Makefile | 4 ++-- kprobe/kprobes.c | 60 +++++++++++++++++++++++++++++++++++++++++---------- kprobe/kprobes_arch.c | 6 ++++++ 4 files changed, 59 insertions(+), 15 deletions(-) diff --git a/driver/Makefile b/driver/Makefile index 2b23686..9ec4986 100644 --- a/driver/Makefile +++ b/driver/Makefile @@ -5,10 +5,10 @@ cross_compiler = $(subst gcc,,$(CC)) all-local: cp $(top_srcdir)/src/modules/kprobe/Module.symvers $(driver_module_dir) - CROSS_COMPILE=$(cross_compiler) $(MAKE) ARCH=arm memchecker=$(memchecker) $(AM_MAKEFLAGS) -C $(target_kernel_src) M=$(driver_module_dir) modules + $(MAKE) CROSS_COMPILE=$(cross_compiler) ARCH=arm memchecker=$(memchecker) $(AM_MAKEFLAGS) -C $(target_kernel_src) M=$(driver_module_dir) modules clean-local: - CROSS_COMPILE=$(cross_compiler) $(MAKE) ARCH=arm $(AM_MAKEFLAGS) -C $(target_kernel_src) M=$(driver_module_dir) clean + $(MAKE) CROSS_COMPILE=$(cross_compiler) ARCH=arm $(AM_MAKEFLAGS) -C $(target_kernel_src) M=$(driver_module_dir) clean install-exec-local: install -m 644 $(driver_module_dir)/$(module_name).ko $(prefix) diff --git a/kprobe/Makefile b/kprobe/Makefile index cf35e70..475b5a8 100644 --- a/kprobe/Makefile +++ b/kprobe/Makefile @@ -4,10 +4,10 @@ module_name = inperfa_kprobe cross_compiler = $(subst gcc,,$(CC)) all-local: - CROSS_COMPILE=$(cross_compiler) $(MAKE) ARCH=arm $(AM_MAKEFLAGS) -C $(target_kernel_src) M=$(kprobes_module_dir) modules + $(MAKE) CROSS_COMPILE=$(cross_compiler) ARCH=arm $(AM_MAKEFLAGS) -C $(target_kernel_src) M=$(kprobes_module_dir) modules clean-local: - CROSS_COMPILE=$(cross_compiler) $(MAKE) ARCH=arm $(AM_MAKEFLAGS) -C $(target_kernel_src) M=$(kprobes_module_dir) clean + $(MAKE) CROSS_COMPILE=$(cross_compiler) ARCH=arm $(AM_MAKEFLAGS) -C $(target_kernel_src) M=$(kprobes_module_dir) clean install-exec-local: install -m 644 $(kprobes_module_dir)/$(module_name).ko $(prefix) diff --git a/kprobe/kprobes.c b/kprobe/kprobes.c index a852592..9f6e39f 100644 --- a/kprobe/kprobes.c +++ b/kprobe/kprobes.c @@ -1301,7 +1301,7 @@ unregister_all_uprobes (struct task_struct *task, int atomic) #define GUP_FLAGS_IGNORE_VMA_PERMISSIONS 0x4 #define GUP_FLAGS_IGNORE_SIGKILL 0x8 - +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18) static inline int use_zero_page(struct vm_area_struct *vma) { /* @@ -1318,6 +1318,7 @@ static inline int use_zero_page(struct vm_area_struct *vma) */ return !vma->vm_ops || !vma->vm_ops->fault; } +#endif int __get_user_pages_uprobe(struct task_struct *tsk, struct mm_struct *mm, unsigned long start, int len, int flags, @@ -1393,8 +1394,13 @@ int __get_user_pages_uprobe(struct task_struct *tsk, struct mm_struct *mm, return i ? : -EFAULT; if (is_vm_hugetlb_page(vma)) { +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,18) + i = follow_hugetlb_page(mm, vma, pages, vmas, + &start, &len, i); +#else i = follow_hugetlb_page(mm, vma, pages, vmas, &start, &len, i, write); +#endif continue; } @@ -1402,14 +1408,17 @@ int __get_user_pages_uprobe(struct task_struct *tsk, struct mm_struct *mm, if (pages) foll_flags |= FOLL_GET; +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18) #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,30) if (!write && use_zero_page(vma)) foll_flags |= FOLL_ANON; #endif +#endif do { struct page *page; +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18) /* * If we have a pending SIGKILL, don't keep faulting * pages and potentially allocating memory, unless @@ -1420,6 +1429,7 @@ int __get_user_pages_uprobe(struct task_struct *tsk, struct mm_struct *mm, if (unlikely(!ignore_sigkill && fatal_signal_pending(current))) return i ? i : -ERESTARTSYS; +#endif if (write) foll_flags |= FOLL_WRITE; @@ -1432,18 +1442,39 @@ int __get_user_pages_uprobe(struct task_struct *tsk, struct mm_struct *mm, int ret; ret = handle_mm_fault(mm, vma, start, foll_flags & FOLL_WRITE); + +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,18) + if (ret & VM_FAULT_WRITE) + foll_flags &= ~FOLL_WRITE; + + switch (ret & ~VM_FAULT_WRITE) { + case VM_FAULT_MINOR: + tsk->min_flt++; + break; + case VM_FAULT_MAJOR: + tsk->maj_flt++; + break; + case VM_FAULT_SIGBUS: + return i ? i : -EFAULT; + case VM_FAULT_OOM: + return i ? i : -ENOMEM; + default: + BUG(); + } + +#else if (ret & VM_FAULT_ERROR) { - if (ret & VM_FAULT_OOM) - return i ? i : -ENOMEM; - else if (ret & VM_FAULT_SIGBUS) - return i ? i : -EFAULT; - BUG(); + if (ret & VM_FAULT_OOM) + return i ? i : -ENOMEM; + else if (ret & VM_FAULT_SIGBUS) + return i ? i : -EFAULT; + BUG(); } if (ret & VM_FAULT_MAJOR) - tsk->maj_flt++; + tsk->maj_flt++; else - tsk->min_flt++; - + tsk->min_flt++; + /* * The VM_FAULT_WRITE bit tells us that * do_wp_page has broken COW when necessary, @@ -1458,16 +1489,23 @@ int __get_user_pages_uprobe(struct task_struct *tsk, struct mm_struct *mm, */ if ((ret & VM_FAULT_WRITE) && !(vma->vm_flags & VM_WRITE)) - foll_flags &= ~FOLL_WRITE; - + foll_flags &= ~FOLL_WRITE; + //cond_resched(); +#endif + } + if (IS_ERR(page)) return i ? i : PTR_ERR(page); if (pages) { pages[i] = page; +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,18) + flush_anon_page(page, start); +#else flush_anon_page(vma, page, start); +#endif flush_dcache_page(page); } if (vmas) diff --git a/kprobe/kprobes_arch.c b/kprobe/kprobes_arch.c index 51426ee..d2804e6 100644 --- a/kprobe/kprobes_arch.c +++ b/kprobe/kprobes_arch.c @@ -3091,11 +3091,13 @@ DECLARE_MOD_FUNC_DEP(access_process_vm, int, struct task_struct * tsk, unsigned DECLARE_MOD_FUNC_DEP(find_extend_vma, struct vm_area_struct *, struct mm_struct * mm, unsigned long addr); +#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 18) #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 30) DECLARE_MOD_FUNC_DEP(handle_mm_fault, int, struct mm_struct *mm, struct vm_area_struct *vma, unsigned long address, int write_access); #else DECLARE_MOD_FUNC_DEP(handle_mm_fault, int, struct mm_struct *mm, struct vm_area_struct *vma, unsigned long address, unsigned int flags); #endif +#endif DECLARE_MOD_FUNC_DEP(get_gate_vma, struct vm_area_struct *, struct task_struct *tsk); DECLARE_MOD_FUNC_DEP(in_gate_area_no_task, int, unsigned long addr); @@ -3159,6 +3161,7 @@ IMP_MOD_DEP_WRAPPER(access_process_vm, tsk, addr, buf, len, write) DECLARE_MOD_DEP_WRAPPER (find_extend_vma, struct vm_area_struct *, struct mm_struct * mm, unsigned long addr) IMP_MOD_DEP_WRAPPER (find_extend_vma, mm, addr) +#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 18) #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 30) DECLARE_MOD_DEP_WRAPPER (handle_mm_fault, int, struct mm_struct *mm, struct vm_area_struct *vma, unsigned long address, int write_access) IMP_MOD_DEP_WRAPPER (handle_mm_fault, mm, vma, address, write_access) @@ -3166,6 +3169,7 @@ IMP_MOD_DEP_WRAPPER (handle_mm_fault, mm, vma, address, write_access) DECLARE_MOD_DEP_WRAPPER (handle_mm_fault, int, struct mm_struct *mm, struct vm_area_struct *vma, unsigned long address, unsigned int flags) IMP_MOD_DEP_WRAPPER (handle_mm_fault, mm, vma, address, flags) #endif +#endif DECLARE_MOD_DEP_WRAPPER (get_gate_vma, struct vm_area_struct *, struct task_struct *tsk) IMP_MOD_DEP_WRAPPER (get_gate_vma, tsk) @@ -3278,7 +3282,9 @@ int __init arch_init_kprobes (void) sched_addr = (kprobe_opcode_t *)kallsyms_search("__switch_to");//"schedule"); fork_addr = (kprobe_opcode_t *)kallsyms_search("do_fork"); +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 18)) INIT_MOD_DEP_VAR(handle_mm_fault, handle_mm_fault); +#endif INIT_MOD_DEP_VAR(flush_ptrace_access, flush_ptrace_access); INIT_MOD_DEP_VAR(find_extend_vma, find_extend_vma); INIT_MOD_DEP_VAR(get_gate_vma, get_gate_vma); -- 2.7.4