}
}
-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,
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;
}
}
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);
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);
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);
}
/**
{
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;
}
/**
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;
}
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;
}
*/
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);
}
/**
{
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)