void *data = NULL;
struct sspt_proc *proc;
- proc = sspt_proc_get_by_task(task);
+ proc = sspt_proc_by_task(task);
if (proc)
data = sspt_get_feature_data(proc->feature, feature_id);
return false;
r_debug_addr += r_state_offset;
- proc = sspt_proc_get_by_task(task);
+ proc = sspt_proc_by_task(task);
if (proc)
proc->r_state_addr = r_debug_addr;
return 0;
}
- proc = sspt_proc_get_by_task(task);
+ proc = sspt_proc_by_task(task);
if (!proc)
return 0;
if (IS_ERR_VALUE(vaddr))
return 0;
- proc = sspt_proc_get_by_task(task);
+ proc = sspt_proc_by_task(task);
if (!proc)
return 0;
{
struct pd_t *pd;
- pd = do_create_pd(proc->task);
+ pd = do_create_pd(proc->leader);
return (void *)pd;
}
#endif /* CONFIG_arch */
if (data->addr) {
- struct sspt_proc * proc = sspt_proc_get_by_task(current);
+ struct sspt_proc *proc = sspt_proc_by_task(current);
if (proc && (proc->r_state_addr == data->addr))
/* skip ret_handler_pf() for current task */
};
sspt_proc_write_lock();
- proc = sspt_proc_get_by_task_no_lock(current);
+ proc = sspt_proc_by_task(current);
if (proc) {
sspt_proc_on_each_ip(proc, func_uinst_creare, (void *)&cdata.head);
urinst_info_get_current_hlist(&cdata.rhead, false);
/* TODO: this lock for synchronizing to disarm urp */
down_write(&mm->mmap_sem);
- if (task->tgid != task->pid) {
+ if (task != task->group_leader) {
struct sspt_proc *proc;
struct hlist_head head = HLIST_HEAD_INIT;
/* if the thread is killed we need to discard pending
* uretprobe instances which have not triggered yet */
sspt_proc_write_lock();
- proc = sspt_proc_get_by_task_no_lock(task);
+ proc = sspt_proc_by_task(task);
if (proc) {
urinst_info_get_current_hlist(&head, true);
}
if (sspt_proc_get_files_by_region(proc, &head, start, len)) {
struct sspt_file *file, *n;
unsigned long end = start + len;
- struct task_struct *task = proc->task;
+ struct task_struct *task = proc->leader;
list_for_each_entry_safe(file, n, &head, list) {
if (file->vm_start >= end)
sspt_proc_write_lock();
- proc = sspt_proc_get_by_task_no_lock(task);
+ proc = sspt_proc_by_task(task);
if (proc) {
struct msg_unmap_data msg_data = {
.start = umd->start,
if (IS_ERR_VALUE(start_addr))
return 0;
- proc = sspt_proc_get_by_task(task);
+ proc = sspt_proc_by_task(task);
if (proc == NULL)
return 0;
+/*
+ ******************************************************************************
+ * release_task() *
+ ******************************************************************************
+ */
+static int release_task_h(struct kprobe *p, struct pt_regs *regs)
+{
+ struct task_struct *task = (struct task_struct *)swap_get_karg(regs, 0);
+ struct task_struct *cur = current;
+
+ if (cur->flags & PF_KTHREAD)
+ return 0;
+
+ /* EXEC: change group leader */
+ if (cur != task && task->pid == cur->pid)
+ sspt_change_leader(task, cur);
+
+ return 0;
+}
+
+struct kprobe release_task_kp = {
+ .pre_handler = release_task_h,
+};
+
+static int reg_release_task(void)
+{
+ return swap_register_kprobe(&release_task_kp);
+}
+
+static void unreg_release_task(void)
+{
+ swap_unregister_kprobe(&release_task_kp);
+}
+
+
+
+
/**
* @brief Registration of helper
atomic_set(&stop_flag, 0);
+ /* tracking group leader changing */
+ ret = reg_release_task();
+ if (ret)
+ return ret;
+
/*
* install probe on 'set_task_comm' to detect when field comm struct
* task_struct changes
*/
ret = register_comm();
if (ret)
- return ret;
+ goto unreg_rel_task;
/* install probe on 'do_munmap' to detect when for remove US probes */
ret = register_unmap();
unreg_comm:
unregister_comm();
+unreg_rel_task:
+ unreg_release_task();
+
return ret;
}
unregister_mr();
unregister_unmap();
unregister_comm();
+ unreg_release_task();
}
/**
if (comm_kretprobe.kp.addr == NULL)
goto not_found;
+ sym = "release_task";
+ release_task_kp.addr = (kprobe_opcode_t *)swap_ksyms(sym);
+ if (release_task_kp.addr == NULL)
+ goto not_found;
+
return 0;
not_found:
return 0;
}
+static int pfg_del_proc(struct pf_group *pfg, struct sspt_proc *proc)
+{
+ struct pl_struct *pls, *pls_free = NULL;
+
+ spin_lock(&pfg->pl_lock);
+ list_for_each_entry(pls, &pfg->proc_list, list) {
+ if (pls->proc == proc) {
+ list_del(&pls->list);
+ pls_free = pls;
+ break;
+ }
+ }
+ spin_unlock(&pfg->pl_lock);
+
+ if (pls_free)
+ free_pl_struct(pls_free);
+
+ return !!pls_free;
+}
+
/* called with pfg_list_lock held */
static void pfg_add_to_list(struct pf_group *pfg)
dentry = (struct dentry *)f->pfg->filter.priv;
if (cb->msg_info)
- cb->msg_info(f->proc->task, dentry);
+ cb->msg_info(f->proc->leader, dentry);
if (cb->msg_status_info)
- cb->msg_status_info(f->proc->task);
+ cb->msg_status_info(f->proc->leader);
}
}
}
continue;
if (proc == NULL)
- proc = sspt_proc_get_by_task(task);
+ proc = sspt_proc_by_task(task);
if (proc) {
flag = flag == PIF_NONE ? PIF_SECOND : flag;
return flag;
}
+static void pfg_all_del_proc(struct sspt_proc *proc)
+{
+ struct pf_group *pfg;
+
+ pfg_list_rlock();
+ list_for_each_entry(pfg, &pfg_list, list)
+ pfg_del_proc(pfg, proc);
+ pfg_list_runlock();
+}
+
/**
* @brief Check task and install probes on demand
*
switch (flag) {
case PIF_FIRST:
case PIF_ADD_PFG:
- proc = sspt_proc_get_by_task(task);
+ proc = sspt_proc_by_task(task);
if (proc)
first_install(task, proc);
break;
switch (flag) {
case PIF_FIRST:
case PIF_ADD_PFG:
- proc = sspt_proc_get_by_task(task);
+ proc = sspt_proc_by_task(task);
if (proc)
first_install(task, proc);
break;
case PIF_SECOND:
- proc = sspt_proc_get_by_task(task);
+ proc = sspt_proc_by_task(task);
if (proc)
subsequent_install(task, proc, page_addr);
break;
/* called with sspt_proc_write_lock() */
void uninstall_proc(struct sspt_proc *proc)
{
- struct task_struct *task = proc->task;
+ struct task_struct *task = proc->leader;
sspt_proc_uninstall(proc, task, US_UNREGS_PROBE);
sspt_proc_cleanup(proc);
}
+
+static void mmr_from_exit(struct sspt_proc *proc)
+{
+ BUG_ON(proc->leader != current);
+
+ sspt_proc_write_lock();
+ list_del(&proc->list);
+ sspt_proc_write_unlock();
+
+ uninstall_proc(proc);
+
+ pfg_all_del_proc(proc);
+ sspt_reset_proc(proc->leader);
+}
+
+static void mmr_from_exec(struct sspt_proc *proc)
+{
+ BUG_ON(proc->leader != current);
+
+ if (proc->suspect.after_exec) {
+ sspt_proc_uninstall(proc, proc->leader, US_UNREGS_PROBE);
+ } else {
+ mmr_from_exit(proc);
+ }
+}
+
/**
* @brief Remove probes from the task on demand
*
{
struct sspt_proc *proc;
- sspt_proc_write_lock();
- proc = sspt_proc_get_by_task_no_lock(task);
- if (proc)
- list_del(&proc->list);
- sspt_proc_write_unlock();
-
- if (proc)
- uninstall_proc(proc);
+ proc = sspt_proc_by_task(task);
+ if (proc) {
+ if (task->flags & PF_EXITING)
+ mmr_from_exit(proc);
+ else
+ mmr_from_exec(proc);
+ }
}
/**
if (task->flags & PF_KTHREAD)
continue;
- if (sspt_proc_get_by_task(task))
+ if (sspt_proc_by_task(task))
continue;
/* TODO: get rid of GFP_ATOMIC */
static void __do_get_proc(struct sspt_proc *proc, void *data)
{
- get_task_struct(proc->task);
- proc->__task = proc->task;
- proc->__mm = get_task_mm(proc->task);
+ struct task_struct *task = proc->leader;
+
+ get_task_struct(task);
+ proc->__task = task;
+ proc->__mm = get_task_mm(task);
}
static void __do_put_proc(struct sspt_proc *proc, void *data)
}
up->addr = (kprobe_opcode_t *)ip->orig_addr;
- up->task = ip->page->file->proc->task;
+ up->task = ip->page->file->proc->leader;
up->sm = ip->page->file->proc->sm;
ret = probe_info_register(ip->desc->type, ip);
page_addr >= file->vm_end)
continue;
- mm = page->file->proc->task->mm;
+ mm = page->file->proc->leader->mm;
if (page_present(mm, page_addr))
sspt_register_page(page, file);
}
struct pfg_msg_cb *cb = pfg_msg_cb_get(fl->pfg);
if (cb && cb->msg_term)
- cb->msg_term(fl->proc->task);
+ cb->msg_term(fl->proc->leader);
}
kfree(fl);
spin_lock(&page->ip_list.lock);
if (list_empty(&page->ip_list.not_inst)) {
- struct task_struct *task = page->file->proc->task;
+ struct task_struct *task = page->file->proc->leader;
printk(KERN_INFO "page %lx in %s task[tgid=%u, pid=%u] "
"already installed\n",
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/list.h>
+#include <kprobe/swap_ktd.h>
#include <us_manager/us_slot_manager.h>
static LIST_HEAD(proc_probes_list);
}
-/**
- * @brief Create sspt_proc struct
- *
- * @param task Pointer to the task_struct struct
- * @param priv Private data
- * @return Pointer to the created sspt_proc struct
- */
-struct sspt_proc *sspt_proc_create(struct task_struct *task)
+static void ktd_init(struct task_struct *task, void *data)
+{
+ struct sspt_proc **pproc = (struct sspt_proc **)data;
+
+ *pproc = NULL;
+}
+
+static void ktd_exit(struct task_struct *task, void *data)
+{
+ struct sspt_proc **pproc = (struct sspt_proc **)data;
+
+ WARN_ON(*pproc);
+}
+
+struct ktask_data ktd = {
+ .init = ktd_init,
+ .exit = ktd_exit,
+ .size = sizeof(struct sspt_proc *),
+};
+
+static struct sspt_proc **pproc_by_task(struct task_struct *task)
+{
+ return (struct sspt_proc **)swap_ktd(&ktd, task);
+}
+
+int sspt_proc_init(void)
+{
+ return swap_ktd_reg(&ktd);
+}
+
+void sspt_proc_uninit(void)
+{
+ swap_ktd_unreg(&ktd);
+}
+
+void sspt_change_leader(struct task_struct *prev, struct task_struct *next)
+{
+ struct sspt_proc **prev_pproc;
+
+ prev_pproc = pproc_by_task(prev);
+ if (*prev_pproc) {
+ struct sspt_proc **next_pproc;
+
+ next_pproc = pproc_by_task(next);
+ get_task_struct(next);
+
+ /* Change the keeper sspt_proc */
+ BUG_ON(*next_pproc);
+ *next_pproc = *prev_pproc;
+ *prev_pproc = NULL;
+
+ /* Set new the task leader to sspt_proc */
+ (*next_pproc)->leader = next;
+
+ put_task_struct(prev);
+ }
+}
+
+void sspt_reset_proc(struct task_struct *task)
{
- struct sspt_proc *proc = kzalloc(sizeof(*proc), GFP_ATOMIC);
+ struct sspt_proc **pproc;
+
+ pproc = pproc_by_task(task->group_leader);
+ *pproc = NULL;
+}
+
+
+
+
+
+static struct sspt_proc *sspt_proc_create(struct task_struct *leader)
+{
+ struct sspt_proc *proc = kzalloc(sizeof(*proc), GFP_KERNEL);
if (proc) {
proc->feature = sspt_create_feature();
}
INIT_LIST_HEAD(&proc->list);
- proc->tgid = task->tgid;
- proc->task = task->group_leader;
- proc->sm = create_sm_us(task);
+ 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);
- get_task_struct(proc->task);
+ get_task_struct(proc->leader);
- /* add to list */
- list_add(&proc->list, &proc_probes_list);
+ proc->suspect.after_exec = 1;
+ proc->suspect.after_fork = 0;
}
return proc;
proc->__task = NULL;
}
- put_task_struct(proc->task);
+ put_task_struct(proc->leader);
kfree(proc);
}
}
-struct sspt_proc *sspt_proc_get_by_task(struct task_struct *task)
+struct sspt_proc *sspt_proc_by_task(struct task_struct *task)
{
- struct sspt_proc *proc;
-
- sspt_proc_read_lock();
- proc = sspt_proc_get_by_task_no_lock(task);
- sspt_proc_read_unlock();
-
- return proc;
+ return *pproc_by_task(task->group_leader);
}
-EXPORT_SYMBOL_GPL(sspt_proc_get_by_task);
-
-/**
- * @brief Get sspt_proc by task
- *
- * @param task Pointer on the task_struct struct
- * @return Pointer on the sspt_proc struct
- */
-struct sspt_proc *sspt_proc_get_by_task_no_lock(struct task_struct *task)
-{
- struct sspt_proc *proc, *tmp;
-
- list_for_each_entry_safe(proc, tmp, &proc_probes_list, list) {
- if (proc->tgid == task->tgid)
- return proc;
- }
-
- return NULL;
-}
-EXPORT_SYMBOL_GPL(sspt_proc_get_by_task_no_lock);
+EXPORT_SYMBOL_GPL(sspt_proc_by_task);
/**
* @brief Call func() on each proc (no lock)
*/
struct sspt_proc *sspt_proc_get_by_task_or_new(struct task_struct *task)
{
- struct sspt_proc *proc;
-
- sspt_proc_write_lock();
- proc = sspt_proc_get_by_task_no_lock(task);
- if (proc == NULL)
- proc = sspt_proc_create(task);
- sspt_proc_write_unlock();
+ static DEFINE_MUTEX(local_mutex);
+ struct sspt_proc **pproc;
+ struct task_struct *leader = task->group_leader;
+
+ pproc = pproc_by_task(leader);
+ if (*pproc)
+ goto out;
+
+ /* This lock for synchronizing to create sspt_proc */
+ mutex_lock(&local_mutex);
+ pproc = pproc_by_task(leader);
+ if (*pproc == NULL) {
+ *pproc = sspt_proc_create(leader);
+ if (*pproc) {
+ sspt_proc_write_lock();
+ list_add(&(*pproc)->list, &proc_probes_list);
+ sspt_proc_write_unlock();
+ }
+ }
+ mutex_unlock(&local_mutex);
- return proc;
+out:
+ return *pproc;
}
/**
*/
void sspt_proc_install_page(struct sspt_proc *proc, unsigned long page_addr)
{
- struct mm_struct *mm = proc->task->mm;
+ struct mm_struct *mm = proc->leader->mm;
struct vm_area_struct *vma;
vma = find_vma_intersection(mm, page_addr, page_addr + 1);
void sspt_proc_install(struct sspt_proc *proc)
{
struct vm_area_struct *vma;
- struct mm_struct *mm = proc->task->mm;
+ struct mm_struct *mm = proc->leader->mm;
proc->first_install = 1;
struct list_head file_head; /**< For sspt_file */
pid_t tgid; /**< Thread group ID */
- struct task_struct *task; /**< Ptr to the task */
+ struct task_struct *leader; /**< Ptr to the task leader */
struct mm_struct *__mm;
struct task_struct *__task;
struct slot_manager *sm; /**< Ptr to the manager slot */
struct {
+ unsigned after_exec:1;
+ unsigned after_fork:1;
+ } suspect;
+
+ struct {
struct mutex mtx; /**< Mutex for filter list */
struct list_head head; /**< Filter head */
} filters;
struct list_head *sspt_proc_list(void);
-struct sspt_proc *sspt_proc_create(struct task_struct *task);
void sspt_proc_cleanup(struct sspt_proc *proc);
struct sspt_proc *sspt_proc_get(struct sspt_proc *proc);
void sspt_proc_put(struct sspt_proc *proc);
void *data);
void on_each_proc(void (*func)(struct sspt_proc *, void *), void *data);
-struct sspt_proc *sspt_proc_get_by_task(struct task_struct *task);
-struct sspt_proc *sspt_proc_get_by_task_no_lock(struct task_struct *task);
+struct sspt_proc *sspt_proc_by_task(struct task_struct *task);
struct sspt_proc *sspt_proc_get_by_task_or_new(struct task_struct *task);
void sspt_proc_free_all(void);
void sspt_proc_priv_create(struct sspt_proc *proc);
void sspt_proc_priv_destroy(struct sspt_proc *proc);
+void sspt_reset_proc(struct task_struct *task);
+void sspt_change_leader(struct task_struct *prev, struct task_struct *next);
+int sspt_proc_init(void);
+void sspt_proc_uninit(void);
+
+
#endif /* __SSPT_PROC__ */
struct sspt_proc *proc;
/* FIXME: add read lock (deadlock in sampler) */
- proc = sspt_proc_get_by_task_no_lock(task);
+ proc = sspt_proc_by_task(task);
if (proc)
return sspt_proc_is_send_event(proc);
{
int ret;
- ret = pin_init();
+ ret = sspt_proc_init();
if (ret)
return ret;
+ ret = pin_init();
+ if (ret)
+ goto uninit_proc;
+
ret = init_us_filter();
if (ret)
- pin_exit();
+ goto uninit_pin;
+
+ return 0;
+
+uninit_pin:
+ pin_exit();
+uninit_proc:
+ sspt_proc_uninit();
return ret;
}
exit_us_filter();
pin_exit();
+ sspt_proc_uninit();
}
SWAP_LIGHT_INIT_MODULE(usm_once, init_us_manager, exit_us_manager,