From 413b0a1baaaa9f5e1e43b93b590d36bf407e1948 Mon Sep 17 00:00:00 2001 From: Vyacheslav Cherkashin Date: Mon, 11 Apr 2016 17:06:02 +0300 Subject: [PATCH] [IMPROVE] synchronize usage of sspt_proc.files.head Change-Id: Id308856c9d300394e3946094a43b6d3c8102eb0d Signed-off-by: Vyacheslav Cherkashin --- us_manager/helper.c | 40 ++++++++++++++++++++-------------------- us_manager/sspt/sspt_debug.h | 6 ++++-- us_manager/sspt/sspt_proc.c | 40 +++++++++++++++++++++++++++++----------- us_manager/sspt/sspt_proc.h | 6 +++++- 4 files changed, 58 insertions(+), 34 deletions(-) diff --git a/us_manager/helper.c b/us_manager/helper.c index 1bdfecf..e3dde3c 100644 --- a/us_manager/helper.c +++ b/us_manager/helper.c @@ -464,14 +464,12 @@ static void __remove_unmap_probes(struct sspt_proc *proc, } } -static void remove_unmap_probes(struct task_struct *task, - struct unmap_data *umd) +static unsigned long cb_munmap(void *data) { struct sspt_proc *proc; + struct unmap_data *umd = (struct unmap_data *)data; - sspt_proc_write_lock(); - - proc = sspt_proc_get_by_task(task); + proc = sspt_proc_get_by_task(current); if (proc) { struct msg_unmap_data msg_data = { .start = umd->start, @@ -486,39 +484,41 @@ static void remove_unmap_probes(struct task_struct *task, sspt_proc_put(proc); } - sspt_proc_write_unlock(); + atomic_dec(&unmap_cnt); + return 0; } static int entry_handler_unmap(struct kretprobe_instance *ri, struct pt_regs *regs) { struct unmap_data *data = (struct unmap_data *)ri->data; - struct task_struct *task = current->group_leader; - - atomic_inc(&unmap_cnt); data->start = swap_get_karg(regs, 1); data->len = (size_t)PAGE_ALIGN(swap_get_karg(regs, 2)); - if (!is_kthread(task) && atomic_read(&stop_flag)) - remove_unmap_probes(task, data); - + atomic_inc(&unmap_cnt); return 0; } static int ret_handler_unmap(struct kretprobe_instance *ri, struct pt_regs *regs) { - struct task_struct *task; - - task = current->group_leader; - if (is_kthread(task) || regs_return_value(regs)) - goto out; + int ret; - remove_unmap_probes(task, (struct unmap_data *)ri->data); + if (regs_return_value(regs)) { + atomic_dec(&unmap_cnt); + return 0; + } -out: - atomic_dec(&unmap_cnt); + ret = set_jump_cb((unsigned long)ri->ret_addr, regs, cb_munmap, + (struct unmap_data *)ri->data, + sizeof(struct unmap_data)); + if (ret == 0) { + ri->ret_addr = (unsigned long *)get_jump_addr(); + } else { + WARN_ON(1); + atomic_dec(&unmap_cnt); + } return 0; } diff --git a/us_manager/sspt/sspt_debug.h b/us_manager/sspt/sspt_debug.h index 5a22b31..a6830ff 100644 --- a/us_manager/sspt/sspt_debug.h +++ b/us_manager/sspt/sspt_debug.h @@ -101,14 +101,16 @@ static inline void print_file_probes(const struct sspt_file *file) } } -static inline void print_proc_probes(const struct sspt_proc *proc) +static inline void print_proc_probes(struct sspt_proc *proc) { struct sspt_file *file; printk(KERN_INFO "### print_proc_probes\n"); - list_for_each_entry(file, &proc->file_head, list) { + down_read(&proc->files.sem); + list_for_each_entry(file, &proc->files.head, list) { print_file_probes(file); } + up_read(&proc->files.sem); printk(KERN_INFO "### print_proc_probes\n"); } diff --git a/us_manager/sspt/sspt_proc.c b/us_manager/sspt/sspt_proc.c index 28239ac..f5e2512 100644 --- a/us_manager/sspt/sspt_proc.c +++ b/us_manager/sspt/sspt_proc.c @@ -178,11 +178,12 @@ static struct sspt_proc *sspt_proc_create(struct task_struct *leader) } INIT_LIST_HEAD(&proc->list); + INIT_LIST_HEAD(&proc->files.head); + init_rwsem(&proc->files.sem); proc->tgid = leader->tgid; proc->leader = leader; /* FIXME: change the task leader */ proc->sm = create_sm_us(leader); - INIT_LIST_HEAD(&proc->file_head); mutex_init(&proc->filters.mtx); INIT_LIST_HEAD(&proc->filters.head); atomic_set(&proc->usage, 1); @@ -210,10 +211,12 @@ void sspt_proc_cleanup(struct sspt_proc *proc) sspt_proc_del_all_filters(proc); - list_for_each_entry_safe(file, n, &proc->file_head, list) { + down_write(&proc->files.sem); + list_for_each_entry_safe(file, n, &proc->files.head, list) { list_del(&file->list); sspt_file_free(file); } + up_write(&proc->files.sem); sspt_destroy_feature(proc->feature); @@ -349,8 +352,10 @@ void sspt_proc_check_empty(void) static void sspt_proc_add_file(struct sspt_proc *proc, struct sspt_file *file) { - list_add(&file->list, &proc->file_head); + down_write(&proc->files.sem); + list_add(&file->list, &proc->files.head); file->proc = proc; + up_write(&proc->files.sem); } /** @@ -387,12 +392,17 @@ struct sspt_file *sspt_proc_find_file(struct sspt_proc *proc, { struct sspt_file *file; - list_for_each_entry(file, &proc->file_head, list) { + down_read(&proc->files.sem); + list_for_each_entry(file, &proc->files.head, list) { if (dentry == file->dentry) - return file; + goto unlock; } + file = NULL; - return NULL; +unlock: + up_read(&proc->files.sem); + + return file; } /** @@ -464,14 +474,16 @@ int sspt_proc_uninstall(struct sspt_proc *proc, int err = 0; struct sspt_file *file; - list_for_each_entry_rcu(file, &proc->file_head, list) { + down_read(&proc->files.sem); + list_for_each_entry(file, &proc->files.head, list) { err = sspt_file_uninstall(file, task, flag); if (err != 0) { printk(KERN_INFO "ERROR sspt_proc_uninstall: err=%d\n", err); - return err; + break; } } + up_read(&proc->files.sem); return err; } @@ -501,12 +513,14 @@ int sspt_proc_get_files_by_region(struct sspt_proc *proc, struct sspt_file *file, *n; unsigned long end = start + len; - list_for_each_entry_safe(file, n, &proc->file_head, list) { + down_write(&proc->files.sem); + list_for_each_entry_safe(file, n, &proc->files.head, list) { if (intersection(file->vm_start, file->vm_end, start, end)) { ret = 1; list_move(&file->list, head); } } + up_write(&proc->files.sem); return ret; } @@ -520,7 +534,9 @@ int sspt_proc_get_files_by_region(struct sspt_proc *proc, */ void sspt_proc_insert_files(struct sspt_proc *proc, struct list_head *head) { - list_splice(head, &proc->file_head); + down_write(&proc->files.sem); + list_splice(head, &proc->files.head); + up_write(&proc->files.sem); } /** @@ -611,8 +627,10 @@ void sspt_proc_on_each_ip(struct sspt_proc *proc, { struct sspt_file *file; - list_for_each_entry(file, &proc->file_head, list) + down_read(&proc->files.sem); + list_for_each_entry(file, &proc->files.head, list) sspt_file_on_each_ip(file, func, data); + up_read(&proc->files.sem); } static void is_send_event(struct sspt_filter *f, void *data) diff --git a/us_manager/sspt/sspt_proc.h b/us_manager/sspt/sspt_proc.h index 835b9cb..ec7a133 100644 --- a/us_manager/sspt/sspt_proc.h +++ b/us_manager/sspt/sspt_proc.h @@ -26,6 +26,7 @@ #include #include +#include #include "sspt_file.h" struct slot_manager; @@ -49,7 +50,10 @@ struct sspt_proc { struct list_head list; /**< For global process list */ /* sspt_file */ - struct list_head file_head; /**< For sspt_file */ + struct { + struct rw_semaphore sem;/**< Semaphore for files list */ + struct list_head head; /**< For sspt_file */ + } files; pid_t tgid; /**< Thread group ID */ struct task_struct *leader; /**< Ptr to the task leader */ -- 2.7.4