From baea86d42113f4b876fa15f04f1fb3ad9ddcd993 Mon Sep 17 00:00:00 2001 From: Vyacheslav Cherkashin Date: Tue, 11 Jun 2013 12:23:22 +0400 Subject: [PATCH] [FEATURE] first working version working, when install probes on page (do_page_foult()), and creating entity "img_*" --- driver/Kbuild | 1 - driver/us_def_handler.c | 8 +- us_manager/Kbuild | 4 +- us_manager/helper.c | 3 + us_manager/img/img_file.c | 88 ++++++++++++++ us_manager/img/img_file.h | 25 ++++ us_manager/img/img_ip.c | 25 ++++ us_manager/img/img_ip.h | 18 +++ us_manager/img/img_proc.c | 90 ++++++++++++++ us_manager/img/img_proc.h | 22 ++++ us_manager/pf/pf_group.c | 281 +++++++++++++++++++++++++++++++++++++++++++ us_manager/pf/pf_group.h | 29 +++++ us_manager/pf/proc_filters.c | 11 ++ us_manager/pf/proc_filters.h | 8 +- us_manager/sspt/sspt.h | 14 ++- 15 files changed, 618 insertions(+), 9 deletions(-) create mode 100644 us_manager/img/img_file.c create mode 100644 us_manager/img/img_file.h create mode 100644 us_manager/img/img_ip.c create mode 100644 us_manager/img/img_ip.h create mode 100644 us_manager/img/img_proc.c create mode 100644 us_manager/img/img_proc.h create mode 100644 us_manager/pf/pf_group.c create mode 100644 us_manager/pf/pf_group.h diff --git a/driver/Kbuild b/driver/Kbuild index 0f84b58..35d18c0 100644 --- a/driver/Kbuild +++ b/driver/Kbuild @@ -3,5 +3,4 @@ EXTRA_CFLAGS := $(extra_cflags) obj-m := swap_driver.o swap_driver-y := error_storage.o device_driver.o ec.o legacy.o module.o probes.o \ probes_manager.o storage.o us_proc_inst.o \ - us_def_handler.o \ ks_def_handler.o diff --git a/driver/us_def_handler.c b/driver/us_def_handler.c index 31f4f7a..fa3ef09 100644 --- a/driver/us_def_handler.c +++ b/driver/us_def_handler.c @@ -33,7 +33,7 @@ void ujprobe_event_handler(unsigned long arg0, unsigned long arg1, addr = ip->offset & 0x01 ? addr | 0x01 : addr; #endif - pack_event_info(US_PROBE_ID, RECORD_ENTRY, "ppppppp", addr, arg0, arg1, + ptr_pack_task_event_info(current, US_PROBE_ID, RECORD_ENTRY, "ppppppp", addr, arg0, arg1, arg2, arg3, arg4, arg5); swap_ujprobe_return(); } @@ -65,11 +65,11 @@ static void send_plt(struct us_ip *ip) } if (name) - pack_event_info(PLT_ADDR_PROBE_ID, RECORD_RET, "ppsp", + ptr_pack_task_event_info(current, PLT_ADDR_PROBE_ID, RECORD_RET, "ppsp", addr, real_addr, name, real_addr - vma->vm_start); else - pack_event_info(PLT_ADDR_PROBE_ID, RECORD_RET, "ppp", + ptr_pack_task_event_info(current, PLT_ADDR_PROBE_ID, RECORD_RET, "ppp", addr, real_addr, real_addr - vma->vm_start); } @@ -91,7 +91,7 @@ int uretprobe_event_handler(struct uretprobe_instance *probe, addr = ip->offset & 0x01 ? addr | 0x01 : addr; #endif - pack_event_info(US_PROBE_ID, RECORD_RET, "pd", addr, retval); + ptr_pack_task_event_info(current, US_PROBE_ID, RECORD_RET, "pd", addr, retval); return 0; } diff --git a/us_manager/Kbuild b/us_manager/Kbuild index ebdf08d..b2addfc 100644 --- a/us_manager/Kbuild +++ b/us_manager/Kbuild @@ -3,4 +3,6 @@ EXTRA_CFLAGS := $(extra_cflags) obj-m := swap_us_manager.o swap_us_manager-y := us_manager.o us_slot_manager.o helper.o \ sspt/ip.o sspt/sspt_page.o sspt/sspt_file.o sspt/sspt_proc.o \ - pf/proc_filters.o + pf/proc_filters.o pf/pf_group.o \ + img/img_proc.o img/img_file.o img/img_ip.o \ + ../driver/us_def_handler.o diff --git a/us_manager/helper.c b/us_manager/helper.c index 69458d8..7fbe6b0 100644 --- a/us_manager/helper.c +++ b/us_manager/helper.c @@ -42,6 +42,9 @@ static int ret_handler_pf(struct kretprobe_instance *ri, struct pt_regs *regs) struct task_struct *task; struct sspt_proc *proc; + install_page(((struct pf_data *)ri->data)->addr); + return 0; + /* * Because process threads have same address space * we instrument only group_leader of all this threads diff --git a/us_manager/img/img_file.c b/us_manager/img/img_file.c new file mode 100644 index 0000000..5daeea2 --- /dev/null +++ b/us_manager/img/img_file.c @@ -0,0 +1,88 @@ +#include "img_file.h" +#include "img_ip.h" +#include +#include + +struct img_file *create_img_file(struct dentry *dentry) +{ + struct img_file *file; + + file = kmalloc(sizeof(*file), GFP_KERNEL); + file->dentry = dentry; + INIT_LIST_HEAD(&file->ip_list); + INIT_LIST_HEAD(&file->list); + + return file; +} + +void free_img_file(struct img_file *file) +{ + /* FIXME: */ +} + +static void img_add_ip_by_list(struct img_file *file, struct img_ip *ip) +{ + list_add(&ip->list, &file->ip_list); +} + +static void img_del_ip_by_list(struct img_ip *ip) +{ + list_del(&ip->list); +} + +static struct img_ip *find_img_ip(struct img_file *file, unsigned long addr) +{ + struct img_ip *ip; + + list_for_each_entry(ip, &file->ip_list, list) { + if (ip->addr == addr) + return ip; + } + + return NULL; +} + +int img_file_add_ip(struct img_file *file, unsigned long addr) +{ + struct img_ip *ip; + + ip = find_img_ip(file, addr); + if (ip) + return -EINVAL; + + ip = create_img_ip(addr); + img_add_ip_by_list(file, ip); + + return 0; +} + +int img_file_del_ip(struct img_file *file, unsigned long addr) +{ + struct img_ip *ip; + + ip = find_img_ip(file, addr); + if (ip == NULL) + return -EINVAL; + + img_del_ip_by_list(ip); + + return 0; +} + +int img_file_empty(struct img_file *file) +{ + return list_empty(&file->ip_list); +} + +/* debug */ +void img_file_print(struct img_file *file) +{ + struct img_ip *ip; + + printk("### d_iname=%s\n", file->dentry->d_iname); + + list_for_each_entry(ip, &file->ip_list, list) { + img_ip_print(ip); + } +} +/* debug */ diff --git a/us_manager/img/img_file.h b/us_manager/img/img_file.h new file mode 100644 index 0000000..d4f2b4f --- /dev/null +++ b/us_manager/img/img_file.h @@ -0,0 +1,25 @@ +#ifndef _IMG_FILE_H +#define _IMG_FILE_H + +#include + +struct img_file { + struct list_head list; /* for img_proc */ + struct dentry *dentry; + struct list_head ip_list; /* for img_ip */ +}; + +struct img_file *create_img_file(struct dentry *dentry); +void free_img_file(struct img_file *ip); + +int img_file_add_ip(struct img_file *file, unsigned long addr); +int img_file_del_ip(struct img_file *file, unsigned long addr); + +int img_file_empty(struct img_file *file); + +/* debug */ +void img_file_print(struct img_file *file); +/* debug */ + +#endif /* _IMG_FILE_H */ + diff --git a/us_manager/img/img_ip.c b/us_manager/img/img_ip.c new file mode 100644 index 0000000..2f2410d --- /dev/null +++ b/us_manager/img/img_ip.c @@ -0,0 +1,25 @@ +#include "img_ip.h" +#include + +struct img_ip *create_img_ip(unsigned long addr) +{ + struct img_ip *ip; + + ip = kmalloc(sizeof(*ip), GFP_KERNEL); + INIT_LIST_HEAD(&ip->list); + ip->addr = addr; + + return ip; +} + +void free_img_ip(struct img_ip *ip) +{ + kfree(ip); +} + +/* debug */ +void img_ip_print(struct img_ip *ip) +{ + printk("### addr=%x\n", ip->addr); +} +/* debug */ diff --git a/us_manager/img/img_ip.h b/us_manager/img/img_ip.h new file mode 100644 index 0000000..b6c41a6 --- /dev/null +++ b/us_manager/img/img_ip.h @@ -0,0 +1,18 @@ +#ifndef _IMG_IP_H +#define _IMG_IP_H + +#include + +struct img_ip { + struct list_head list; /* for img_file */ + unsigned long addr; +}; + +struct img_ip *create_img_ip(unsigned long addr); +void free_img_ip(struct img_ip *ip); + +/* debug */ +void img_ip_print(struct img_ip *ip); +/* debug */ + +#endif /* _IMG_IP_H */ diff --git a/us_manager/img/img_proc.c b/us_manager/img/img_proc.c new file mode 100644 index 0000000..054d95a --- /dev/null +++ b/us_manager/img/img_proc.c @@ -0,0 +1,90 @@ +#include "img_proc.h" +#include "img_file.h" +#include + +struct img_proc *create_img_proc(void) +{ + struct img_proc *proc; + + proc = kmalloc(sizeof(*proc), GFP_KERNEL); + INIT_LIST_HEAD(&proc->file_list); + + return proc; +} + +void free_img_proc(struct img_proc *ip) +{ + /* FIXME: */ +} + +static void img_add_file_by_list(struct img_proc *proc, struct img_file *file) +{ + list_add(&file->list, &proc->file_list); +} + +static void img_del_file_by_list(struct img_file *file) +{ + list_del(&file->list); +} + +static struct img_file *find_img_file(struct img_proc *proc, struct dentry *dentry) +{ + struct img_file *file; + + list_for_each_entry(file, &proc->file_list, list) { + if (file->dentry == dentry) + return file; + } + + return NULL; +} + +int img_proc_add_ip(struct img_proc *proc, struct dentry *dentry, unsigned long addr) +{ + int ret; + struct img_file *file; + + file = find_img_file(proc, dentry); + if (file) + return img_file_add_ip(file, addr); + + file = create_img_file(dentry); + + ret = img_file_add_ip(file, addr); + if (ret) + free_img_file(file); + else + img_add_file_by_list(proc, file); + + return ret; +} + +int img_proc_del_ip(struct img_proc *proc, struct dentry *dentry, unsigned long addr) +{ + int ret; + struct img_file *file; + + file = find_img_file(proc, dentry); + if (file == NULL) + return -EINVAL; + + ret = img_file_del_ip(file, addr); + if (ret == 0 && img_file_empty(file)) { + img_del_file_by_list(file); + free_img_file(file); + } + + return ret; +} + +/* debug */ +void img_proc_print(struct img_proc *proc) +{ + struct img_file *file; + + printk("### img_proc_print:\n"); + list_for_each_entry(file, &proc->file_list, list) { + img_file_print(file); + } +} +/* debug */ diff --git a/us_manager/img/img_proc.h b/us_manager/img/img_proc.h new file mode 100644 index 0000000..b6e253d --- /dev/null +++ b/us_manager/img/img_proc.h @@ -0,0 +1,22 @@ +#ifndef _IMG_PROC_H +#define _IMG_PROC_H + +#include + +struct dentry; + +struct img_proc { + struct list_head file_list; +}; + +struct img_proc *create_img_proc(void); +void free_img_proc(struct img_proc *proc); + +int img_proc_add_ip(struct img_proc *proc, struct dentry *dentry, unsigned long addr); +int img_proc_del_ip(struct img_proc *proc, struct dentry *dentry, unsigned long addr); + +/* debug */ +void img_proc_print(struct img_proc *proc); +/* debug */ + +#endif /* _IMG_PROC_H */ diff --git a/us_manager/pf/pf_group.c b/us_manager/pf/pf_group.c new file mode 100644 index 0000000..8428a1b --- /dev/null +++ b/us_manager/pf/pf_group.c @@ -0,0 +1,281 @@ +#include +#include +#include +#include "proc_filters.h" +#include +#include +#include +#include +#include + +#include "../../driver/us_def_handler.h" + +struct pf_group { + struct list_head list; + struct img_proc *i_proc; + struct proc_filter *filter; + + /* TODO: proc_list*/ + struct list_head proc_list; +}; + +struct pl_struct { + struct list_head list; + struct sspt_proc *proc; +}; + +static LIST_HEAD(proc_list); + +/* struct pl_struct */ +static struct pl_struct *create_pl_struct(struct sspt_proc *proc) +{ + struct pl_struct *pls = kmalloc(sizeof(*pls), GFP_KERNEL); + + INIT_LIST_HEAD(&pls->list); + pls->proc = proc; + + return pls; +} + +static void free_pl_struct(struct pl_struct *pls) +{ + /* FIXME: free */ +} + +static void add_pl_struct(struct pf_group *pfg, struct pl_struct *pls) +{ + list_add(&pls->list, &pfg->proc_list); +} + +static void del_pl_struct(struct pl_struct *pls) +{ + list_del(&pls->list); +} + +void copy_proc_form_img_to_sspt(struct img_proc *i_proc, struct sspt_proc *proc) +{ + char *file_name; + struct sspt_file *file; + struct ip_data ip_d; + struct dentry *dentry; + + struct img_file *i_file; + struct img_ip *i_ip; + + list_for_each_entry(i_file, &i_proc->file_list, list) { + dentry = i_file->dentry; + file_name = dentry->d_iname; + file = sspt_proc_find_file_or_new(proc, dentry, file_name); + + list_for_each_entry(i_ip, &i_file->ip_list, list) { + ip_d.flag_retprobe = 1; + ip_d.got_addr = 0; + ip_d.jp_handler = ujprobe_event_handler; + ip_d.offset = i_ip->addr; + ip_d.pre_handler = ujprobe_event_pre_handler; + ip_d.rp_handler = uretprobe_event_handler; + + sspt_file_add_ip(file, &ip_d); + } + } +} + +static struct sspt_proc *get_proc_by_pfg(struct pf_group *pfg, + struct task_struct *task) +{ + struct pl_struct *pls; + + list_for_each_entry(pls, &pfg->proc_list, list) { + if (pls->proc->tgid == task->tgid) + return pls->proc; + } + + return NULL; +} + +static struct sspt_proc *get_proc_by_pfg_or_new(struct pf_group *pfg, + struct task_struct *task) +{ + struct sspt_proc *proc; + + proc = get_proc_by_pfg(pfg, task); + if (proc == NULL) { + struct pl_struct *pls; + + /* or find?! */ + proc = sspt_proc_get_new(task); + copy_proc_form_img_to_sspt(pfg->i_proc, proc); + + pls = create_pl_struct(proc); + add_pl_struct(pfg, pls); + } + + return proc; +} +/* struct pl_struct */ + +static struct pf_group *create_pfg(struct proc_filter *filter) +{ + struct pf_group *pfg = kmalloc(sizeof(*pfg), GFP_KERNEL); + + INIT_LIST_HEAD(&pfg->list); + pfg->filter = filter; + pfg->i_proc = create_img_proc(); + INIT_LIST_HEAD(&pfg->proc_list); + + return pfg; +} + +static void free_pfg(struct pf_group *pfg) +{ + /* FIXME: */ + kfree(pfg); +} + +static void add_pfg_by_list(struct pf_group *pfg) +{ + list_add(&pfg->list, &proc_list); +} + +static void del_pfg_by_list(struct pf_group *pfg) +{ + list_del(&pfg->list); +} + +struct pf_group *get_pf_group_by_dentry(struct dentry *dentry) +{ + struct pf_group *pfg; + struct proc_filter *filter; + + list_for_each_entry(pfg, &proc_list, list) { + if (check_pf_by_dentry(pfg->filter, dentry)) + return pfg; + } + + filter = create_pf_by_dentry(dentry); + pfg = create_pfg(filter); + + add_pfg_by_list(pfg); + + return pfg; +} +EXPORT_SYMBOL_GPL(get_pf_group_by_dentry); + +struct pf_group *get_pf_group_by_tgid(pid_t tgid) +{ + struct pf_group *pfg; + struct proc_filter *filter; + + list_for_each_entry(pfg, &proc_list, list) { + if (check_pf_by_tgid(pfg->filter, tgid)) + return pfg; + } + + filter = create_pf_by_tgid(tgid); + pfg = create_pfg(filter); + + add_pfg_by_list(pfg); + + return pfg; +} + +void put_pf_group(struct pf_group *pfg) +{ + +} + +int pf_register_probe(struct pf_group *pfg, struct dentry *dentry, + unsigned long offset, void *pre_handler, + void *jp_handler, void *rp_handler) +{ + return img_proc_add_ip(pfg->i_proc, dentry, offset); +} +EXPORT_SYMBOL_GPL(pf_register_probe); + +int pf_unregister_probe(struct pf_group *pfg, struct dentry *dentry, + unsigned long offset) +{ + return img_proc_del_ip(pfg->i_proc, dentry, offset); +} + +void install_all(void) +{ + +} + +void uninstall_all(void) +{ +// struct pf_group *pfg; +// list_for_each_entry(pfg, &proc_list, list) { +// struct task_struct *task, ts; +// +// rcu_read_lock(); +// for_each_process(task) { +// if (task->tgid != task->pid) +// continue; +// +// if (is_kthread(task)) +// continue; +// +// ts = check_task_f(pfg->filter, task); +// +// if (ts) { +// proc = sspt_proc_get_by_task_or_new(ts); +// sspt_proc_install(proc); +// } +// } +// rcu_read_unlock(); +// } +} + + +static void install_page_by_pfg(unsigned long addr, struct task_struct *task, + struct pf_group *pfg) +{ + struct sspt_proc *proc; + + proc = get_proc_by_pfg(pfg, task); + if (proc) + goto install_proc; + + task = check_task_f(pfg->filter, task); + if (task) { + proc = get_proc_by_pfg_or_new(pfg, task); + goto install_proc; + } + + return; + +install_proc: + if (proc->first_install) + sspt_proc_install_page(proc, addr & PAGE_MASK); + else + sspt_proc_install(proc); +} + +void install_page(unsigned long addr) +{ + struct pf_group *pfg; + struct task_struct *task, *ts; + + task = current->group_leader; + if (is_kthread(task)) + return; + + list_for_each_entry(pfg, &proc_list, list) { + install_page_by_pfg(addr, task, pfg); + } +} + +void uninstall_page(unsigned long addr) +{ + +} + +/* debug */ +void pfg_print(struct pf_group *pfg) +{ + img_proc_print(pfg->i_proc); +} +EXPORT_SYMBOL_GPL(pfg_print); +/* debug */ diff --git a/us_manager/pf/pf_group.h b/us_manager/pf/pf_group.h new file mode 100644 index 0000000..1e3c3b4 --- /dev/null +++ b/us_manager/pf/pf_group.h @@ -0,0 +1,29 @@ +#ifndef _PF_GROUP_H +#define _PF_GROUP_H + +#include + +struct dentry; +struct pf_group; + +struct pf_group *get_pf_group_by_dentry(struct dentry *dentry); +struct pf_group *get_pf_group_by_tgid(pid_t tgid); +void put_pf_group(struct pf_group *pfg); + +int pf_register_probe(struct pf_group *pfg, struct dentry *dentry, + unsigned long offset, void *pre_handler, + void *jp_handler, void *rp_handler); +int pf_unregister_probe(struct pf_group *pfg, struct dentry *dentry, + unsigned long offset); + +void install_all(void); +void uninstall_all(void); + +void install_page(unsigned long addr); +void uninstall_page(unsigned long addr); + +/* debug */ +void pfg_print(struct pf_group *pfg); +/* debug */ + +#endif /* _PF_GROUP_H */ diff --git a/us_manager/pf/proc_filters.c b/us_manager/pf/proc_filters.c index 29ae507..43004a0 100644 --- a/us_manager/pf/proc_filters.c +++ b/us_manager/pf/proc_filters.c @@ -75,3 +75,14 @@ void free_pf(struct proc_filter *pf) { kfree(pf); } + +int check_pf_by_dentry(struct proc_filter *filter, struct dentry *dentry) +{ + return filter->data == (void *)dentry && + filter->call == &call_by_dentry; +} + +int check_pf_by_tgid(struct proc_filter *filter, pid_t tgid) +{ + return filter->data == (void *)tgid && filter->call == &call_by_tgid; +} diff --git a/us_manager/pf/proc_filters.h b/us_manager/pf/proc_filters.h index 6b68ca2..315d18d 100644 --- a/us_manager/pf/proc_filters.h +++ b/us_manager/pf/proc_filters.h @@ -6,12 +6,18 @@ struct task_struct; struct proc_filter { - struct task_struct *(*call)(struct proc_filter *self, struct task_struct *task); + struct task_struct *(*call)(struct proc_filter *self, + struct task_struct *task); void *data; }; +#define check_task_f(filter, task) filter->call(filter, task) + struct proc_filter *create_pf_by_dentry(struct dentry *dentry); struct proc_filter *create_pf_by_tgid(pid_t tgid); void free_pf(struct proc_filter *pf); +int check_pf_by_dentry(struct proc_filter *filter, struct dentry *dentry); +int check_pf_by_tgid(struct proc_filter *filter, pid_t tgid); + #endif /* _PROC_FILTERS_H */ diff --git a/us_manager/sspt/sspt.h b/us_manager/sspt/sspt.h index ac209d9..e1de782 100644 --- a/us_manager/sspt/sspt.h +++ b/us_manager/sspt/sspt.h @@ -40,6 +40,7 @@ #include "../../common/ec_probe.h" #include +#include static void print_proc_probes(const struct sspt_proc *proc); @@ -48,6 +49,9 @@ struct sspt_proc; static inline struct sspt_proc *get_file_probes(inst_us_proc_t *task_inst_info) { int i, ret; + struct pf_group *pfg; + + pfg = get_pf_group_by_dentry(task_inst_info->m_f_dentry); for (i = 0; i < task_inst_info->libs_count; ++i) { int k, j; @@ -76,9 +80,13 @@ static inline struct sspt_proc *get_file_probes(inst_us_proc_t *task_inst_info) pd.jp_handler = (unsigned long) (ip->jprobe.entry ? ip->jprobe.entry : ujprobe_event_handler); pd.rp_handler = ip->retprobe.handler ? ip->retprobe.handler : uretprobe_event_handler; - ret = usm_register_probe(dentry, pd.offset, pd.pre_handler, pd.jp_handler, pd.rp_handler); +// ret = usm_register_probe(dentry, pd.offset, pd.pre_handler, pd.jp_handler, pd.rp_handler); +// if (ret) +// printk("### ERROR: usm_register_probe ret=%d\n", ret); + + ret = pf_register_probe(pfg, dentry, pd.offset, pd.pre_handler, pd.jp_handler, pd.rp_handler); if (ret) - printk("### ERROR: usm_register_probe ret=%d\n", ret); + printk("### ERROR: pf_register_probe ret=%d\n", ret); } } @@ -86,6 +94,8 @@ static inline struct sspt_proc *get_file_probes(inst_us_proc_t *task_inst_info) printk("####### get END #######\n"); + pfg_print(pfg); + return NULL; } -- 2.7.4