*/
+#include <linux/slab.h>
#include <linux/module.h>
#include <linux/version.h>
#include <linux/errno.h>
#include "us_inst.h"
+struct pfg_item {
+ struct list_head list;
+ struct pf_group *pfg;
+};
+
+
+static LIST_HEAD(pfg_item_list);
+static DEFINE_SPINLOCK(pfg_item_lock);
+
+
+static struct pfg_item *pfg_item_create(struct pf_group *pfg)
+{
+ struct pfg_item *item;
+
+ item = kmalloc(sizeof(*item), GFP_KERNEL);
+ if (item) {
+ INIT_LIST_HEAD(&item->list);
+ item->pfg = pfg;
+ }
+
+ return item;
+}
+
+static void pfg_item_free(struct pfg_item *item)
+{
+ kfree(item);
+}
+
+/* called with pfg_item_lock held */
+static bool pfg_check(struct pf_group *pfg)
+{
+ struct pfg_item *item;
+
+ list_for_each_entry(item, &pfg_item_list, list) {
+ if (item->pfg == pfg)
+ return true;
+ }
+
+ return false;
+}
+
+static int pfg_add(struct pf_group *pfg)
+{
+ bool already;
+
+ spin_lock(&pfg_item_lock);
+ already = pfg_check(pfg);
+ spin_unlock(&pfg_item_lock);
+
+ if (already) {
+ put_pf_group(pfg);
+ } else {
+ struct pfg_item *item;
+
+ item = pfg_item_create(pfg);
+ if (item == NULL)
+ return -ENOMEM;
+
+ spin_lock(&pfg_item_lock);
+ list_add(&item->list, &pfg_item_list);
+ spin_unlock(&pfg_item_lock);
+ }
+
+ return 0;
+}
+
+void pfg_put_all(void)
+{
+ LIST_HEAD(tmp_list);
+ struct pfg_item *item, *n;
+
+ spin_lock(&pfg_item_lock);
+ list_splice_init(&pfg_item_list, &tmp_list);
+ spin_unlock(&pfg_item_lock);
+
+ list_for_each_entry_safe(item, n, &tmp_list, list) {
+ list_del(&item->list);
+ put_pf_group(item->pfg);
+ pfg_item_free(item);
+ }
+}
+
static int mod_func_inst(struct func_inst_data *func, struct pf_group *pfg,
struct dentry *dentry, enum MOD_TYPE mt)
{
return ret;
}
+ ret = pfg_add(pfg);
+ if (ret) {
+ put_pf_group(pfg);
+ printk(KERN_INFO "Cannot pfg_add, ret=%d\n", ret);
+ return ret;
+ }
+
for (i = 0; i < app_inst->cnt_func; ++i) {
/* TODO: */
dentry = dentry_by_path(app_inst->app_info->exec_path);
struct list_head list;
struct img_proc *i_proc;
struct proc_filter filter;
+ atomic_t usage;
/* TODO: proc_list*/
struct list_head proc_list;
};
static LIST_HEAD(pfg_list);
+static DEFINE_RWLOCK(pfg_list_lock);
/* struct pl_struct */
static struct pl_struct *create_pl_struct(struct sspt_proc *proc)
INIT_LIST_HEAD(&pfg->list);
memset(&pfg->filter, 0, sizeof(pfg->filter));
INIT_LIST_HEAD(&pfg->proc_list);
+ atomic_set(&pfg->usage, 1);
return pfg;
kfree(pfg);
}
+/* called with pfg_list_lock held */
static void add_pfg_by_list(struct pf_group *pfg)
{
list_add(&pfg->list, &pfg_list);
}
+/* called with pfg_list_lock held */
static void del_pfg_by_list(struct pf_group *pfg)
{
list_del(&pfg->list);
{
struct pf_group *pfg;
+ write_lock(&pfg_list_lock);
list_for_each_entry(pfg, &pfg_list, list) {
- if (check_pf_by_dentry(&pfg->filter, dentry))
- return pfg;
+ if (check_pf_by_dentry(&pfg->filter, dentry)) {
+ atomic_inc(&pfg->usage);
+ goto unlock;
+ }
}
pfg = create_pfg();
if (pfg == NULL)
- return NULL;
+ goto unlock;
set_pf_by_dentry(&pfg->filter, dentry, priv);
add_pfg_by_list(pfg);
+unlock:
+ write_unlock(&pfg_list_lock);
return pfg;
}
EXPORT_SYMBOL_GPL(get_pf_group_by_dentry);
{
struct pf_group *pfg;
+ write_lock(&pfg_list_lock);
list_for_each_entry(pfg, &pfg_list, list) {
- if (check_pf_by_tgid(&pfg->filter, tgid))
- return pfg;
+ if (check_pf_by_tgid(&pfg->filter, tgid)) {
+ atomic_inc(&pfg->usage);
+ goto unlock;
+ }
}
pfg = create_pfg();
if (pfg == NULL)
- return NULL;
+ goto unlock;
set_pf_by_tgid(&pfg->filter, tgid, priv);
add_pfg_by_list(pfg);
+unlock:
+ write_unlock(&pfg_list_lock);
return pfg;
}
EXPORT_SYMBOL_GPL(get_pf_group_by_tgid);
int ret;
struct pf_group *pfg;
+ write_lock(&pfg_list_lock);
list_for_each_entry(pfg, &pfg_list, list) {
- if (check_pf_by_comm(&pfg->filter, comm))
- return pfg;
+ if (check_pf_by_comm(&pfg->filter, comm)) {
+ atomic_inc(&pfg->usage);
+ goto unlock;
+ }
}
pfg = create_pfg();
if (pfg == NULL)
- return NULL;
+ goto unlock;
ret = set_pf_by_comm(&pfg->filter, comm, priv);
if (ret) {
printk(KERN_ERR "ERROR: set_pf_by_comm, ret=%d\n", ret);
free_pfg(pfg);
- return NULL;
+ pfg = NULL;
+ goto unlock;
}
add_pfg_by_list(pfg);
-
+unlock:
+ write_unlock(&pfg_list_lock);
return pfg;
}
EXPORT_SYMBOL_GPL(get_pf_group_by_comm);
{
struct pf_group *pfg;
+ write_lock(&pfg_list_lock);
list_for_each_entry(pfg, &pfg_list, list) {
- if (check_pf_dumb(&pfg->filter))
- return pfg;
+ if (check_pf_dumb(&pfg->filter)) {
+ atomic_inc(&pfg->usage);
+ goto unlock;
+ }
}
pfg = create_pfg();
if (pfg == NULL)
- return NULL;
+ goto unlock;
set_pf_dumb(&pfg->filter, priv);
add_pfg_by_list(pfg);
+unlock:
+ write_unlock(&pfg_list_lock);
return pfg;
}
EXPORT_SYMBOL_GPL(get_pf_group_dumb);
*/
void put_pf_group(struct pf_group *pfg)
{
+ if (atomic_dec_and_test(&pfg->usage)) {
+ write_lock(&pfg_list_lock);
+ del_pfg_by_list(pfg);
+ write_unlock(&pfg_list_lock);
+ free_pfg(pfg);
+ }
}
/**
{
struct pf_group *pfg;
+ read_lock(&pfg_list_lock);
list_for_each_entry(pfg, &pfg_list, list) {
if (check_task_f(&pfg->filter, task))
return 1;
}
+ read_unlock(&pfg_list_lock);
return 0;
}
struct pf_group *pfg;
struct sspt_proc *proc = NULL;
+ read_lock(&pfg_list_lock);
list_for_each_entry(pfg, &pfg_list, list) {
if (check_task_f(&pfg->filter, task) == NULL)
continue;
printk(KERN_ERR "SWAP US_MANAGER: Error! Trying"
" to first install filter that "
"already exists in proc!\n");
- return;
+ proc = NULL;
+ goto unlock;
}
break;
}
}
}
+unlock:
+ read_unlock(&pfg_list_lock);
+
if (proc)
first_install(task, proc, pfg);
}
struct pf_group *pfg, *pfg_first = NULL;
struct sspt_proc *proc = NULL;
+ read_lock(&pfg_list_lock);
list_for_each_entry(pfg, &pfg_list, list) {
if ((check_task_f(&pfg->filter, task) == NULL))
continue;
break;
}
}
+ read_unlock(&pfg_list_lock);
if (proc) {
if (pfg_first)
struct pf_group *pfg;
struct pl_struct *pls;
+ read_lock(&pfg_list_lock);
list_for_each_entry(pfg, &pfg_list, list) {
pls = find_pl_struct(pfg, task);
if (pls) {
free_pl_struct(pls);
}
}
+ read_unlock(&pfg_list_lock);
task_lock(task);
BUG_ON(task->mm == NULL);
#endif /* CONFIG_ARM */
}
-static void clean_pfg(void)
-{
- struct pf_group *pfg, *n;
-
- list_for_each_entry_safe(pfg, n, &pfg_list, list) {
- del_pfg_by_list(pfg);
- free_pfg(pfg);
- }
-}
-
static void on_each_uninstall_proc(struct sspt_proc *proc, void *data)
{
uninstall_proc(proc);
sspt_proc_write_lock();
on_each_proc_no_lock(on_each_uninstall_proc, NULL);
sspt_proc_write_unlock();
-
- clean_pfg();
}
/**