From 750cecb351642b0c218121edb3f3623e76cd59bc Mon Sep 17 00:00:00 2001 From: Vyacheslav Cherkashin Date: Fri, 14 Nov 2014 18:34:16 +0400 Subject: [PATCH] [IMPROVE] new interface for probe_info struct Change-Id: I71bb2f0afee8662411bdc6b758954b30561469c9 Signed-off-by: Vyacheslav Cherkashin --- fbiprobe/fbiprobe.c | 6 +++--- preload/preload_control.c | 2 +- preload/preload_module.c | 6 +++--- preload/preload_probe.c | 6 +++--- retprobe/retprobe.c | 6 +++--- us_manager/img/img_ip.c | 26 +++++++++++++++++++------- us_manager/img/img_ip.h | 4 ++-- us_manager/pf/pf_group.c | 2 +- us_manager/probes/probes.c | 36 ++++++++++++++++++++++++++++++++++++ us_manager/probes/probes.h | 15 +++++++++++++++ us_manager/sspt/ip.c | 23 ++++++++++++++++------- us_manager/sspt/ip.h | 4 ++-- us_manager/sspt/sspt.h | 10 +++++----- us_manager/sspt/sspt_debug.h | 2 +- us_manager/sspt/sspt_file.c | 2 +- us_manager/sspt/sspt_page.c | 2 +- webprobe/webprobe.c | 2 +- 17 files changed, 113 insertions(+), 41 deletions(-) diff --git a/fbiprobe/fbiprobe.c b/fbiprobe/fbiprobe.c index bd095a6..d507502 100644 --- a/fbiprobe/fbiprobe.c +++ b/fbiprobe/fbiprobe.c @@ -259,11 +259,11 @@ static int fbi_probe_handler(struct kprobe *p, struct pt_regs *regs) { struct uprobe *up = container_of(p, struct uprobe, kp); struct us_ip *ip = container_of(up, struct us_ip, uprobe); - struct fbi_info *fbi_i = &ip->probe_i.fbi_i; + struct fbi_info *fbi_i = &ip->info->fbi_i; struct fbi_var_data *fbi_d = NULL; uint8_t i; - if (ip->probe_i.probe_type != SWAP_FBIPROBE) { + if (ip->info->probe_type != SWAP_FBIPROBE) { /* How this can occure? Doesn't matter, just print and go */ print_err("Not FBI probe in FBI handler!\n"); return 0; @@ -314,7 +314,7 @@ void fbi_probe_init(struct us_ip *ip) void fbi_probe_uninit(struct us_ip *ip) { if (ip != NULL) - fbi_probe_cleanup(&ip->probe_i); + fbi_probe_cleanup(ip->info); } static int fbi_probe_register_probe(struct us_ip *ip) diff --git a/preload/preload_control.c b/preload/preload_control.c index 61ede6f..cf29979 100644 --- a/preload/preload_control.c +++ b/preload/preload_control.c @@ -216,7 +216,7 @@ enum preload_call_type preload_control_call_type(struct us_ip *ip, void *caller) if (__is_instrumented(caller)) return INTERNAL_CALL; - if (ip->probe_i.pl_i.type & SWAP_PRELOAD_ALWAYS) + if (ip->info->pl_i.type & SWAP_PRELOAD_ALWAYS) return EXTERNAL_CALL; return NOT_INSTRUMENTED; diff --git a/preload/preload_module.c b/preload/preload_module.c index f1960b6..ba73bd4 100644 --- a/preload/preload_module.c +++ b/preload/preload_module.c @@ -284,7 +284,7 @@ static inline struct vm_area_struct *__get_vma_by_addr(struct task_struct *task, static inline bool __is_probe_non_block(struct us_ip *ip) { - if (!(ip->probe_i.pl_i.type & (0x1 << 1))) + if (!(ip->info->pl_i.type & (0x1 << 1))) return true; return false; @@ -378,7 +378,7 @@ static int preload_us_entry(struct uretprobe_instance *ri, struct pt_regs *regs) struct us_ip *ip = container_of(ri->rp, struct us_ip, retprobe); struct us_priv *priv = (struct us_priv *)ri->data; unsigned long flags = get_preload_flags(current); - unsigned long offset = ip->probe_i.pl_i.handler; + unsigned long offset = ip->info->pl_i.handler; unsigned long vaddr = 0; char __user *path = NULL; @@ -461,7 +461,7 @@ static int preload_us_ret(struct uretprobe_instance *ri, struct pt_regs *regs) struct us_ip *ip = container_of(ri->rp, struct us_ip, retprobe); struct us_priv *priv = (struct us_priv *)ri->data; unsigned long flags = get_preload_flags(current); - unsigned long offset = ip->probe_i.pl_i.handler; + unsigned long offset = ip->info->pl_i.handler; unsigned long vaddr = 0; switch (preload_pd_get_state(pd)) { diff --git a/preload/preload_probe.c b/preload/preload_probe.c index efb0d29..400a422 100644 --- a/preload/preload_probe.c +++ b/preload/preload_probe.c @@ -127,7 +127,7 @@ static void preload_uninit(struct us_ip *ip) { preload_module_uprobe_exit(ip); - preload_info_cleanup(&ip->probe_i); + preload_info_cleanup(ip->info); } static struct probe_iface preload_iface = { @@ -176,7 +176,7 @@ static void get_caller_uninit(struct us_ip *ip) { preload_module_get_caller_exit(ip); - get_caller_info_cleanup(&ip->probe_i); + get_caller_info_cleanup(ip->info); } static struct probe_iface get_caller_iface = { @@ -198,7 +198,7 @@ static void get_call_type_uninit(struct us_ip *ip) { preload_module_get_call_type_exit(ip); - get_caller_info_cleanup(&ip->probe_i); + get_caller_info_cleanup(ip->info); } static struct probe_iface get_call_type_iface = { diff --git a/retprobe/retprobe.c b/retprobe/retprobe.c index 5a29986..8a5daa2 100644 --- a/retprobe/retprobe.c +++ b/retprobe/retprobe.c @@ -78,7 +78,7 @@ static int retprobe_entry_handler(struct uretprobe_instance *ri, struct pt_regs if (rp && get_quiet() == QT_OFF) { struct us_ip *ip = container_of(rp, struct us_ip, retprobe); - const char *fmt = ip->probe_i.rp_i.args; + const char *fmt = ip->info->rp_i.args; const unsigned long func_addr = (unsigned long)ip->orig_addr; rp_msg_entry(regs, func_addr, fmt); @@ -95,7 +95,7 @@ static int retprobe_ret_handler(struct uretprobe_instance *ri, struct pt_regs *r struct us_ip *ip = container_of(rp, struct us_ip, retprobe); const unsigned long func_addr = (unsigned long)ip->orig_addr; const unsigned long ret_addr = (unsigned long)ri->ret_addr; - const char ret_type = ip->probe_i.rp_i.ret_type; + const char ret_type = ip->info->rp_i.ret_type; rp_msg_exit(regs, func_addr, ret_type, ret_addr); } @@ -112,7 +112,7 @@ static void retprobe_init(struct us_ip *ip) static void retprobe_uninit(struct us_ip *ip) { - retprobe_cleanup(&ip->probe_i); + retprobe_cleanup(ip->info); } diff --git a/us_manager/img/img_ip.c b/us_manager/img/img_ip.c index 8b92f05..ef0d0fe 100644 --- a/us_manager/img/img_ip.c +++ b/us_manager/img/img_ip.c @@ -34,15 +34,26 @@ * @param probe_i Pointer to the probe info data. * @return Pointer to the created img_ip struct */ -struct img_ip *create_img_ip(unsigned long addr, struct probe_info *probe_i) +struct img_ip *create_img_ip(unsigned long addr, struct probe_info *info) { struct img_ip *ip; ip = kmalloc(sizeof(*ip), GFP_KERNEL); - INIT_LIST_HEAD(&ip->list); - ip->addr = addr; + if (ip) { + struct probe_info *info_new; - probe_info_copy(probe_i, &ip->probe_i); + info_new = probe_info_dup(info); + if (info_new == NULL) { + kfree(ip); + return NULL; + } + + probe_info_copy(info, info_new); + + INIT_LIST_HEAD(&ip->list); + ip->addr = addr; + ip->info = info_new; + } return ip; } @@ -55,7 +66,8 @@ struct img_ip *create_img_ip(unsigned long addr, struct probe_info *probe_i) */ void free_img_ip(struct img_ip *ip) { - probe_info_cleanup(&ip->probe_i); + probe_info_cleanup(ip->info); + probe_info_free(ip->info); kfree(ip); } @@ -69,8 +81,8 @@ void free_img_ip(struct img_ip *ip) /* debug */ void img_ip_print(struct img_ip *ip) { - if (ip->probe_i.probe_type == SWAP_RETPROBE) + if (ip->info->probe_type == SWAP_RETPROBE) printk(KERN_INFO "### addr=8%lx, args=%s\n", - ip->addr, ip->probe_i.rp_i.args); + ip->addr, ip->info->rp_i.args); } /* debug */ diff --git a/us_manager/img/img_ip.h b/us_manager/img/img_ip.h index cd14722..08a7b3b 100644 --- a/us_manager/img/img_ip.h +++ b/us_manager/img/img_ip.h @@ -36,10 +36,10 @@ struct img_ip { struct list_head list; /**< For img_file */ unsigned long addr; /**< Function address */ - struct probe_info probe_i; /**< Probe info */ + struct probe_info *info; /**< Probe info */ }; -struct img_ip *create_img_ip(unsigned long addr, struct probe_info *probe_i); +struct img_ip *create_img_ip(unsigned long addr, struct probe_info *info); void free_img_ip(struct img_ip *ip); /* debug */ diff --git a/us_manager/pf/pf_group.c b/us_manager/pf/pf_group.c index 927b82d..cc1fa79 100644 --- a/us_manager/pf/pf_group.c +++ b/us_manager/pf/pf_group.c @@ -88,7 +88,7 @@ void copy_proc_form_img_to_sspt(struct img_proc *i_proc, struct sspt_proc *proc) file = sspt_proc_find_file_or_new(proc, i_file->dentry); list_for_each_entry(i_ip, &i_file->ip_list, list) - sspt_file_add_ip(file, i_ip->addr, &i_ip->probe_i); + sspt_file_add_ip(file, i_ip->addr, i_ip->info); } } diff --git a/us_manager/probes/probes.c b/us_manager/probes/probes.c index 52b024f..e38789f 100644 --- a/us_manager/probes/probes.c +++ b/us_manager/probes/probes.c @@ -26,10 +26,46 @@ #include "register_probes.h" #include "use_probes.h" +#include #include #include #include + +struct probe_info *probe_info_malloc(size_t size, enum probe_t type) +{ + struct probe_info *info; + + info = kmalloc(sizeof(*info) + size, GFP_ATOMIC); + if (info) { + info->probe_type = type; + info->size = size; + } + + return info; +} +EXPORT_SYMBOL_GPL(probe_info_malloc); + +struct probe_info *probe_info_dup(const struct probe_info *info) +{ + struct probe_info *info_new; + size_t size = info->size; + + info_new = probe_info_malloc(size, info->probe_type); + if (info_new && size) + memcpy(info_new->data, info->data, size); + + return info_new; +} +EXPORT_SYMBOL_GPL(probe_info_dup); + +void probe_info_free(struct probe_info *info) +{ + kfree(info); +} +EXPORT_SYMBOL_GPL(probe_info_free); + + static struct probe_iface *probes_methods[SWAP_PROBE_MAX_VAL] = { NULL }; /* 1 - correct probe type diff --git a/us_manager/probes/probes.h b/us_manager/probes/probes.h index 988bfe8..dbd3392 100644 --- a/us_manager/probes/probes.h +++ b/us_manager/probes/probes.h @@ -67,6 +67,21 @@ struct probe_info { struct get_caller_info gc_i; struct get_call_type_info gct_i; }; + + char data[0]; }; + +#define probe_info_create(val_t, type) probe_info_malloc(sizeof(val_t), type) +struct probe_info *probe_info_malloc(size_t size, enum probe_t type); +struct probe_info *probe_info_dup(const struct probe_info *info); +void probe_info_free(struct probe_info *info); + + +#define probe_info_get_data(info) ((void *)(info->data)) +#define probe_info_get_ptr(info, val_t) (val_t *)probe_info_get_data(info) +#define probe_info_get_val(info, val_t) *probe_info_get_ptr(info, val_t) +#define probe_info_set_val(info, val_t, v) *probe_info_get_ptr(info, val_t) = v + + #endif /* __PROBES_H__ */ diff --git a/us_manager/sspt/ip.c b/us_manager/sspt/ip.c index c9d401d..7275353 100644 --- a/us_manager/sspt/ip.c +++ b/us_manager/sspt/ip.c @@ -38,24 +38,32 @@ * @param page Pointer to the parent sspt_page struct * @return Pointer to the created us_ip struct */ -struct us_ip *create_ip(unsigned long offset, const struct probe_info *probe_i, +struct us_ip *create_ip(unsigned long offset, const struct probe_info *info, struct sspt_page *page) { - size_t len = probe_i->size; struct us_ip *ip; + struct probe_info *info_new; - ip = kmalloc(sizeof(*ip) + len, GFP_ATOMIC); + info_new = probe_info_dup(info); + if (info_new == NULL) { + printk("Cannot probe_info_dup in %s function!\n", __func__); + return NULL; + } + + ip = kmalloc(sizeof(*ip), GFP_ATOMIC); if (ip != NULL) { - memset(ip, 0, sizeof(*ip) + len); + memset(ip, 0, sizeof(*ip)); INIT_LIST_HEAD(&ip->list); ip->offset = offset; ip->page = page; - probe_info_copy(probe_i, &ip->probe_i); - probe_info_init(&ip->probe_i, ip); + probe_info_copy(info, info_new); + probe_info_init(info_new, ip); + ip->info = info_new; } else { printk(KERN_INFO "Cannot kmalloc in create_ip function!\n"); + probe_info_free(info_new); } return ip; @@ -69,6 +77,7 @@ struct us_ip *create_ip(unsigned long offset, const struct probe_info *probe_i, */ void free_ip(struct us_ip *ip) { - probe_info_uninit(&ip->probe_i, ip); + probe_info_uninit(ip->info, ip); + probe_info_free(ip->info); kfree(ip); } diff --git a/us_manager/sspt/ip.h b/us_manager/sspt/ip.h index 7229f03..f895b20 100644 --- a/us_manager/sspt/ip.h +++ b/us_manager/sspt/ip.h @@ -37,7 +37,7 @@ struct sspt_page; struct us_ip { struct list_head list; /**< For sspt_page */ struct sspt_page *page; /**< Pointer on the page (parent) */ - struct probe_info probe_i; /**< Probe's data */ + struct probe_info *info; /**< Probe's data */ unsigned long orig_addr; /**< Function address */ unsigned long offset; /**< Page offset */ @@ -50,7 +50,7 @@ struct us_ip { #define to_us_ip(rp) container_of(rp, struct us_ip, retprobe) -struct us_ip *create_ip(unsigned long offset, const struct probe_info *probe_i, +struct us_ip *create_ip(unsigned long offset, const struct probe_info *info, struct sspt_page *page); void free_ip(struct us_ip *ip); diff --git a/us_manager/sspt/sspt.h b/us_manager/sspt/sspt.h index cf06221..6524776 100644 --- a/us_manager/sspt/sspt.h +++ b/us_manager/sspt/sspt.h @@ -51,7 +51,7 @@ static inline int sspt_register_usprobe(struct us_ip *ip) int ret; struct uprobe *up = NULL; - up = probe_info_get_uprobe(&ip->probe_i, ip); + up = probe_info_get_uprobe(ip->info, ip); if (!up) { printk(KERN_INFO "SWAP US_MANAGER: failed getting uprobe!\n"); @@ -61,7 +61,7 @@ static inline int sspt_register_usprobe(struct us_ip *ip) up->task = ip->page->file->proc->task; up->sm = ip->page->file->proc->sm; - ret = probe_info_register(&ip->probe_i, ip); + ret = probe_info_register(ip->info, ip); if (ret) { struct sspt_file *file = ip->page->file; char *name = file->dentry->d_iname; @@ -84,14 +84,14 @@ static inline int sspt_unregister_usprobe(struct task_struct *task, switch (flag) { case US_UNREGS_PROBE: - probe_info_unregister(&ip->probe_i, ip, 1); + probe_info_unregister(ip->info, ip, 1); break; case US_DISARM: - up = probe_info_get_uprobe(&ip->probe_i, ip); + up = probe_info_get_uprobe(ip->info, ip); disarm_uprobe(&up->kp, task); break; case US_UNINSTALL: - probe_info_unregister(&ip->probe_i, ip, 0); + probe_info_unregister(ip->info, ip, 0); break; default: panic("incorrect value flag=%d", flag); diff --git a/us_manager/sspt/sspt_debug.h b/us_manager/sspt/sspt_debug.h index 7cb8325..0b3dc79 100644 --- a/us_manager/sspt/sspt_debug.h +++ b/us_manager/sspt/sspt_debug.h @@ -42,7 +42,7 @@ static inline void print_retprobe(struct uretprobe *rp) static inline void print_ip(struct us_ip *ip, int i) { - if (ip->probe_i.probe_type == SWAP_RETPROBE) { + if (ip->info->probe_type == SWAP_RETPROBE) { struct uretprobe *rp = &ip->retprobe; printk(KERN_INFO "### addr[%2d]=%lx, R_addr=%lx\n", diff --git a/us_manager/sspt/sspt_file.c b/us_manager/sspt/sspt_file.c index f0355cd..8b88ff0 100644 --- a/us_manager/sspt/sspt_file.c +++ b/us_manager/sspt/sspt_file.c @@ -306,7 +306,7 @@ int sspt_file_uninstall(struct sspt_file *file, } } - if (flag != US_DISARM) + if (flag != US_DISARM) { file->loaded = 0; file->vm_start = 0; file->vm_end = 0; diff --git a/us_manager/sspt/sspt_page.c b/us_manager/sspt/sspt_page.c index 37deca4..40413a2 100644 --- a/us_manager/sspt/sspt_page.c +++ b/us_manager/sspt/sspt_page.c @@ -164,7 +164,7 @@ int sspt_register_page(struct sspt_page *page, struct sspt_file *file) addr = file->vm_start + page->offset + ip->offset; ip->orig_addr = addr; - up = probe_info_get_uprobe(&ip->probe_i, ip); + up = probe_info_get_uprobe(ip->info, ip); up->kp.addr = (kprobe_opcode_t *)addr; err = sspt_register_usprobe(ip); diff --git a/webprobe/webprobe.c b/webprobe/webprobe.c index 5de8fea..d73b36c 100644 --- a/webprobe/webprobe.c +++ b/webprobe/webprobe.c @@ -154,7 +154,7 @@ static void webprobe_init(struct us_ip *ip) static void webprobe_uninit(struct us_ip *ip) { - webprobe_cleanup(&ip->probe_i); + webprobe_cleanup(ip->info); } -- 2.7.4