From 7e96a80cb3be27d7007f5baf0fd0af36bd213ca4 Mon Sep 17 00:00:00 2001 From: Vyacheslav Cherkashin Date: Thu, 2 Jul 2015 12:30:12 +0300 Subject: [PATCH] [FIX] installation of a few pfg on one process Change-Id: I2ea723b41e97510944155257a6280f2447dcc20c Signed-off-by: Vyacheslav Cherkashin --- parser/Kbuild | 3 +- parser/swap_msg_parser.c | 5 + parser/us_inst.c | 17 +++ {us_manager => parser}/usm_msg.c | 0 {us_manager => parser}/usm_msg.h | 0 us_manager/Kbuild | 1 - us_manager/helper.c | 39 ++++++- us_manager/pf/pf_group.c | 218 ++++++++++++++++++++++----------------- us_manager/pf/pf_group.h | 13 +++ us_manager/sspt/sspt_filter.c | 16 ++- us_manager/sspt/sspt_filter.h | 8 +- us_manager/sspt/sspt_proc.c | 34 +++--- us_manager/sspt/sspt_proc.h | 12 ++- us_manager/us_manager.c | 5 +- 14 files changed, 246 insertions(+), 125 deletions(-) rename {us_manager => parser}/usm_msg.c (100%) rename {us_manager => parser}/usm_msg.h (100%) diff --git a/parser/Kbuild b/parser/Kbuild index 13a49fa..7faf7ba 100644 --- a/parser/Kbuild +++ b/parser/Kbuild @@ -13,4 +13,5 @@ swap_message_parser-y := swap_msg_parser.o \ msg_cmd.o \ features.o \ us_inst.o \ - cpu_ctrl.o + cpu_ctrl.o \ + usm_msg.o diff --git a/parser/swap_msg_parser.c b/parser/swap_msg_parser.c index 60fc0ac..bed50d0 100644 --- a/parser/swap_msg_parser.c +++ b/parser/swap_msg_parser.c @@ -38,6 +38,7 @@ #include "us_inst.h" #include "msg_buf.h" #include "msg_cmd.h" +#include "usm_msg.h" #include "cpu_ctrl.h" #include @@ -176,6 +177,10 @@ static int once(void) return ret; ret = init_cpu_deps(); + if (ret) + return ret; + + ret = usm_msg_once(); return ret; } diff --git a/parser/us_inst.c b/parser/us_inst.c index bb40481..d298ae8 100644 --- a/parser/us_inst.c +++ b/parser/us_inst.c @@ -37,6 +37,7 @@ #include "msg_parser.h" #include "us_inst.h" +#include "usm_msg.h" struct pfg_item { @@ -201,6 +202,14 @@ static int get_pfg_by_app_info(struct app_info_data *app_info, return 0; } +static struct pfg_msg_cb msg_cb = { + .msg_info = usm_msg_info, + .msg_status_info = usm_msg_status_info, + .msg_term = usm_msg_term, + .msg_map = usm_msg_map, + .msg_unmap = usm_msg_unmap +}; + static int mod_us_app_inst(struct app_inst_data *app_inst, enum MOD_TYPE mt) { int ret, i; @@ -220,6 +229,14 @@ static int mod_us_app_inst(struct app_inst_data *app_inst, enum MOD_TYPE mt) return ret; } + ret = pfg_msg_cb_set(pfg, &msg_cb); + if (ret) { + put_pf_group(pfg); + printk(KERN_INFO "Cannot set path [%s], ret=%d\n", + app_inst->app_info->exec_path, ret); + return ret; + } + for (i = 0; i < app_inst->cnt_func; ++i) { /* TODO: */ dentry = dentry_by_path(app_inst->app_info->exec_path); diff --git a/us_manager/usm_msg.c b/parser/usm_msg.c similarity index 100% rename from us_manager/usm_msg.c rename to parser/usm_msg.c diff --git a/us_manager/usm_msg.h b/parser/usm_msg.h similarity index 100% rename from us_manager/usm_msg.h rename to parser/usm_msg.h diff --git a/us_manager/Kbuild b/us_manager/Kbuild index 67707a6..64e4d35 100644 --- a/us_manager/Kbuild +++ b/us_manager/Kbuild @@ -11,5 +11,4 @@ swap_us_manager-y := us_manager.o us_slot_manager.o helper.o debugfs_us_manager. img/img_proc.o img/img_file.o img/img_ip.o \ probes/probes.o \ probes/probe_info_new.o \ - usm_msg.o \ callbacks.o diff --git a/us_manager/helper.c b/us_manager/helper.c index 05dc0dd..b3a9395 100644 --- a/us_manager/helper.c +++ b/us_manager/helper.c @@ -29,7 +29,7 @@ #include #include "us_slot_manager.h" #include "sspt/sspt.h" -#include "usm_msg.h" +#include "sspt/sspt_filter.h" #include "helper.h" struct task_struct; @@ -321,6 +321,25 @@ struct unmap_data { static atomic_t unmap_cnt = ATOMIC_INIT(0); +struct msg_unmap_data { + unsigned long start; + unsigned long end; +}; + +static void msg_unmap(struct sspt_filter *f, void *data) +{ + if (f->pfg_is_inst) { + struct pfg_msg_cb *cb = pfg_msg_cb_get(f->pfg); + + if (cb && cb->msg_unmap) { + struct msg_unmap_data *msg_data; + + msg_data = (struct msg_unmap_data *)data; + cb->msg_unmap(msg_data->start, msg_data->end); + } + } +} + static void __remove_unmap_probes(struct sspt_proc *proc, struct unmap_data *umd) { @@ -332,6 +351,10 @@ static void __remove_unmap_probes(struct sspt_proc *proc, if (sspt_proc_get_files_by_region(proc, &head, start, len)) { struct sspt_file *file, *n; unsigned long end = start + len; + struct msg_unmap_data msg_data = { + .start = start, + .end = end + }; list_for_each_entry_safe(file, n, &head, list) { if (file->vm_start >= end) @@ -344,7 +367,7 @@ static void __remove_unmap_probes(struct sspt_proc *proc, sspt_proc_insert_files(proc, &head); - usm_msg_unmap(start, end); + sspt_proc_on_each_filter(proc, msg_unmap, (void *)&msg_data); } } @@ -432,6 +455,16 @@ static void unregister_unmap(void) * do_mmap_pgoff() * ****************************************************************************** */ +static void msg_map(struct sspt_filter *f, void *data) +{ + if (f->pfg_is_inst) { + struct pfg_msg_cb *cb = pfg_msg_cb_get(f->pfg); + + if (cb && cb->msg_map) + cb->msg_map((struct vm_area_struct *)data); + } +} + static int ret_handler_mmap(struct kretprobe_instance *ri, struct pt_regs *regs) { @@ -454,7 +487,7 @@ static int ret_handler_mmap(struct kretprobe_instance *ri, vma = find_vma_intersection(task->mm, start_addr, start_addr + 1); if (vma && check_vma(vma)) - usm_msg_map(vma); + sspt_proc_on_each_filter(proc, msg_map, (void *)vma); return 0; } diff --git a/us_manager/pf/pf_group.c b/us_manager/pf/pf_group.c index e0f180c..6b2ec7b 100644 --- a/us_manager/pf/pf_group.c +++ b/us_manager/pf/pf_group.c @@ -28,8 +28,9 @@ #include #include +#include "pf_group.h" #include "proc_filters.h" -#include +#include "../sspt/sspt_filter.h" #include #include #include @@ -40,6 +41,7 @@ struct pf_group { struct list_head list; struct img_proc *i_proc; struct proc_filter filter; + struct pfg_msg_cb *msg_cb; atomic_t usage; /* TODO: proc_list*/ @@ -92,34 +94,6 @@ static struct pl_struct *find_pl_struct(struct pf_group *pfg, return NULL; } - -static struct sspt_proc *get_proc_by_pfg(struct pf_group *pfg, - struct task_struct *task) -{ - struct pl_struct *pls; - - pls = find_pl_struct(pfg, task); - if (pls) - return pls->proc; - - return NULL; -} - -static struct sspt_proc *new_proc_by_pfg(struct pf_group *pfg, - struct task_struct *task) -{ - struct pl_struct *pls; - struct sspt_proc *proc; - - proc = sspt_proc_get_by_task_or_new(task, pfg->filter.priv); - img_proc_copy_to_sspt(pfg->i_proc, proc); - sspt_proc_add_filter(proc, pfg); - - pls = create_pl_struct(proc); - add_pl_struct(pfg, pls); - - return proc; -} /* struct pl_struct */ static struct pf_group *create_pfg(void) @@ -136,6 +110,7 @@ static struct pf_group *create_pfg(void) INIT_LIST_HEAD(&pfg->list); memset(&pfg->filter, 0, sizeof(pfg->filter)); INIT_LIST_HEAD(&pfg->proc_list); + pfg->msg_cb = NULL; atomic_set(&pfg->usage, 1); return pfg; @@ -170,21 +145,33 @@ static void del_pfg_by_list(struct pf_group *pfg) list_del(&pfg->list); } -static void first_install(struct task_struct *task, struct sspt_proc *proc, - struct pf_group *pfg) + +static void msg_info(struct sspt_filter *f, void *data) { - struct dentry *dentry; + if (f->pfg_is_inst == false) { + struct pfg_msg_cb *cb; + + f->pfg_is_inst = true; + + cb = pfg_msg_cb_get(f->pfg); + if (cb) { + struct dentry *dentry; + + dentry = (struct dentry *)f->pfg->filter.priv; - dentry = (struct dentry *)get_pf_priv(&pfg->filter); - if (dentry == NULL) { - dentry = task->mm->exe_file ? - task->mm->exe_file->f_dentry : - NULL; + if (cb->msg_info) + cb->msg_info(f->proc->task, dentry); + + if (cb->msg_status_info) + cb->msg_status_info(f->proc->task); + } } +} +static void first_install(struct task_struct *task, struct sspt_proc *proc) +{ down_write(&task->mm->mmap_sem); - usm_msg_info(task, dentry); - usm_msg_status_info(task); + sspt_proc_on_each_filter(proc, msg_info, NULL); sspt_proc_install(proc); up_write(&task->mm->mmap_sem); } @@ -231,6 +218,23 @@ struct dentry *dentry_by_path(const char *path) } EXPORT_SYMBOL_GPL(dentry_by_path); + +int pfg_msg_cb_set(struct pf_group *pfg, struct pfg_msg_cb *msg_cb) +{ + if (pfg->msg_cb) + return -EBUSY; + + pfg->msg_cb = msg_cb; + + return 0; +} +EXPORT_SYMBOL_GPL(pfg_msg_cb_set); + +struct pfg_msg_cb *pfg_msg_cb_get(struct pf_group *pfg) +{ + return pfg->msg_cb; +} + /** * @brief Get pf_group struct by dentry * @@ -440,92 +444,118 @@ int check_task_on_filters(struct task_struct *task) unlock: read_unlock(&pfg_list_lock); + return ret; +} + +static int pfg_add_proc(struct pf_group *pfg, struct sspt_proc *proc) +{ + struct pl_struct *pls; + + pls = create_pl_struct(proc); + if (pls == NULL) + return -ENOMEM; + + add_pl_struct(pfg, pls); + return 0; } -/** - * @brief Check task and install probes on demand - * - * @prarm task Pointer on the task_struct struct - * @return Void - */ -void check_task_and_install(struct task_struct *task) +enum pf_inst_flag { + PIF_NONE, + PIF_FIRST, + PIF_SECOND, + PIF_ADD_PFG +}; + +static enum pf_inst_flag pfg_check_task(struct task_struct *task) { struct pf_group *pfg; struct sspt_proc *proc = NULL; + enum pf_inst_flag flag = PIF_NONE; read_lock(&pfg_list_lock); list_for_each_entry(pfg, &pfg_list, list) { if (check_task_f(&pfg->filter, task) == NULL) continue; - proc = get_proc_by_pfg(pfg, task); + if (proc == NULL) + proc = sspt_proc_get_by_task(task); + if (proc) { - if (sspt_proc_is_filter_new(proc, pfg)) { - img_proc_copy_to_sspt(pfg->i_proc, proc); - sspt_proc_add_filter(proc, pfg); - } else { - printk(KERN_ERR "SWAP US_MANAGER: Error! Trying" - " to first install filter that " - "already exists in proc!\n"); - proc = NULL; - goto unlock; + flag = flag == PIF_NONE ? PIF_SECOND : flag; + } else if (task->tgid == task->pid) { + proc = sspt_proc_get_by_task_or_new(task); + if (proc == NULL) { + printk(KERN_ERR "cannot create sspt_proc\n"); + break; } - break; + flag = PIF_FIRST; } - if (task->tgid == task->pid) { - proc = new_proc_by_pfg(pfg, task); - break; + if (proc && sspt_proc_is_filter_new(proc, pfg)) { + img_proc_copy_to_sspt(pfg->i_proc, proc); + sspt_proc_add_filter(proc, pfg); + pfg_add_proc(pfg, proc); + flag = flag == PIF_FIRST ? flag : PIF_ADD_PFG; } } - -unlock: read_unlock(&pfg_list_lock); - if (proc) - first_install(task, proc, pfg); + return flag; } /** * @brief Check task and install probes on demand * * @prarm task Pointer on the task_struct struct - * @param page_addr Page fault address * @return Void */ -void call_page_fault(struct task_struct *task, unsigned long page_addr) +void check_task_and_install(struct task_struct *task) { - struct pf_group *pfg, *pfg_first = NULL; - struct sspt_proc *proc = NULL; - - read_lock(&pfg_list_lock); - list_for_each_entry(pfg, &pfg_list, list) { - if ((check_task_f(&pfg->filter, task) == NULL)) - continue; - - proc = get_proc_by_pfg(pfg, task); - if (proc) { - if (sspt_proc_is_filter_new(proc, pfg)) { - img_proc_copy_to_sspt(pfg->i_proc, proc); - sspt_proc_add_filter(proc, pfg); - } - break; - } - - if (task->tgid == task->pid) { - proc = new_proc_by_pfg(pfg, task); - pfg_first = pfg; - break; - } + struct sspt_proc *proc; + enum pf_inst_flag flag; + + flag = pfg_check_task(task); + switch (flag) { + case PIF_FIRST: + case PIF_ADD_PFG: + proc = sspt_proc_get_by_task(task); + first_install(task, proc); + break; + + case PIF_NONE: + case PIF_SECOND: + break; } - read_unlock(&pfg_list_lock); +} - if (proc) { - if (pfg_first) - first_install(task, proc, pfg_first); - else - subsequent_install(task, proc, page_addr); +/** + * @brief Check task and install probes on demand + * + * @prarm task Pointer on the task_struct struct + * @param page_addr Page fault address + * @return Void + */ +void call_page_fault(struct task_struct *task, unsigned long page_addr) +{ + struct sspt_proc *proc; + enum pf_inst_flag flag; + + flag = pfg_check_task(task); + switch (flag) { + case PIF_FIRST: + case PIF_ADD_PFG: + proc = sspt_proc_get_by_task(task); + first_install(task, proc); + break; + + case PIF_SECOND: + proc = sspt_proc_get_by_task(task); + subsequent_install(task, proc, page_addr); + break; + + case PIF_NONE: + break; } } diff --git a/us_manager/pf/pf_group.h b/us_manager/pf/pf_group.h index 9a053d1..908891b 100644 --- a/us_manager/pf/pf_group.h +++ b/us_manager/pf/pf_group.h @@ -32,6 +32,16 @@ struct pf_group; struct sspt_proc; struct probe_info; + +struct pfg_msg_cb { + void (*msg_info)(struct task_struct *task, struct dentry *dentry); + void (*msg_status_info)(struct task_struct *task); + void (*msg_term)(struct task_struct *task); + void (*msg_map)(struct vm_area_struct *vma); + void (*msg_unmap)(unsigned long start, unsigned long end); +}; + + /* FIXME: create and use get_dentry() and put_dentry() */ struct dentry *dentry_by_path(const char *path); @@ -41,6 +51,9 @@ struct pf_group *get_pf_group_by_comm(char *comm, void *priv); struct pf_group *get_pf_group_dumb(void *priv); void put_pf_group(struct pf_group *pfg); +int pfg_msg_cb_set(struct pf_group *pfg, struct pfg_msg_cb *msg_cb); +struct pfg_msg_cb *pfg_msg_cb_get(struct pf_group *pfg); + int pf_register_probe(struct pf_group *pfg, struct dentry *dentry, unsigned long offset, struct probe_info *probe_i); int pf_unregister_probe(struct pf_group *pfg, struct dentry *dentry, diff --git a/us_manager/sspt/sspt_filter.c b/us_manager/sspt/sspt_filter.c index 1478cd8..0d02e73 100644 --- a/us_manager/sspt/sspt_filter.c +++ b/us_manager/sspt/sspt_filter.c @@ -2,8 +2,11 @@ #include #include "sspt_filter.h" #include "sspt_proc.h" +#include "../pf/pf_group.h" -struct sspt_filter *sspt_filter_create(struct pf_group *pfg) + +struct sspt_filter *sspt_filter_create(struct sspt_proc *proc, + struct pf_group *pfg) { struct sspt_filter *fl; @@ -12,12 +15,23 @@ struct sspt_filter *sspt_filter_create(struct pf_group *pfg) return NULL; INIT_LIST_HEAD(&fl->list); + list_add(&fl->list, &proc->filter_list); + + fl->proc = proc; fl->pfg = pfg; + fl->pfg_is_inst = false; return fl; } void sspt_filter_free(struct sspt_filter *fl) { + if (fl->pfg_is_inst) { + struct pfg_msg_cb *cb = pfg_msg_cb_get(fl->pfg); + + if (cb && cb->msg_term) + cb->msg_term(fl->proc->task); + } + kfree(fl); } diff --git a/us_manager/sspt/sspt_filter.h b/us_manager/sspt/sspt_filter.h index 757cd78..faeac80 100644 --- a/us_manager/sspt/sspt_filter.h +++ b/us_manager/sspt/sspt_filter.h @@ -1,14 +1,20 @@ #ifndef __SSPT_FILTER_H__ #define __SSPT_FILTER_H__ +#include + struct pf_group; +struct sspt_proc; struct sspt_filter { struct list_head list; + struct sspt_proc *proc; struct pf_group *pfg; + bool pfg_is_inst; }; -struct sspt_filter *sspt_filter_create(struct pf_group *pfg); +struct sspt_filter *sspt_filter_create(struct sspt_proc *proc, + struct pf_group *pfg); void sspt_filter_free(struct sspt_filter *fl); #endif /* __SSPT_FILTER_H__ */ diff --git a/us_manager/sspt/sspt_proc.c b/us_manager/sspt/sspt_proc.c index 5152925..c4e7255 100644 --- a/us_manager/sspt/sspt_proc.c +++ b/us_manager/sspt/sspt_proc.c @@ -27,10 +27,10 @@ #include "sspt_page.h" #include "sspt_feature.h" #include "sspt_filter.h" +#include "../pf/proc_filters.h" #include #include #include -#include #include @@ -86,7 +86,7 @@ void sspt_proc_write_unlock(void) * @param priv Private data * @return Pointer to the created sspt_proc struct */ -struct sspt_proc *sspt_proc_create(struct task_struct *task, void *priv) +struct sspt_proc *sspt_proc_create(struct task_struct *task) { struct sspt_proc *proc = kmalloc(sizeof(*proc), GFP_ATOMIC); @@ -135,7 +135,6 @@ void sspt_proc_free(struct sspt_proc *proc) sspt_destroy_feature(proc->feature); - usm_msg_term(proc->task); free_sm_us(proc->sm); kfree(proc); } @@ -197,12 +196,11 @@ EXPORT_SYMBOL_GPL(on_each_proc); * @param priv Private data * @return Pointer on the sspt_proc struct */ -struct sspt_proc *sspt_proc_get_by_task_or_new(struct task_struct *task, - void *priv) +struct sspt_proc *sspt_proc_get_by_task_or_new(struct task_struct *task) { struct sspt_proc *proc = sspt_proc_get_by_task(task); if (proc == NULL) - proc = sspt_proc_create(task, priv); + proc = sspt_proc_create(task); return proc; } @@ -434,13 +432,7 @@ void sspt_proc_insert_files(struct sspt_proc *proc, struct list_head *head) */ void sspt_proc_add_filter(struct sspt_proc *proc, struct pf_group *pfg) { - struct sspt_filter *fl; - - fl = sspt_filter_create(pfg); - if (fl == NULL) - return; - - list_add(&fl->list, &proc->filter_list); + sspt_filter_create(proc, pfg); } /** @@ -485,13 +477,23 @@ void sspt_proc_del_all_filters(struct sspt_proc *proc) * @param pfg Pointer to pf_group struct * @return Boolean */ -int sspt_proc_is_filter_new(struct sspt_proc *proc, struct pf_group *pfg) +bool sspt_proc_is_filter_new(struct sspt_proc *proc, struct pf_group *pfg) { struct sspt_filter *fl; list_for_each_entry(fl, &proc->filter_list, list) if (fl->pfg == pfg) - return 0; + return false; + + return true; +} - return 1; +void sspt_proc_on_each_filter(struct sspt_proc *proc, + void (*func)(struct sspt_filter *, void *), + void *data) +{ + struct sspt_filter *fl; + + list_for_each_entry(fl, &proc->filter_list, list) + func(fl, data); } diff --git a/us_manager/sspt/sspt_proc.h b/us_manager/sspt/sspt_proc.h index 9fcee58..22fe786 100644 --- a/us_manager/sspt/sspt_proc.h +++ b/us_manager/sspt/sspt_proc.h @@ -30,6 +30,7 @@ struct slot_manager; struct task_struct; struct pf_group; +struct sspt_filter; /** Flags for sspt_*_uninstall() */ enum US_FLAGS { @@ -55,7 +56,7 @@ struct sspt_proc { }; -struct sspt_proc *sspt_proc_create(struct task_struct *task, void *priv); +struct sspt_proc *sspt_proc_create(struct task_struct *task); void sspt_proc_free(struct sspt_proc *proc); void on_each_proc_no_lock(void (*func)(struct sspt_proc *, void *), @@ -63,8 +64,7 @@ void on_each_proc_no_lock(void (*func)(struct sspt_proc *, void *), void on_each_proc(void (*func)(struct sspt_proc *, void *), void *data); struct sspt_proc *sspt_proc_get_by_task(struct task_struct *task); -struct sspt_proc *sspt_proc_get_by_task_or_new(struct task_struct *task, - void *priv); +struct sspt_proc *sspt_proc_get_by_task_or_new(struct task_struct *task); void sspt_proc_free_all(void); struct sspt_file *sspt_proc_find_file(struct sspt_proc *proc, @@ -93,6 +93,10 @@ void sspt_proc_write_unlock(void); void sspt_proc_add_filter(struct sspt_proc *proc, struct pf_group *pfg); void sspt_proc_del_filter(struct sspt_proc *proc, struct pf_group *pfg); void sspt_proc_del_all_filters(struct sspt_proc *proc); -int sspt_proc_is_filter_new(struct sspt_proc *proc, struct pf_group *pfg); +bool sspt_proc_is_filter_new(struct sspt_proc *proc, struct pf_group *pfg); + +void sspt_proc_on_each_filter(struct sspt_proc *proc, + void (*func)(struct sspt_filter *, void *), + void *data); #endif /* __SSPT_PROC__ */ diff --git a/us_manager/us_manager.c b/us_manager/us_manager.c index 56efc67..aa5f3c7 100644 --- a/us_manager/us_manager.c +++ b/us_manager/us_manager.c @@ -29,7 +29,6 @@ #include "probes/probe_info_new.h" #include "helper.h" #include "us_manager.h" -#include "usm_msg.h" #include "debugfs_us_manager.h" #include "callbacks.h" #include @@ -217,10 +216,8 @@ static int usm_once(void) int ret; ret = once_helper(); - if (ret) - return ret; - return usm_msg_once(); + return ret; } static int init_us_manager(void) -- 2.7.4