struct task_struct *check_task(struct task_struct *task);
+static atomic_t stop_flag = ATOMIC_INIT(0);
+
+
/*
******************************************************************************
* do_page_fault() *
* copy_process() *
******************************************************************************
*/
+static atomic_t copy_process_cnt = ATOMIC_INIT(0);
static void recover_child(struct task_struct *child_task, struct sspt_proc *proc)
{
static void rm_uprobes_child(struct task_struct *task)
{
- struct sspt_proc *proc = sspt_proc_get_by_task(current);
- if(proc) {
+ struct sspt_proc *proc;
+
+ sspt_proc_write_lock();
+
+ proc = sspt_proc_get_by_task(current);
+ if (proc)
recover_child(task, proc);
- }
+
+ sspt_proc_write_unlock();
+}
+
+static int entry_handler_cp(struct kretprobe_instance *ri, struct pt_regs *regs)
+{
+ atomic_inc(©_process_cnt);
+
+ if (atomic_read(&stop_flag))
+ call_mm_release(current);
+
+ return 0;
}
/* Delete uprobs in children at fork */
rm_uprobes_child(task);
}
out:
+ atomic_dec(©_process_cnt);
+
return 0;
}
static struct kretprobe cp_kretprobe = {
+ .entry_handler = entry_handler_cp,
.handler = ret_handler_cp,
};
static void unregister_cp(void)
{
- dbi_unregister_kretprobe(&cp_kretprobe);
+ dbi_unregister_kretprobe_top(&cp_kretprobe, 0);
+ do {
+ synchronize_sched();
+ } while (atomic_read(©_process_cnt));
+ dbi_unregister_kretprobe_bottom(&cp_kretprobe);
}
size_t len;
};
-static void remove_unmap_probes(struct sspt_proc *proc, struct unmap_data *umd)
+static atomic_t unmap_cnt = ATOMIC_INIT(0);
+
+static void __remove_unmap_probes(struct sspt_proc *proc,
+ struct unmap_data *umd)
{
struct task_struct *task = proc->task;
unsigned long start = umd->start;
}
}
+static void remove_unmap_probes(struct task_struct *task,
+ struct unmap_data *umd)
+{
+ struct sspt_proc *proc;
+
+ sspt_proc_write_lock();
+
+ proc = sspt_proc_get_by_task(task);
+ if (proc)
+ __remove_unmap_probes(proc, umd);
+
+ sspt_proc_write_unlock();
+}
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)swap_get_karg(regs, 2);
+ if (!is_kthread(task) && atomic_read(&stop_flag))
+ remove_unmap_probes(task, data);
+
return 0;
}
struct pt_regs *regs)
{
struct task_struct *task;
- struct sspt_proc *proc;
task = current->group_leader;
if (is_kthread(task) ||
get_regs_ret_val(regs))
return 0;
- proc = sspt_proc_get_by_task(task);
- if (proc)
- remove_unmap_probes(proc, (struct unmap_data *)ri->data);
+ remove_unmap_probes(task, (struct unmap_data *)ri->data);
+
+ atomic_dec(&unmap_cnt);
return 0;
}
static void unregister_unmap(void)
{
- dbi_unregister_kretprobe(&unmap_kretprobe);
+ dbi_unregister_kretprobe_top(&unmap_kretprobe, 0);
+ do {
+ synchronize_sched();
+ } while (atomic_read(&unmap_cnt));
+ dbi_unregister_kretprobe_bottom(&unmap_kretprobe);
}
{
int ret = 0;
+ atomic_set(&stop_flag, 0);
+
/* install probe on 'do_munmap' to detect when for remove US probes */
ret = register_unmap();
if (ret)
void unregister_helper_top(void)
{
unregister_mf();
+ atomic_set(&stop_flag, 1);
}
void unregister_helper_bottom(void)
}
static LIST_HEAD(proc_probes_list);
-static DEFINE_SPINLOCK(proc_lock);
+static DEFINE_RWLOCK(sspt_proc_rwlock);
+
+void sspt_proc_read_lock(void)
+{
+ read_lock(&sspt_proc_rwlock);
+}
+
+void sspt_proc_read_unlock(void)
+{
+ read_unlock(&sspt_proc_rwlock);
+}
+
+void sspt_proc_write_lock(void)
+{
+ write_lock(&sspt_proc_rwlock);
+}
+
+void sspt_proc_write_unlock(void)
+{
+ write_unlock(&sspt_proc_rwlock);
+}
+
struct sspt_proc *sspt_proc_create(struct task_struct *task, void *priv)
{
return proc;
}
+/* called with sspt_proc_write_lock() */
void sspt_proc_free(struct sspt_proc *proc)
{
struct sspt_file *file, *n;
/* delete from list */
- spin_lock(&proc_lock);
list_del(&proc->list);
- spin_unlock(&proc_lock);
list_for_each_entry_safe(file, n, &proc->file_list, list) {
list_del(&file->list);
void on_each_proc(void (*func)(struct sspt_proc *, void *), void *data)
{
- spin_lock(&proc_lock);
+ sspt_proc_read_lock();
on_each_proc_no_lock(func, data);
- spin_unlock(&proc_lock);
+ sspt_proc_read_unlock();
}
EXPORT_SYMBOL_GPL(on_each_proc);
-void wait_proc_lock(void)
-{
- spin_lock(&proc_lock);
- spin_unlock(&proc_lock);
-}
-
struct sspt_proc *sspt_proc_get_by_task_or_new(struct task_struct *task,
void *priv)
{
void on_each_proc_no_lock(void (*func)(struct sspt_proc *, void *),
void *data);
void on_each_proc(void (*func)(struct sspt_proc *, void *), void *data);
-void wait_proc_lock(void);
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,
unsigned long start, size_t len);
void sspt_proc_insert_files(struct sspt_proc *proc, struct list_head *head);
+void sspt_proc_read_lock(void);
+void sspt_proc_read_unlock(void);
+void sspt_proc_write_lock(void);
+void sspt_proc_write_unlock(void);
+
+
#endif /* __SSPT_PROC__ */