From: Vyacheslav Cherkashin Date: Thu, 24 Jan 2013 14:22:24 +0000 (+0400) Subject: add 'swap_ksyms' module X-Git-Tag: Tizen_SDK_2.3~721 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=f9c21080d47b4f43bc4b128bc2e21f3ad6204589;p=kernel%2Fswap-modules.git add 'swap_ksyms' module --- diff --git a/driver/Kbuild b/driver/Kbuild index 1a4ab38..4d01ba9 100644 --- a/driver/Kbuild +++ b/driver/Kbuild @@ -1,4 +1,4 @@ -EXTRA_CFLAGS := -I$(src)/../../common -I$(src)/../../profile -DEC_ARCH_$(ARCH) -D__DEBUG $(memchecker) $(debug_opt) $(android_opt) $(slp_opt) $(android_app_opt) $(board_opt) +EXTRA_CFLAGS := $(extra_cflags) obj-m := swap_driver.o swap_driver-y := device_driver.o ec.o legacy.o module.o probes.o probes_manager.o storage.o us_proc_inst.o diff --git a/driver/Makefile.am b/driver/Makefile.am index 303cc68..4aa4f95 100644 --- a/driver/Makefile.am +++ b/driver/Makefile.am @@ -30,11 +30,14 @@ driver_module_dir = $(realpath $(srcdir)) module_name = swap_driver cross_compiler = $(subst gcc,,$(CC)) +inlude_opt = -I$(top_srcdir)/src/modules/ksyms -I$(top_srcdir)/src/common -I$(top_srcdir)/src/profile +extra_cflags = "$(inlude_opt) -DEC_ARCH_$(ARCH) -D__DEBUG $(memchecker) $(debug_opt) $(android_opt) $(slp_opt) $(android_app_opt) $(board_opt)" + #bin_SCRIPTS = patchko.sh insmod.sh all-local: cp $(top_srcdir)/src/modules/kprobe/Module.symvers $(driver_module_dir) - $(MAKE) CROSS_COMPILE=$(cross_compiler) ARCH=$(target_arch) memchecker=$(memchecker) android_opt=$(android_opt) slp_opt=$(slp_opt) android_app_opt=$(android_app_opt) board_opt=$(board_opt) debug_opt=$(debug_opt) $(AM_MAKEFLAGS) -C $(target_kernel_src) M=$(driver_module_dir) modules + $(MAKE) CROSS_COMPILE=$(cross_compiler) ARCH=$(target_arch) extra_cflags=$(extra_cflags) $(AM_MAKEFLAGS) -C $(target_kernel_src) M=$(driver_module_dir) modules echo "generate data for version patching <$(OBJDUMP)><$(READELF)>" $(top_srcdir)/src/modules/driver/patchko.sh -g $(driver_module_dir)/$(module_name).ko $(OBJDUMP) $(READELF) diff --git a/driver/handlers_core.h b/driver/handlers_core.h index 02d3c40..d708fac 100644 --- a/driver/handlers_core.h +++ b/driver/handlers_core.h @@ -37,6 +37,7 @@ struct dbi_modules_handlers_info { void * dbi_module_callback_stop; int dbi_module_priority_start; int dbi_module_priority_stop; + void * (*get_uprobes)(void); }; extern int dbi_register_handlers_module(struct dbi_modules_handlers_info *dbi_mhi); diff --git a/driver/module.c b/driver/module.c index 00e2472..172e9e8 100644 --- a/driver/module.c +++ b/driver/module.c @@ -8,7 +8,7 @@ // SEE ALSO: module.h // AUTHOR: L.Komkov, A.Gerenkov // COMPANY NAME: Samsung Research Center in Moscow -// DEPT NAME: Advanced Software Group +// DEPT NAME: Advanced Software Group // CREATED: 2008.02.15 // VERSION: 1.0 // REVISION DATE: 2008.12.03 @@ -64,10 +64,6 @@ void (*flush_cache_page) (struct vm_area_struct * vma, unsigned long page); static int __init InitializeModule(void) { - if(lookup_name == NULL) { - EPRINTF("fp_kallsyms_lookup_name parameter undefined!"); - return -1; - } if(device_name == NULL) { EPRINTF("Using default device name!"); device_name = gl_szDefaultDeviceName; @@ -77,7 +73,7 @@ static int __init InitializeModule(void) device_major = DEFAULT_DEVICE_MAJOR; } - __real_put_task_struct = (void *) lookup_name (SWAPDRV_PUT_TASK_STRUCT); + __real_put_task_struct = (void *)swap_ksyms(SWAPDRV_PUT_TASK_STRUCT); if (!__real_put_task_struct) { EPRINTF (SWAPDRV_PUT_TASK_STRUCT " is not found! Oops. Where is it?"); @@ -85,7 +81,7 @@ static int __init InitializeModule(void) } #if defined(CONFIG_MIPS) - flush_cache_page = (void *) lookup_name ("r4k_flush_cache_page"); + flush_cache_page = (void *)swap_ksyms("r4k_flush_cache_page"); if (!flush_cache_page) { EPRINTF ("failed to resolve 'flush_cache_page'!\n"); diff --git a/driver/module.h b/driver/module.h index da0ffee..fe77472 100644 --- a/driver/module.h +++ b/driver/module.h @@ -7,7 +7,7 @@ // SEE ALSO: module.c // AUTHOR: L.Komkov, A.Gerenkov // COMPANY NAME: Samsung Research Center in Moscow -// DEPT NAME: Advanced Software Group +// DEPT NAME: Advanced Software Group // CREATED: 2008.02.15 // VERSION: 1.0 // REVISION DATE: 2008.12.03 @@ -75,11 +75,6 @@ extern char *device_name; extern unsigned int device_major; -typedef unsigned long (*fp_kallsyms_lookup_name_t) (const char *name); - -//export by swap_kprobes.ko -extern fp_kallsyms_lookup_name_t lookup_name; - struct handler_map { unsigned long func_addr; unsigned long jp_handler_addr; diff --git a/driver/probes_manager.c b/driver/probes_manager.c index 3c748c0..6ca7abe 100644 --- a/driver/probes_manager.c +++ b/driver/probes_manager.c @@ -16,6 +16,7 @@ //////////////////////////////////////////////////////////////////////////////////// #include +#include #include "module.h" #include "probes_manager.h" @@ -54,36 +55,31 @@ probes_manager_init (void) spin_lock_init(&ec_spinlock); spin_lock_init(&ec_probe_spinlock); #endif /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 38) */ -#ifdef CONFIG_X86 - //pf_addr = lookup_name("handle_mm_fault"); - pf_addr = lookup_name("do_page_fault"); -#else - pf_addr = lookup_name("do_page_fault"); -#endif + pf_addr = swap_ksyms("do_page_fault"); if (pf_addr == 0) { EPRINTF("Cannot find address for page fault function!"); return -EINVAL; } - cp_addr = lookup_name("copy_process"); + cp_addr = swap_ksyms("copy_process"); if (cp_addr == 0) { EPRINTF("Cannot find address for copy_process function!"); return -EINVAL; } - mr_addr = lookup_name("mm_release"); + mr_addr = swap_ksyms("mm_release"); if (mr_addr == 0) { EPRINTF("Cannot find address for mm_release function!"); return -EINVAL; } - exit_addr = lookup_name("do_exit"); + exit_addr = swap_ksyms("do_exit"); if (exit_addr == 0) { EPRINTF("Cannot find address for do_exit function!"); return -EINVAL; } - unmap_addr = lookup_name("do_munmap"); + unmap_addr = swap_ksyms("do_munmap"); if (unmap_addr == 0) { EPRINTF("Cannot find address for do_munmap function!"); return -EINVAL; @@ -518,16 +514,17 @@ void dbi_install_user_handlers(void) struct hlist_node *node; unsigned long pre_handler_addr, jp_handler_addr, rp_handler_addr; + // FIXME: functions 'find_jp_handler', 'find_rp_handler', 'find_pre_handler' - not found /* We must perform this lookup whenever this function is called * because the addresses of find_*_handler functions may differ. */ // swap_handlers removed unsigned long (*find_jp_handler)(unsigned long) = // swap_handlers removed - (unsigned long (*)(unsigned long))lookup_name("find_jp_handler"); + (unsigned long (*)(unsigned long))swap_ksyms("find_jp_handler"); unsigned long (*find_rp_handler)(unsigned long) = - (unsigned long (*)(unsigned long))lookup_name("find_rp_handler"); + (unsigned long (*)(unsigned long))swap_ksyms("find_rp_handler"); unsigned long (*find_pre_handler)(unsigned long) = - (unsigned long (*)(unsigned long))lookup_name("find_pre_handler"); + (unsigned long (*)(unsigned long))swap_ksyms("find_pre_handler"); hlist_for_each_entry_rcu (probe, node, &kernel_probes, hlist) { if(find_pre_handler) { diff --git a/driver/storage.c b/driver/storage.c index 8d42da5..da0fa40 100644 --- a/driver/storage.c +++ b/driver/storage.c @@ -161,18 +161,10 @@ int dbi_register_handlers_module(struct dbi_modules_handlers_info *dbi_mhi) // struct dbi_modules_handlers_info *local_mhi; int i=0; int nr_handlers=dbi_mhi->dbi_nr_handlers; - printk ("lookup_name=0x%08x\n", lookup_name); - if ( lookup_name != NULL){ - for (i=0;idbi_handlers[i].func_addr = (void (*)(pte_t) ) lookup_name (dbi_mhi->dbi_handlers[i].func_name); - printk("[0x%08x]-%s\n",dbi_mhi->dbi_handlers[i].func_addr,dbi_mhi->dbi_handlers[i].func_name); - } - } - else - { - printk("[ERROR] lookup_name is NULL\n"); + for (i = 0; i < nr_handlers; ++i) { + dbi_mhi->dbi_handlers[i].func_addr = swap_ksyms(dbi_mhi->dbi_handlers[i].func_name); + printk("[0x%08x]-%s\n", dbi_mhi->dbi_handlers[i].func_addr, dbi_mhi->dbi_handlers[i].func_name); } spin_lock_irqsave(&dbi_mh.lock, dbi_flags); @@ -221,6 +213,31 @@ int dbi_unregister_handlers_module(struct dbi_modules_handlers_info *dbi_mhi) } EXPORT_SYMBOL_GPL(dbi_unregister_handlers_module); +static inst_us_proc_t empty_uprobes_info = +{ + .libs_count = 0, + .p_libs = NULL, +}; + +static inst_us_proc_t *get_uprobes(void) +{ + unsigned long dbi_flags; + inst_us_proc_t *ret = &empty_uprobes_info; + struct dbi_modules_handlers_info *mhi; + struct list_head *head = &dbi_mh.modules_handlers; + + spin_lock_irqsave(&dbi_mh.lock, dbi_flags); + list_for_each_entry_rcu(mhi, head, dbi_list_head) { + if (mhi->get_uprobes) { + ret = mhi->get_uprobes(); + break; + } + } + spin_unlock_irqrestore(&dbi_mh.lock, dbi_flags); + + return ret; +} + EXPORT_SYMBOL_GPL(us_proc_info); EXPORT_SYMBOL_GPL(dex_proc_info); typedef void *(*get_my_uprobes_info_t)(void); @@ -607,13 +624,7 @@ extern struct dentry *dentry_by_path(const char *path); int link_bundle() { - get_my_uprobes_info_t get_uprobes = NULL; - inst_us_proc_t *my_uprobes_info = 0; - inst_us_proc_t empty_uprobes_info = - { - .libs_count = 0, - .p_libs = NULL, - }; + inst_us_proc_t *my_uprobes_info = get_uprobes(); char *p = bundle; /* read pointer for bundle */ int nr_kern_probes; int i, j, l, k; @@ -631,15 +642,6 @@ int link_bundle() int lib_name_len; int handler_index; - - /* Get user-defined us handlers (if they are provided) */ - get_uprobes = (get_my_uprobes_info_t)lookup_name("get_my_uprobes_info"); - if (get_uprobes) - my_uprobes_info = (inst_us_proc_t *)get_uprobes(); - - if (my_uprobes_info == 0) - my_uprobes_info = &empty_uprobes_info; - DPRINTF("Going to release us_proc_info"); if (us_proc_info.path) unlink_bundle(); @@ -1357,7 +1359,8 @@ int put_us_event (char *data, unsigned long len) } else { - mec_post_event = lookup_name("mec_post_event"); + // FIXME: 'mec_post_event' - not found + mec_post_event = swap_ksyms("mec_post_event"); if(mec_post_event == NULL) { EPRINTF ("Failed to find function 'mec_post_event' from mec_handlers.ko. Memory Error Checker will work incorrectly."); @@ -1448,22 +1451,7 @@ int set_predef_uprobes (ioctl_predef_uprobes_info_t *data) { int i, k, size = 0, probe_size, result, j; char *buf, *sep1, *sep2; - get_my_uprobes_info_t get_uprobes = NULL; - inst_us_proc_t *my_uprobes_info = NULL; - - inst_us_proc_t empty_uprobes_info = - { - .libs_count = 0, - .p_libs = NULL, - }; - - get_uprobes = (get_my_uprobes_info_t)lookup_name("get_my_uprobes_info"); - if (get_uprobes) - my_uprobes_info = (inst_us_proc_t *)get_uprobes(); - - DPRINTF("my_uprobes_info lookup result: 0x%p", my_uprobes_info); - if (my_uprobes_info == 0) - my_uprobes_info = &empty_uprobes_info; + inst_us_proc_t *my_uprobes_info = get_uprobes(); for(j = 0; j < data->probes_count; j++) { @@ -1521,21 +1509,7 @@ int set_predef_uprobes (ioctl_predef_uprobes_info_t *data) int get_predef_uprobes_size(int *size) { int i, k; - get_my_uprobes_info_t get_uprobes = NULL; - inst_us_proc_t *my_uprobes_info = NULL; - - inst_us_proc_t empty_uprobes_info = - { - .libs_count = 0, - .p_libs = NULL, - }; - - get_uprobes = (get_my_uprobes_info_t)lookup_name("get_my_uprobes_info"); - if (get_uprobes) - my_uprobes_info = (inst_us_proc_t *)get_uprobes(); - - if (my_uprobes_info == 0) - my_uprobes_info = &empty_uprobes_info; + inst_us_proc_t *my_uprobes_info = get_uprobes(); *size = 0; for(i = 0; i < my_uprobes_info->libs_count; i++) @@ -1557,22 +1531,7 @@ int get_predef_uprobes(ioctl_predef_uprobes_info_t *udata) int i, k, size, lib_size, func_size, result; unsigned count = 0; char sep[] = ":"; - - inst_us_proc_t empty_uprobes_info = - { - .libs_count = 0, - .p_libs = NULL, - }; - - get_my_uprobes_info_t get_uprobes = NULL; - inst_us_proc_t *my_uprobes_info = NULL; - - get_uprobes = (get_my_uprobes_info_t)lookup_name("get_my_uprobes_info"); - if (get_uprobes) - my_uprobes_info = (inst_us_proc_t *)get_uprobes(); - - if (my_uprobes_info == 0) - my_uprobes_info = &empty_uprobes_info; + inst_us_proc_t *my_uprobes_info = get_uprobes(); // get addr of array if (copy_from_user ((void *)&data, udata, sizeof (data))) diff --git a/driver/swap_driver.sh b/driver/swap_driver.sh index 4993ff7..1837f63 100755 --- a/driver/swap_driver.sh +++ b/driver/swap_driver.sh @@ -14,22 +14,6 @@ DEVICE_NAME=${DEVICE} # name of the device DEVICE_FILE=__DEV_DIR__/${DEVICE} -KSYMS=kallsyms_lookup_name - -# ADDRESS for "kallsyms_lookup_name" function taken from /proc/kallsyms -ADDRESS=0x`sed "/ kallsyms_lookup_name/ ! d" /proc/kallsyms | sed "s/ T kallsyms_lookup_name//"` - -if [ "${ADDRESS}" = "0x" ]; then - if [ "$1" = "" ]; then - echo "Enter kallsyms_lookup_name as parameter:" - echo "insmod.sh " - exit - else - ADDRESS=$1 - echo "kallsyms_lookup_name address is ${ADDRESS}" - fi -fi - MAJOR=`sed "/${DEVICE_NAME}/ ! d" /proc/devices | sed "s/ ${DEVICE_NAME}//"` if [ "${MAJOR}" != "" ] ; then echo "SWAP Driver is already loaded!" diff --git a/kprobe/Kbuild b/kprobe/Kbuild index 8d92f8d..975a317 100644 --- a/kprobe/Kbuild +++ b/kprobe/Kbuild @@ -1,4 +1,4 @@ -EXTRA_CFLAGS := $(android_opt) $(board_opt) +EXTRA_CFLAGS := $(extra_cflags) obj-m := swap_kprobe.o swap_kprobe-y := dbi_kprobes_deps.o dbi_insn_slots.o dbi_uprobes.o arch/asm/dbi_kprobes.o arch/dbi_kprobes.o dbi_kprobes.o diff --git a/kprobe/Makefile.am b/kprobe/Makefile.am index 39eebd6..bc703e3 100644 --- a/kprobe/Makefile.am +++ b/kprobe/Makefile.am @@ -12,10 +12,12 @@ kprobes_module_dir = $(realpath $(top_srcdir)/src/modules/kprobe) module_name = swap_kprobe cross_compiler = $(subst gcc,,$(CC)) +inlude_opt = -I$(top_srcdir)/src/modules/ksyms +extra_cflags = "$(inlude_opt) $(android_opt) $(board_opt)" all-local: rm -f $(top_srcdir)/src/modules/kprobe/arch/asm && $(LN_S) asm-${target_arch} $(top_srcdir)/src/modules/kprobe/arch/asm - $(MAKE) CROSS_COMPILE=$(cross_compiler) ARCH=$(target_arch) android_opt=$(android_opt) board_opt=$(board_opt) $(AM_MAKEFLAGS) -C $(target_kernel_src) M=$(kprobes_module_dir) modules + $(MAKE) CROSS_COMPILE=$(cross_compiler) ARCH=$(target_arch) extra_cflags=$(extra_cflags) $(AM_MAKEFLAGS) -C $(target_kernel_src) M=$(kprobes_module_dir) modules echo "generate data for version patching <$(OBJDUMP)><$(READELF)>" diff --git a/kprobe/arch/asm-arm/dbi_kprobes.c b/kprobe/arch/asm-arm/dbi_kprobes.c index 152fc86..99d45b1 100644 --- a/kprobe/arch/asm-arm/dbi_kprobes.c +++ b/kprobe/arch/asm-arm/dbi_kprobes.c @@ -39,6 +39,7 @@ #include "../../dbi_insn_slots.h" #include "../../dbi_kprobes_deps.h" #include "../../dbi_uprobes.h" +#include #include @@ -63,8 +64,6 @@ extern struct kretprobe *sched_rp; extern struct hlist_head kprobe_insn_pages; extern struct hlist_head uprobe_insn_pages; -extern unsigned long (*kallsyms_search) (const char *name); - extern struct kprobe *kprobe_running(void); extern void reset_current_kprobe(void); extern struct kprobe_ctlblk *get_kprobe_ctlblk(void); @@ -1586,21 +1585,21 @@ int __init arch_init_kprobes (void) return -1; } - do_bp_handler = (unsigned int) kallsyms_search ("do_undefinstr"); + do_bp_handler = swap_ksyms("do_undefinstr"); if (do_bp_handler == 0) { DBPRINTF("no do_undefinstr symbol found!"); return -1; } arr_traps_template[NOTIFIER_CALL_CHAIN_INDEX] = arch_construct_brunch ((unsigned int)kprobe_handler, do_bp_handler + NOTIFIER_CALL_CHAIN_INDEX * 4, 1); // Register hooks (kprobe_handler) - do_kpro = (void *)kallsyms_search ("register_undef_hook"); + do_kpro = swap_ksyms("register_undef_hook"); if (do_kpro == 0) { printk("no register_undef_hook symbol found!\n"); return -1; } // Unregister hooks (kprobe_handler) - undo_kpro = (void *)kallsyms_search ("unregister_undef_hook"); + undo_kpro = swap_ksyms("unregister_undef_hook"); if (undo_kpro == 0) { printk("no unregister_undef_hook symbol found!\n"); return -1; diff --git a/kprobe/arch/asm-mips/dbi_kprobes.c b/kprobe/arch/asm-mips/dbi_kprobes.c index 52ced9a..ac97010 100644 --- a/kprobe/arch/asm-mips/dbi_kprobes.c +++ b/kprobe/arch/asm-mips/dbi_kprobes.c @@ -33,6 +33,7 @@ #include "../../dbi_insn_slots.h" #include "../../dbi_kprobes_deps.h" #include "../../dbi_uprobes.h" +#include #ifdef OVERHEAD_DEBUG #include @@ -55,8 +56,6 @@ extern struct kprobe *kprobe_running (void); extern struct kprobe_ctlblk *get_kprobe_ctlblk (void); extern void reset_current_kprobe (void); -extern unsigned long (*kallsyms_search) (const char *name); - #ifdef OVERHEAD_DEBUG unsigned long swap_sum_time = 0; unsigned long swap_sum_hit = 0; @@ -816,7 +815,7 @@ int __init arch_init_kprobes (void) return -1; } - do_bp_handler = (unsigned int) kallsyms_search ("do_bp"); + do_bp_handler = (unsigned int)swap_ksyms("do_bp"); kprobe_handler_addr = (unsigned int) &kprobe_handler; insns_num = sizeof (arr_traps_template) / sizeof (arr_traps_template[0]); @@ -855,7 +854,7 @@ void __exit dbi_arch_exit_kprobes (void) unsigned int code_size = 0; // Get instruction address - do_bp_handler = (unsigned int) kallsyms_search ("do_undefinstr"); + do_bp_handler = (unsigned int)swap_ksyms("do_undefinstr"); //dbi_unregister_jprobe(&do_exit_p, 0); diff --git a/kprobe/arch/asm-x86/dbi_kprobes.c b/kprobe/arch/asm-x86/dbi_kprobes.c index 14dc364..5771243 100644 --- a/kprobe/arch/asm-x86/dbi_kprobes.c +++ b/kprobe/arch/asm-x86/dbi_kprobes.c @@ -78,8 +78,6 @@ extern struct hlist_head uprobe_insn_pages; extern spinlock_t kretprobe_lock; -extern unsigned long (*kallsyms_search) (const char *name); - extern struct kprobe *kprobe_running (void); extern struct kprobe_ctlblk *get_kprobe_ctlblk (void); extern void reset_current_kprobe (void); diff --git a/kprobe/arch/dbi_kprobes.c b/kprobe/arch/dbi_kprobes.c index 7bcdca8..8c3ec7f 100644 --- a/kprobe/arch/dbi_kprobes.c +++ b/kprobe/arch/dbi_kprobes.c @@ -56,10 +56,8 @@ #include "../dbi_kprobes_deps.h" #include +#include -typedef unsigned long (*fp_kallsyms_lookup_name_t) (const char *name); -//export by swap_kprobes.ko -extern fp_kallsyms_lookup_name_t lookup_name; extern unsigned long sched_addr; extern unsigned long fork_addr; @@ -68,15 +66,6 @@ extern struct hlist_head kprobe_insn_pages; extern struct hlist_head uprobe_insn_pages; -static int ksyms = INVALID_VALUE; -module_param(ksyms, uint, 0); -MODULE_PARM_DESC(ksyms, "kallsyms_lookup_name address"); - -fp_kallsyms_lookup_name_t lookup_name; -EXPORT_SYMBOL_GPL(lookup_name); - -extern unsigned long (*kallsyms_search) (const char *name); - void arch_remove_kprobe (struct kprobe *p, struct task_struct *task) { // TODO: check boostable for x86 and MIPS @@ -118,12 +107,8 @@ void arch_disarm_uretprobe (struct kretprobe *p, struct task_struct *tsk) int arch_init_module_dependencies() { - lookup_name = (void *) ksyms; - kallsyms_search = lookup_name;//(void *) ksyms; - DBPRINTF ("kallsyms=0x%08x\n", kallsyms_search); - - sched_addr = kallsyms_search("__switch_to");//"schedule"); - fork_addr = kallsyms_search("do_fork"); + sched_addr = swap_ksyms("__switch_to"); + fork_addr = swap_ksyms("do_fork"); init_module_dependencies(); diff --git a/kprobe/dbi_kprobes.c b/kprobe/dbi_kprobes.c index cba8fd1..995ca6d 100644 --- a/kprobe/dbi_kprobes.c +++ b/kprobe/dbi_kprobes.c @@ -56,7 +56,7 @@ #include "dbi_kprobes_deps.h" #include "dbi_insn_slots.h" #include "dbi_uprobes.h" - +#include #include #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) @@ -74,8 +74,6 @@ extern unsigned long sched_addr; extern unsigned long fork_addr; extern struct hlist_head kprobe_insn_pages; -extern unsigned long (*kallsyms_search) (const char *name); - DEFINE_PER_CPU (struct kprobe *, current_kprobe) = NULL; DEFINE_PER_CPU (struct kprobe_ctlblk, kprobe_ctlblk); @@ -468,7 +466,7 @@ int dbi_register_kprobe (struct kprobe *p) { if (p->addr) return -EINVAL; - p->addr = (kprobe_opcode_t *)kallsyms_search (p->symbol_name); + p->addr = (kprobe_opcode_t *)swap_ksyms(p->symbol_name); } if (!p->addr) diff --git a/kprobe/dbi_kprobes_deps.c b/kprobe/dbi_kprobes_deps.c index 53af180..f656f97 100644 --- a/kprobe/dbi_kprobes_deps.c +++ b/kprobe/dbi_kprobes_deps.c @@ -59,7 +59,6 @@ IMP_MOD_DEP_WRAPPER(copy_to_user_page, vma, page, uaddr, dst, src, len) #endif /* copy_to_user_page */ -DECLARE_MOD_CB_DEP(kallsyms_search, unsigned long, const char *name); DECLARE_MOD_FUNC_DEP(access_process_vm, int, struct task_struct * tsk, unsigned long addr, void *buf, int len, int write); DECLARE_MOD_FUNC_DEP(find_extend_vma, struct vm_area_struct *, struct mm_struct * mm, unsigned long addr); @@ -107,10 +106,6 @@ DECLARE_MOD_FUNC_DEP(vm_normal_page, \ struct page *, struct vm_area_struct *vma, \ unsigned long addr, pte_t pte); -DECLARE_MOD_FUNC_DEP(flush_ptrace_access, \ - void, struct vm_area_struct *vma, struct page *page, \ - unsigned long uaddr, void *kaddr, unsigned long len, int write); - #if (LINUX_VERSION_CODE != KERNEL_VERSION(2, 6, 16)) DECLARE_MOD_FUNC_DEP(put_task_struct, \ @@ -202,17 +197,12 @@ IMP_MOD_DEP_WRAPPER (__flush_anon_page, vma, page, vmaddr) unsigned long addr, pte_t pte) IMP_MOD_DEP_WRAPPER (vm_normal_page, vma, addr, pte) - DECLARE_MOD_DEP_WRAPPER (flush_ptrace_access, \ - void, struct vm_area_struct *vma, struct page *page, \ - unsigned long uaddr, void *kaddr, unsigned long len, int write) -IMP_MOD_DEP_WRAPPER (flush_ptrace_access, vma, page, uaddr, kaddr, len, write) - int init_module_dependencies() { #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 29) - init_mm_ptr = (struct mm_struct*) kallsyms_search ("init_mm"); + init_mm_ptr = (struct mm_struct*)swap_ksyms("init_mm"); memcmp(init_mm_ptr, &init_mm, sizeof(struct mm_struct)); #endif @@ -224,7 +214,6 @@ int init_module_dependencies() INIT_MOD_DEP_VAR(copy_to_user_page, copy_to_user_page); #endif /* copy_to_user_page */ - 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); diff --git a/kprobe/dbi_kprobes_deps.h b/kprobe/dbi_kprobes_deps.h index 57b9f64..c8c05b5 100644 --- a/kprobe/dbi_kprobes_deps.h +++ b/kprobe/dbi_kprobes_deps.h @@ -23,9 +23,8 @@ * * 2008-2009 Alexey Gerenkov User-Space * Probes initial implementation; Support x86/ARM/MIPS for both user and kernel spaces. - * 2010 Ekaterina Gorelkina : redesign module for separating core and arch parts + * 2010 Ekaterina Gorelkina : redesign module for separating core and arch parts * - */ #include // LINUX_VERSION_CODE, KERNEL_VERSION() @@ -33,6 +32,7 @@ #include #include #include +#include #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 12)) @@ -58,7 +58,7 @@ #define INIT_MOD_DEP_VAR(dep, name) \ { \ - __ref_##dep = (void *) kallsyms_search (#name); \ + __ref_##dep = (void *) swap_ksyms (#name); \ if (!__ref_##dep) \ { \ DBPRINTF (#name " is not found! Oops. Where is it?"); \ @@ -68,7 +68,7 @@ #define INIT_MOD_DEP_CB(dep, name) \ { \ - dep = (void *) kallsyms_search (#name); \ + dep = (void *) swap_ksyms (#name); \ if (!dep) \ { \ DBPRINTF (#name " is not found! Oops. Where is it?"); \ diff --git a/kprobe/swap_kprobe.sh b/kprobe/swap_kprobe.sh index 66d6686..dcebf69 100755 --- a/kprobe/swap_kprobe.sh +++ b/kprobe/swap_kprobe.sh @@ -1,27 +1,12 @@ #!/bin/sh SWAP_KPROBE=swap_kprobe -KSYMS=kallsyms_lookup_name - -# ADDRESS for "kallsyms_lookup_name" function taken from /proc/kallsyms -ADDRESS=0x`sed "/ kallsyms_lookup_name/ ! d" /proc/kallsyms | sed "s/ T kallsyms_lookup_name//"` - -if [ "${ADDRESS}" = "0x" ]; then - if [ "$1" = "" ]; then - echo "Enter kallsyms_lookup_name as parameter:" - echo "swap_kprobe.sh " - exit 1 - else - ADDRESS=$1 - echo "kallsyms_lookup_name address is ${ADDRESS}" - fi -fi # Check for running module in /proc/modules RUNNING=`sed "/${SWAP_KPROBE}/ ! d" /proc/modules` if [ "${RUNNING}" = "" ]; then - ./bin/insmod.sh ${SWAP_KPROBE}.ko ksyms=${ADDRESS} + ./bin/insmod.sh ${SWAP_KPROBE}.ko if [ $? -ne 0 ]; then echo "Error: unable to load SWAP KProbe!" exit 1 diff --git a/ksyms/Kbuild b/ksyms/Kbuild new file mode 100644 index 0000000..317f398 --- /dev/null +++ b/ksyms/Kbuild @@ -0,0 +1,4 @@ +ifneq ($(CONFIG_KALLSYMS),y) + obj-m := swap_ksyms.o + swap_ksyms-y := ksyms.o +endif \ No newline at end of file diff --git a/ksyms/Makefile.am b/ksyms/Makefile.am new file mode 100644 index 0000000..41498ce --- /dev/null +++ b/ksyms/Makefile.am @@ -0,0 +1,26 @@ +target_kernel_src = @KERNEL@ +target_arch = @ARCH@ +module_dir = $(realpath $(top_srcdir)/src/modules/ksyms) +module_name = swap_ksyms +cross_compiler = $(subst gcc,,$(CC)) +module_path = $(module_dir)/$(module_name).ko + + +all-local: + $(MAKE) CROSS_COMPILE=$(cross_compiler) ARCH=$(target_arch) $(AM_MAKEFLAGS) -C $(target_kernel_src) M=$(module_dir) modules + + if [ -e $(module_path) ] ; then \ + echo "generate data for version patching <$(OBJDUMP)><$(READELF)>" ; \ + PATH=$(PATH) $(top_srcdir)/src/modules/driver/patchko.sh -g $(module_dir)/$(module_name).ko $(OBJDUMP) $(READELF) ; \ + fi + +clean-local: + $(MAKE) CROSS_COMPILE=$(cross_compiler) ARCH=$(target_arch) $(AM_MAKEFLAGS) -C $(target_kernel_src) M=$(module_dir) clean + +install-exec-local: + if [ -e $(module_path) ] ; then \ + install -m 644 $(module_path) $(prefix) ; \ + install -m 644 $(module_path).addr $(prefix) ; \ + \ + if [ "$(android)" != "yes" ] ; then install -m 755 $(module_dir)/$(module_name).sh $(prefix) ; fi ; \ + fi diff --git a/ksyms/ksyms.c b/ksyms/ksyms.c new file mode 100644 index 0000000..6cf9ada --- /dev/null +++ b/ksyms/ksyms.c @@ -0,0 +1,348 @@ +/* + * Dynamic Binary Instrumentation Module based on KProbes + * modules/ksyms/ksyms.c + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (C) Samsung Electronics, 2013 + * + * 2013 Vyacheslav Cherkashin + * + */ + +#include "ksyms.h" +#include +#include +#include +#include +#include +#include +#include + + +#ifndef CONFIG_KALLSYMS + +#define KSYMS_ERR(format, args...) \ + do { \ + char *f = __FILE__; \ + char *n = strrchr(f, '/'); \ + printk("%s:%u \'%s\' ERROR: " format "\n" , (n) ? n+1 : f, __LINE__, __FUNCTION__, ##args); \ + } while(0) + + +struct sys_map_item { + struct list_head list; + + unsigned long addr; + char *name; +}; + +static char* sm_path = NULL; +module_param(sm_path, charp, 0); + +LIST_HEAD(smi_list); +static struct file *file = NULL; + +static int cnt_init_sm = 0; +DEFINE_SEMAPHORE(cnt_init_sm_lock); + +static int file_open(void) +{ + struct file *f = filp_open(sm_path, O_RDONLY, 0); + + if (IS_ERR(f)) { + KSYMS_ERR("cannot open file \'%s\'", sm_path); + return PTR_ERR(f); + } + + file = f; + + return 0; +} + +static void file_close(void) +{ + if (file) { + int ret = filp_close(file, NULL); + file = NULL; + + if (ret) { + KSYMS_ERR("while closing file \'%s\' err=%d", sm_path, ret); + } + } +} + +static int file_check(void) +{ + int ret = file_open(); + if (ret == 0) { + file_close(); + } + + return ret; +} + +static long file_size(struct file *file) +{ + struct kstat st; + if (vfs_getattr(file->f_path.mnt, file->f_path.dentry, &st)) { + return -1; + } + + if (!S_ISREG(st.mode)) { + return -1; + } + + if (st.size != (long)st.size) { + return -1; + } + + return st.size; +} + +static struct sys_map_item *create_smi(unsigned long addr, const char *name) +{ + struct sys_map_item *smi = kmalloc(sizeof(*smi), GFP_KERNEL); + + if (smi == NULL) { + KSYMS_ERR("not enough memory"); + return NULL; + } + + smi->name = kmalloc(strlen(name) + 1, GFP_KERNEL); + if (smi->name == NULL) { + kfree(smi); + KSYMS_ERR("not enough memory"); + return NULL; + } + + INIT_LIST_HEAD(&smi->list); + smi->addr = addr; + strcpy(smi->name, name); + + return smi; +} + +static void free_smi(struct sys_map_item *smi) +{ + kfree(smi->name); + kfree(smi); +} + +static void add_smi(const struct sys_map_item *smi) +{ + list_add_tail(&smi->list, &smi_list); +} + +static int is_endline(char c) +{ + return c == '\n' || c == '\r' || c == '\0'; +} + +static int is_symbol_attr(char c) +{ + return c == 't' || c == 'T'; +} + +static struct sys_map_item *get_sys_map_item(char *begin, char *end) +{ + struct sys_map_item *smi = NULL; + int n, len = end - begin; + unsigned long addr; + char attr, name[128], *line; + + line = kmalloc(len + 1, GFP_KERNEL); + memcpy(line, begin, len); + line[len] = '\0'; + + n = sscanf(line, "%x %c %127s", &addr, &attr, &name); + name[127] = '\0'; + + if (n != 3) { + KSYMS_ERR("parsing line: \"%s\"", line); + attr = '\0'; + } + + kfree(line); + + if (is_symbol_attr(attr)) { + smi = create_smi(addr, name); + } + + return smi; +} + + +static void parsing(char *buf, int size) +{ + struct sys_map_item *smi; + char *start, *end, *c; + + start = buf; + end = buf + size; + + for (c = start; c < end; ++c) { + if (is_endline(*c)) { + smi = get_sys_map_item(start, c); + if (smi) { + add_smi(smi); + } + + for (start = c; c < end; ++c) { + if (!is_endline(*c)) { + start = c; + break; + } + } + } + } +} + +static int create_sys_map(void) +{ + char *data; + long size; + int ret = file_open(); + + if (ret) { + return ret; + } + + size = file_size(file); + if (size < 0) { + KSYMS_ERR("cannot get file size"); + ret = size; + goto close; + } + + data = vmalloc(size); + if (data == NULL) { + KSYMS_ERR("not enough memory"); + ret = -1; + goto close; + } + + if (kernel_read(file, 0, data, size) != size) { + KSYMS_ERR("reading file %s", sm_path); + ret = -1; + goto free; + } + + parsing(data, size); + +free: + vfree(data); + +close: + file_close(); + + return 0; +} + +static void free_sys_map(void) +{ + struct sys_map_item *smi, *n; + list_for_each_entry_safe(smi, n, &smi_list, list) { + list_del(&smi->list); + free_smi(smi); + } +} + +int swap_get_ksyms(void) +{ + int ret = 0; + + down(&cnt_init_sm_lock); + if (cnt_init_sm == 0) { + ret = create_sys_map(); + } + + ++cnt_init_sm; + up(&cnt_init_sm_lock); + + return ret; +} +EXPORT_SYMBOL_GPL(swap_get_ksyms); + +void swap_put_ksyms(void) +{ + down(&cnt_init_sm_lock); + --cnt_init_sm; + if (cnt_init_sm == 0) { + free_sys_map(); + } + + if (cnt_init_sm < 0) { + KSYMS_ERR("cnt_init_sm=%d", cnt_init_sm); + cnt_init_sm = 0; + } + + up(&cnt_init_sm_lock); +} +EXPORT_SYMBOL_GPL(swap_put_ksyms); + +unsigned long swap_ksyms(const char *name) +{ + struct sys_map_item *smi; + + list_for_each_entry(smi, &smi_list, list) { + if (strcmp(name, smi->name) == 0) { + return smi->addr; + } + } + + return 0; +} +EXPORT_SYMBOL_GPL(swap_ksyms); + +int __init swap_ksyms_init(void) +{ + int ret = 0; + + if (sm_path == NULL) { + KSYMS_ERR("sm_path=NULL"); + return -EINVAL; + } + + ret = file_check(); + if (ret) { + return -EINVAL; + } + + // TODO: calling func 'swap_get_ksyms' in module used func 'swap_ksyms' + swap_get_ksyms(); + + return 0; +} + +void __exit swap_ksyms_exit(void) +{ + down(&cnt_init_sm_lock); + + if (cnt_init_sm > 0) { + free_sys_map(); + } + + up(&cnt_init_sm_lock); +} + +module_init(swap_ksyms_init); +module_exit(swap_ksyms_exit); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("SWAP ksyms module"); +MODULE_AUTHOR("Vyacheslav Cherkashin "); + +#endif /*CONFIG_KALLSYMS*/ diff --git a/ksyms/ksyms.h b/ksyms/ksyms.h new file mode 100644 index 0000000..6e50d6d --- /dev/null +++ b/ksyms/ksyms.h @@ -0,0 +1,61 @@ +#ifndef __KSYMS_H__ +#define __KSYMS_H__ + +/* + * Dynamic Binary Instrumentation Module based on KProbes + * modules/ksyms/ksyms.h + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (C) Samsung Electronics, 2013 + * + * 2013 Vyacheslav Cherkashin + * + */ + +#include +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33) +#include +#else +#include +#endif + +#include + +#ifdef CONFIG_KALLSYMS + +static int swap_get_ksyms(void) +{ + return 0; +} + +static void swap_put_ksyms(void) +{ +} + +static unsigned long swap_ksyms(const char *name) +{ + return kallsyms_lookup_name(name); +} + +#else /* !CONFIG_KALLSYMS */ + +int swap_get_ksyms(void); +void swap_put_ksyms(void); +unsigned long swap_ksyms(const char *name); + +#endif /*CONFIG_KALLSYMS*/ + +#endif /*__KSYMS_H__*/ diff --git a/ksyms/swap_ksyms.sh b/ksyms/swap_ksyms.sh new file mode 100755 index 0000000..21e85e3 --- /dev/null +++ b/ksyms/swap_ksyms.sh @@ -0,0 +1,18 @@ +#!/bin/sh + +MODULE_NAME=swap_ksyms +SYS_MAP_PACH=/mnt/nfs/System.map + +# Check for running module in /proc/modules +RUNNING=`sed "/${MODULE_NAME}/ ! d" /proc/modules` + +if [ "${RUNNING}" = "" ]; then + ./bin/insmod.sh ${MODULE_NAME}.ko sm_path=${SYS_MAP_PACH} + if [ $? -ne 0 ]; then + echo "Error: unable to load ${MODULE_NAME}!" + exit 1 + fi +else + echo "module ${MODULE_NAME} is already running!" + exit 1 +fi