struct l_probe_el {
struct list_head list;
+
struct pf_group *pfg;
enum task_id_t task_id;
union {
struct dentry *dentry;
char *id;
};
+
+ struct probe_new p_fixup;
+ struct probe_new p_reloc;
+ struct probe_new p_init;
};
struct bin_data_t {
static int _register_probe_el_no_lock(struct l_probe_el *l_probe)
{
- struct probe_new p_fixup;
- struct probe_new p_reloc;
- struct probe_new p_init;
int ret;
- p_fixup.desc = &pin_fixup;
- p_fixup.offset = _linker_fixup.off;
-
- ret = pin_register(&p_fixup, l_probe->pfg, _linker_fixup.dentry);
+ /* register 'fix_up' */
+ l_probe->p_fixup.desc = &pin_fixup;
+ l_probe->p_fixup.offset = _linker_fixup.off;
+ ret = pin_register(&l_probe->p_fixup, l_probe->pfg,
+ _linker_fixup.dentry);
if (ret != 0) {
printk(GT_PREFIX "Error register linker fixup probe. "
"Linker dentry %s, "
"dl_fixup() offset = 0x%lx\n",
_linker_fixup.dentry->d_name.name,
_linker_fixup.off);
-
return ret;
}
- p_reloc.desc = &pin_reloc;
- p_reloc.offset = _linker_reloc.off;
-
- ret = pin_register(&p_reloc, l_probe->pfg, _linker_reloc.dentry);
+ /* register 'reloc' */
+ l_probe->p_reloc.desc = &pin_reloc;
+ l_probe->p_reloc.offset = _linker_reloc.off;
+ ret = pin_register(&l_probe->p_reloc, l_probe->pfg,
+ _linker_reloc.dentry);
if (ret != 0) {
printk(GT_PREFIX "Error register linker reloc probe. "
"Linker dentry %s, "
goto reg_probe_el_fail;
}
- p_init.desc = &pin_pinit;
- p_init.offset = _pthread_init.off;
-
- ret = pin_register(&p_init, l_probe->pfg, _pthread_init.dentry);
+ /* register 'init' */
+ l_probe->p_init.desc = &pin_pinit;
+ l_probe->p_init.offset = _pthread_init.off;
+ ret = pin_register(&l_probe->p_init, l_probe->pfg,
+ _pthread_init.dentry);
if (ret != 0) {
printk(GT_PREFIX "Error register pthread minimal init. "
"Pthread dentry %s, "
return 0;
reg_probe_pthread_fail:
- pin_unregister(&p_reloc, l_probe->pfg, _linker_reloc.dentry);
+ pin_unregister(&l_probe->p_reloc, l_probe->pfg);
reg_probe_el_fail:
- pin_unregister(&p_fixup, l_probe->pfg, _linker_fixup.dentry);
+ pin_unregister(&l_probe->p_fixup, l_probe->pfg);
return ret;
}
static int _unregister_probe_el_no_lock(struct l_probe_el *l_probe)
{
- struct probe_new p_fixup;
- struct probe_new p_reloc;
- struct probe_new p_init;
- int ret;
-
- p_init.desc = &pin_pinit;
- p_init.offset = _pthread_init.off;
-
- ret = pin_unregister(&p_init, l_probe->pfg, _pthread_init.dentry);
- if (ret != 0) {
- printk(GT_PREFIX "Error unregister pthread minimal init. "
- "Pthread dentry %s, "
- "__pthread_minimal_init() offset = 0x%lx\n",
- _pthread_init.dentry->d_name.name,
- _pthread_init.off);
- return ret;
- }
-
- p_reloc.desc = &pin_reloc;
- p_reloc.offset = _linker_reloc.off;
-
- ret = pin_unregister(&p_reloc, l_probe->pfg, _linker_reloc.dentry);
- if (ret != 0) {
- printk(GT_PREFIX "Error unregister linker reloc probe. "
- "Linker dentry %s, "
- "dl_fixup() offset = 0x%lx\n",
- _linker_reloc.dentry->d_name.name,
- _linker_reloc.off);
- return ret;
- }
-
- p_fixup.desc = &pin_fixup;
- p_fixup.offset = _linker_fixup.off;
-
- ret = pin_unregister(&p_fixup, l_probe->pfg, _linker_fixup.dentry);
- if (ret != 0) {
- printk(GT_PREFIX "Error unregister linker fixup probe. "
- "Linker dentry %s, "
- "dl_fixup() offset = 0x%lx\n",
- _linker_fixup.dentry->d_name.name,
- _linker_fixup.off);
- return ret;
- }
+ pin_unregister(&l_probe->p_init, l_probe->pfg);
+ pin_unregister(&l_probe->p_reloc, l_probe->pfg);
+ pin_unregister(&l_probe->p_fixup, l_probe->pfg);
return 0;
}
return 0;
ur_elm_run:
- pin_unregister(&p_elm_run, pfg, libcapi_dentry);
+ pin_unregister(&p_elm_run, pfg);
ur_ac_init:
- pin_unregister(&p_ac_init, pfg, libcapi_dentry);
+ pin_unregister(&p_ac_init, pfg);
ur_ac_efl_main:
- pin_unregister(&p_ac_efl_main, pfg, libappcore_dentry);
+ pin_unregister(&p_ac_efl_main, pfg);
ur_main:
- pin_unregister(&data->p_main, pfg, data->app_dentry);
+ pin_unregister(&data->p_main, pfg);
ur_dlopen:
- pin_unregister(&p_dlopen, pfg, lpad_dentry);
+ pin_unregister(&p_dlopen, pfg);
ur_dlsym:
- pin_unregister(&p_dlsym, pfg, lpad_dentry);
+ pin_unregister(&p_dlsym, pfg);
put_g:
put_pf_group(pfg);
return ret;
{
struct pf_group *pfg = data->pfg;
- pin_unregister(&p_do_app, pfg, libappcore_dentry);
- pin_unregister(&p_elm_run, pfg, libcapi_dentry);
- pin_unregister(&p_ac_init, pfg, libcapi_dentry);
- pin_unregister(&p_ac_efl_main, pfg, libappcore_dentry);
- pin_unregister(&data->p_main, pfg, data->app_dentry);
- pin_unregister(&p_dlopen, pfg, lpad_dentry);
- pin_unregister(&p_dlsym, pfg, lpad_dentry);
+ pin_unregister(&p_do_app, pfg);
+ pin_unregister(&p_elm_run, pfg);
+ pin_unregister(&p_ac_init, pfg);
+ pin_unregister(&p_ac_efl_main, pfg);
+ pin_unregister(&data->p_main, pfg);
+ pin_unregister(&p_dlopen, pfg);
+ pin_unregister(&p_dlsym, pfg);
put_pf_group(pfg);
data->pfg = NULL;
#include <us_manager/us_manager.h>
-static LIST_HEAD(app_inst_head);
static int wrt_launcher_port;
static int set_config(struct conf_data *conf)
int msg_start(struct msg_buf *mb)
{
int ret = 0;
- u32 cnt;
struct conf_data conf;
+ LIST_HEAD(app_head);
swap_msg_seq_num_reset();
swap_msg_discard_reset();
- cnt = create_us_inst_data(mb, &app_inst_head);
- if (!cnt)
+ if (!create_us_inst_data(mb, &app_head))
return -EINVAL;
if (!is_end_mb(mb)) {
- print_err("to long message, remained=%u", remained_mb(mb));
- ret = -EINVAL;
- goto free_us_inst;
+ pr_info("To long message, remained=%u", remained_mb(mb));
+ destroy_us_inst_data(&app_head);
+ return -EINVAL;
}
- ret = mod_us_inst(&app_inst_head, MT_ADD);
+ ret = app_list_reg(&app_head);
if (ret) {
- printk(KERN_INFO "Cannot mod us inst, ret = %d\n", ret);
- ret = -EINVAL;
- goto free_us_inst;
+ pr_info("Cannot mod us inst, ret = %d\n", ret);
+ return ret;
}
ret = usm_start();
- if (ret)
- goto free_us_inst;
+ if (ret) {
+ app_list_unreg_all();
+ return ret;
+ }
restore_config(&conf);
set_config(&conf);
- return ret;
-
-free_us_inst:
- destroy_us_inst_data(&app_inst_head);
-
- return ret;
+ return 0;
}
/**
if (ret)
return ret;
- pfg_put_all();
+ app_list_unreg_all();
conf.use_features0 = 0;
conf.use_features1 = 0;
printk(KERN_INFO "discarded messages: %d\n", discarded);
swap_msg_discard_reset();
- destroy_us_inst_data(&app_inst_head);
-
return ret;
}
*/
int msg_swap_inst_add(struct msg_buf *mb)
{
- int ret = 0;
- u32 cnt;
- struct app_inst_data *src, *n;
- struct list_head app_head;
+ LIST_HEAD(app_head);
- INIT_LIST_HEAD(&app_head);
- cnt = create_us_inst_data(mb, &app_head);
- if (!cnt)
+ if (!create_us_inst_data(mb, &app_head))
return -EINVAL;
if (!is_end_mb(mb)) {
- print_err("to long message, remained=%u", remained_mb(mb));
- ret = -EINVAL;
- goto free_us_inst;
- }
-
- list_for_each_entry_safe(src, n, &app_head, list) {
- struct app_inst_data *dst;
-
- dst = app_inst_data_find(&app_inst_head, src);
- if (dst) {
- app_inst_data_splice(dst, src);
- } else {
- list_del(&src->list);
- list_add_tail(&src->list, &app_inst_head);
- }
+ pr_info("To long message, remained=%u", remained_mb(mb));
+ destroy_us_inst_data(&app_head);
+ return -EINVAL;
}
- ret = mod_us_inst(&app_inst_head, MT_ADD);
-
-free_us_inst:
- destroy_us_inst_data(&app_head);
-
- return ret;
+ return app_list_reg(&app_head);
}
/**
*/
int msg_swap_inst_remove(struct msg_buf *mb)
{
- int ret = 0;
- u32 cnt;
- struct list_head app_head;
- struct app_inst_data *src, *n;
+ LIST_HEAD(app_head);
INIT_LIST_HEAD(&app_head);
- cnt = create_us_inst_data(mb, &app_head);
- if (!cnt)
+ if (!create_us_inst_data(mb, &app_head))
return -EINVAL;
if (!is_end_mb(mb)) {
- print_err("to long message, remained=%u", remained_mb(mb));
- ret = -EINVAL;
- goto free_us_inst;
- }
-
- list_for_each_entry_safe(src, n, &app_inst_head, list) {
- struct app_inst_data *dst;
-
- dst = app_inst_data_find(&app_head, src);
- if (dst) {
- app_inst_data_move(dst, src);
- if (list_empty(&src->f_head) &&
- list_empty(&src->l_head)) {
- destroy_app_inst_data(src);
- }
- }
+ pr_info("To long message, remained=%u", remained_mb(mb));
+ destroy_us_inst_data(&app_head);
+ return -EINVAL;
}
- ret = mod_us_inst(&app_head, MT_DEL);
-
-free_us_inst:
- destroy_us_inst_data(&app_head);
-
- return ret;
+ return app_list_unreg(&app_head);
}
void set_wrt_launcher_port(int port)
*/
/**
- * @brief Creates and fills app_info_data struct.
+ * @brief Creates and fills pr_app_info struct.
*
* @param mb Pointer to the message buffer.
* @param ai Pointer to the target app_inst_data.
* @return 0 on success, error code on error.
*/
-int create_app_info(struct msg_buf *mb, struct app_inst_data *ai)
+struct pr_app_info *pr_app_info_create(struct msg_buf *mb)
{
int ret;
+ struct pr_app_info *app_info;
u32 app_type;
- char *ta_id, *exec_path;
+ char *str_id, *exec_path;
- print_parse_debug("app_info:\n");
+ app_info = kmalloc(sizeof(*app_info), GFP_KERNEL);
+ if (!app_info)
+ return ERR_PTR(-ENOMEM);
+ print_parse_debug("app_info:\n");
print_parse_debug("type:");
ret = get_u32(mb, &app_type);
if (ret) {
print_err("failed to read target application type\n");
- return -EINVAL;
+ goto free_app_info;
}
print_parse_debug("id:");
- ret = get_string(mb, &ta_id);
+ ret = get_string(mb, &str_id);
if (ret) {
print_err("failed to read target application ID\n");
- return -EINVAL;
+ goto free_app_info;
}
print_parse_debug("exec path:");
ret = get_string(mb, &exec_path);
if (ret) {
print_err("failed to read executable path\n");
- goto free_ta_id;
+ goto free_id;
}
switch (app_type) {
case AT_TIZEN_NATIVE_APP:
case AT_TIZEN_WEB_APP:
case AT_COMMON_EXEC:
- ai->tgid = 0;
+ app_info->tgid = 0;
break;
case AT_PID: {
u32 tgid = 0;
- if (*ta_id != '\0') {
- ret = kstrtou32(ta_id, 10, &tgid);
+ if (*str_id != '\0') {
+ ret = kstrtou32(str_id, 10, &tgid);
if (ret) {
print_err("converting string to PID, "
- "str='%s'\n", ta_id);
+ "str='%s'\n", str_id);
goto free_exec_path;
}
}
- ai->tgid = tgid;
+ app_info->tgid = tgid;
break;
}
default:
goto free_exec_path;
}
- ai->type = (enum APP_TYPE)app_type;
- ai->id = ta_id;
- ai->path = exec_path;
+ app_info->type = (enum APP_TYPE)app_type;
+ app_info->id = str_id;
+ app_info->path = exec_path;
- return 0;
+ return app_info;
free_exec_path:
put_string(exec_path);
+free_id:
+ put_string(str_id);
+free_app_info:
+ kfree(app_info);
+ return ERR_PTR(ret);
+}
-free_ta_id:
- put_string(ta_id);
+void pr_app_info_free(struct pr_app_info *app_info)
+{
+ put_string(app_info->path);
+ put_string(app_info->id);
+ kfree(app_info);
+}
- return -EINVAL;
+int pr_app_info_cmp(struct pr_app_info *app0, struct pr_app_info *app1)
+{
+ print_parse_debug("app0: %d, %d, %s, %s\n",
+ app0->type, app0->tgid, app0->id, app0->path);
+
+ print_parse_debug("app1: %d, %d, %s, %s\n",
+ app1->type, app1->tgid, app1->id, app1->path);
+
+ if ((app0->type == app1->type) &&
+ (app0->tgid == app1->tgid) &&
+ !strcmp(app0->id, app1->id) &&
+ !strcmp(app0->path, app1->path)) {
+ return 0;
+ }
+
+ return 1;
}
}
/**
+ * @brief Retprobe data cleanup.
+ *
+ * @param pi Pointer to the probe_info comprising retprobe.
+ * @return Void.
+ */
+void put_retprobe(struct probe_info *pi)
+{
+ put_string(pi->rp_i.args);
+}
+
+static int cmp_retprobe(struct probe_info *p0, struct probe_info *p1)
+{
+ if (p0->rp_i.ret_type == p1->rp_i.ret_type &&
+ !strcmp(p0->rp_i.args, p1->rp_i.args)) {
+ return 0;
+ }
+
+ return 1;
+}
+
+/**
* @brief Gets webprobe data and puts it to the probe_info struct.
*
* @param mb Pointer to the message buffer.
return 0;
}
-/**
- * @brief Retprobe data cleanup.
- *
- * @param pi Pointer to the probe_info comprising retprobe.
- * @return Void.
- */
-void put_retprobe(struct probe_info *pi)
+static int cmp_webprobe(struct probe_info *p0, struct probe_info *p1)
{
- put_string(pi->rp_i.args);
+ return 0;
}
/**
{
}
+static int cmp_preload_probe(struct probe_info *p0, struct probe_info *p1)
+{
+ if (p0->pl_i.handler == p1->pl_i.handler &&
+ p0->pl_i.flags == p1->pl_i.flags) {
+ return 0;
+ }
+
+ return 1;
+}
+
/**
* @brief Gets preload get_caller and puts it to the probe_info struct.
*
{
}
+static int cmp_get_caller_probe(struct probe_info *p0, struct probe_info *p1)
+{
+ return 0;
+}
+
/**
* @brief Gets preload get_call_type and puts it to the probe_info struct.
*
{
}
+static int cmp_get_caller_type_probe(struct probe_info *p0,
+ struct probe_info *p1)
+{
+ return 0;
+}
+
/**
* @brief Gets preload write_msg and puts it to the probe_info struct.
*
{
}
-
-
+static int cmp_write_msg_probe(struct probe_info *p0, struct probe_info *p1)
+{
+ return 0;
+}
/**
* @brief Gets FBI probe data and puts it to the probe_info struct.
*/
void put_fbi_probe(struct probe_info *pi)
{
+ /* FIXME: memory leak (vars) */
return;
}
+static int cmp_fbi_probe(struct probe_info *p0, struct probe_info *p1)
+{
+ /* TODO: to implement */
+ return 0;
+}
+
/* ============================================================================
- * == FUNC_INST ==
+ * == PROBE ==
* ============================================================================
*/
* @return Pointer to the filled func_inst_data struct on success;\n
* 0 on error.
*/
-struct func_inst_data *create_func_inst_data(struct msg_buf *mb)
+struct pr_probe_desc *pr_probe_desc_create(struct msg_buf *mb)
{
- struct func_inst_data *fi;
- struct probe_desc *pd;
+ int ret = -EINVAL;
+ struct pr_probe_desc *probe;
+ int (*get_probe)(struct msg_buf *mb, struct probe_desc *pd);
u64 addr;
u8 type;
print_parse_debug("func addr:");
if (get_u64(mb, &addr)) {
print_err("failed to read data function address\n");
- return NULL;
+ return ERR_PTR(-EINVAL);
}
print_parse_debug("probe type:");
if (get_u8(mb, &type)) {
print_err("failed to read data probe type\n");
- return NULL;
+ return ERR_PTR(-EINVAL);
}
- fi = kmalloc(sizeof(*fi), GFP_KERNEL);
- if (fi == NULL) {
+ probe = kmalloc(sizeof(*probe), GFP_KERNEL);
+ if (!probe) {
print_err("out of memory\n");
- return NULL;
+ return ERR_PTR(-ENOMEM);
}
- INIT_LIST_HEAD(&fi->list);
- fi->registered = 0;
-
- pd = &fi->p_desc;
+ INIT_LIST_HEAD(&probe->list);
switch (type) {
case SWAP_RETPROBE:
- if (get_retprobe(mb, pd) != 0)
- goto err;
+ get_probe = get_retprobe;
break;
case SWAP_WEBPROBE:
- if (get_webprobe(mb, pd) != 0)
- goto err;
+ get_probe = get_webprobe;
break;
case SWAP_PRELOAD_PROBE:
- if (get_preload_probe(mb, pd) != 0)
- goto err;
+ get_probe = get_preload_probe;
break;
case SWAP_GET_CALLER:
- if (get_get_caller_probe(mb, pd) != 0)
- goto err;
+ get_probe = get_get_caller_probe;
break;
case SWAP_GET_CALL_TYPE:
- if (get_get_call_type_probe(mb, pd) != 0)
- goto err;
+ get_probe = get_get_call_type_probe;
break;
case SWAP_FBIPROBE:
- if (get_fbi_probe(mb, pd) != 0)
- goto err;
+ get_probe = get_fbi_probe;
break;
case SWAP_WRITE_MSG:
- if (get_write_msg_probe(mb, pd) != 0)
- goto err;
+ get_probe = get_write_msg_probe;
break;
default:
printk(KERN_WARNING "SWAP PARSER: Wrong probe type %d!\n",
type);
+ ret = -EINVAL;
goto err;
}
- fi->addr = addr;
- return fi;
-err:
+ ret = get_probe(mb, &probe->p_desc);
+ if (ret)
+ goto err;
+
+ probe->addr = addr;
+ return probe;
- kfree(fi);
- return NULL;
+err:
+ kfree(probe);
+ return ERR_PTR(ret);
}
+
/**
* @brief func_inst_data cleanup.
*
* @param fi Pointer to the target func_inst_data.
* @return Void.
*/
-void destroy_func_inst_data(struct func_inst_data *fi)
+void pr_probe_desc_free(struct pr_probe_desc *probe)
{
- switch (fi->p_desc.type) {
+ switch (probe->p_desc.type) {
case SWAP_RETPROBE:
- put_retprobe(&(fi->p_desc.info));
+ put_retprobe(&(probe->p_desc.info));
break;
case SWAP_WEBPROBE:
break;
case SWAP_PRELOAD_PROBE:
- put_preload_probe(&(fi->p_desc.info));
+ put_preload_probe(&(probe->p_desc.info));
break;
case SWAP_GET_CALLER:
- put_get_caller_probe(&(fi->p_desc.info));
+ put_get_caller_probe(&(probe->p_desc.info));
break;
case SWAP_GET_CALL_TYPE:
- put_get_call_type_probe(&(fi->p_desc.info));
+ put_get_call_type_probe(&(probe->p_desc.info));
break;
case SWAP_FBIPROBE:
- put_fbi_probe(&(fi->p_desc.info));
+ put_fbi_probe(&(probe->p_desc.info));
break;
case SWAP_WRITE_MSG:
- put_write_msg_probe(&(fi->p_desc.info));
+ put_write_msg_probe(&(probe->p_desc.info));
break;
default:
- printk(KERN_WARNING "SWAP PARSER: Wrong probe type %d!\n",
- fi->p_desc.type);
+ pr_err("SWAP PARSER: Wrong probe type %d!\n",
+ probe->p_desc.type);
}
- kfree(fi);
+ kfree(probe);
}
-/**
- * @brief func_inst_data find.
- *
- * @param head Pointer to the list head with func_inst_data.
- * @param func Pointer to the func_inst_data looking for.
- * @return Pointer to the found func_inst_data struct on success;\n
- * NULL on error.
- */
-struct func_inst_data *func_inst_data_find(struct list_head *head,
- struct func_inst_data *func)
+int probe_inst_info_cmp(struct pr_probe_desc *p0, struct pr_probe_desc *p1)
{
- struct func_inst_data *f;
+ enum probe_t type;
+ int (*cmp_probe)(struct probe_info *p0, struct probe_info *p1);
+
+ if (p0->addr != p1->addr &&
+ p0->p_desc.type != p1->p_desc.type)
+ return 1;
- list_for_each_entry(f, head, list) {
- if (func->addr == f->addr)
- return f;
+ type = p0->p_desc.type;
+ switch (type) {
+ case SWAP_RETPROBE:
+ cmp_probe = cmp_retprobe;
+ break;
+ case SWAP_WEBPROBE:
+ cmp_probe = cmp_webprobe;
+ break;
+ case SWAP_PRELOAD_PROBE:
+ cmp_probe = cmp_preload_probe;
+ break;
+ case SWAP_GET_CALLER:
+ cmp_probe = cmp_get_caller_probe;
+ break;
+ case SWAP_GET_CALL_TYPE:
+ cmp_probe = cmp_get_caller_type_probe;
+ break;
+ case SWAP_FBIPROBE:
+ cmp_probe = cmp_fbi_probe;
+ break;
+ case SWAP_WRITE_MSG:
+ cmp_probe = cmp_write_msg_probe;
+ break;
+ default:
+ pr_err("SWAP PARSER: Wrong probe type %d!\n", type);
+ return 1;
}
- return NULL;
+ return cmp_probe(&p0->p_desc.info, &p1->p_desc.info);
}
-/**
- * @brief func_inst_data lists splice
- *
- * @param dst Pointer to the destination list head.
- * @param src Pointer to the source list head.
- * @return u32 count of spliced elements.
- */
-u32 func_inst_data_splice(struct list_head *dst,
- struct list_head *src)
+static struct pr_bin_info *pr_bin_info_create(const char *path)
{
- struct func_inst_data *f, *n, *s;
- u32 cnt = 0;
-
- list_for_each_entry_safe(f, n, src, list) {
- s = func_inst_data_find(dst, f);
- if (s) {
- printk(KERN_WARNING "duplicate func probe\n");
- continue;
- }
+ struct pr_bin_info *info;
- list_del(&f->list);
- list_add_tail(&f->list, dst);
- cnt++;
+ info = kmalloc(sizeof(*info), GFP_KERNEL);
+ if (!info)
+ return ERR_PTR(-ENOMEM);
+
+ info->path = kstrdup(path, GFP_KERNEL);
+ if (!info->path) {
+ kfree(info);
+ return ERR_PTR(-ENOMEM);
}
- return cnt;
+ return info;
}
-/**
- * @brief func_inst_data move from one list to another
- *
- * @param dst Pointer to the destination list head.
- * @param src Pointer to the source list head.
- * @return u32 Counter of moved elements.
- */
-u32 func_inst_data_move(struct list_head *dst,
- struct list_head *src)
+static void pr_bin_info_free(struct pr_bin_info *info)
{
- struct func_inst_data *f, *n, *s;
- u32 cnt = 0;
-
- list_for_each_entry_safe(f, n, src, list) {
- s = func_inst_data_find(dst, f);
- if (s) {
- print_parse_debug("move func 0x%016llX\n", f->addr);
- list_del(&f->list);
- list_del(&s->list);
- destroy_func_inst_data(s);
- list_add_tail(&f->list, dst);
- cnt++;
- }
+ kfree(info->path);
+ kfree(info);
+}
+
+
+struct pr_bin_desc *pr_bin_desc_create(const char *path,
+ struct list_head *probe_list)
+{
+ struct pr_bin_desc *bin;
+
+ bin = kmalloc(sizeof(*bin), GFP_KERNEL);
+ if (!bin)
+ return ERR_PTR(-ENOMEM);
+
+ bin->info = pr_bin_info_create(path);
+ if (IS_ERR(bin->info)) {
+ long err = PTR_ERR(bin->info);
+
+ kfree(bin);
+ return ERR_PTR(err);
}
- return cnt;
+ INIT_LIST_HEAD(&bin->list);
+ INIT_LIST_HEAD(&bin->probe_head);
+ list_splice_init(probe_list, &bin->probe_head);
+
+ return bin;
}
+void pr_bin_desc_free(struct pr_bin_desc *bin)
+{
+ struct pr_probe_desc *p, *n;
+ list_for_each_entry_safe(p, n, &bin->probe_head, list) {
+ list_del(&p->list);
+ pr_probe_desc_free(p);
+ }
-/* ============================================================================
- * == LIB_INST ==
- * ============================================================================
- */
+ pr_bin_info_free(bin->info);
+ kfree(bin);
+}
-/**
- * @brief Creates and fills lib_inst_data struct.
- *
- * @param mb Pointer to the message buffer.
- * @return Pointer to the filled lib_inst_data struct on success;\n
- * 0 on error.
- */
-struct lib_inst_data *create_lib_inst_data(struct msg_buf *mb)
+int pr_bin_info_cmp(struct pr_bin_info *b0, struct pr_bin_info *b1)
+{
+ return strcmp(b0->path, b1->path);
+}
+
+
+static void pr_probe_desc_list_free(struct list_head *head)
+{
+ struct pr_probe_desc *probe, *n;
+
+ list_for_each_entry_safe(probe, n, head, list) {
+ list_del(&probe->list);
+ pr_probe_desc_free(probe);
+ }
+}
+
+static int pr_probe_desc_list_create(struct msg_buf *mb, struct list_head *head)
+{
+ u32 i, cnt;
+
+ if (get_u32(mb, &cnt)) {
+ print_err("failed to read count of functions\n");
+ return -EINVAL;
+ }
+
+ print_parse_debug("probe count:%d", cnt);
+ if (remained_mb(mb) / MIN_SIZE_FUNC_INST < cnt) {
+ print_err("to match count of probes(%u)\n", cnt);
+ return -EINVAL;
+ }
+
+ for (i = 0; i < cnt; ++i) {
+ struct pr_probe_desc *probe;
+
+ print_parse_debug("probe #%d:\n", i + 1);
+ probe = pr_probe_desc_create(mb);
+ if (IS_ERR(probe)) {
+ pr_probe_desc_list_free(head);
+ return PTR_ERR(probe);
+ }
+
+ list_add(&probe->list, head);
+ }
+
+ return cnt;
+}
+
+
+struct pr_bin_desc *bin_info_by_lib(struct msg_buf *mb)
{
- struct lib_inst_data *li;
- struct func_inst_data *fi, *fin;
+ u32 cnt;
char *path;
- u32 cnt, i = 0;
+ struct pr_bin_desc *bin = ERR_PTR(-EINVAL);
print_parse_debug("bin path:");
if (get_string(mb, &path)) {
print_err("failed to read path of binary\n");
- return NULL;
+ return bin;
}
print_parse_debug("func count:");
goto free_path;
}
- li = kmalloc(sizeof(*li), GFP_KERNEL);
- if (li == NULL) {
- print_err("out of memory\n");
- goto free_path;
- }
- INIT_LIST_HEAD(&li->list);
- INIT_LIST_HEAD(&li->f_head);
-
if (cnt) {
+ u32 i;
+ LIST_HEAD(probe_head);
+
for (i = 0; i < cnt; ++i) {
+ struct pr_probe_desc *probe;
print_parse_debug("func #%d:\n", i + 1);
- fi = create_func_inst_data(mb);
- if (fi == NULL)
- goto free_func;
- list_add_tail(&fi->list, &li->f_head);
- }
- }
-
- li->path = path;
- li->cnt_func = cnt;
+ probe = pr_probe_desc_create(mb);
+ if (IS_ERR(probe)) {
+ /* set error to 'bin' */
+ bin = ERR_PTR(PTR_ERR(probe));
+ pr_probe_desc_list_free(&probe_head);
+ goto free_path;
+ }
- return li;
+ list_add(&probe->list, &probe_head);
+ }
-free_func:
- list_for_each_entry_safe(fi, fin, &li->f_head, list) {
- list_del(&fi->list);
- destroy_func_inst_data(fi);
+ bin = pr_bin_desc_create(path, &probe_head);
+ if (IS_ERR(bin))
+ pr_probe_desc_list_free(&probe_head);
}
- kfree(li);
free_path:
put_string(path);
-
- return NULL;
+ return bin;
}
-/**
- * @brief lib_inst_data cleanup.
- *
- * @param li Pointer to the target lib_inst_data.
- * @return Void.
- */
-void destroy_lib_inst_data(struct lib_inst_data *li)
-{
- struct func_inst_data *fi, *fin;
- list_for_each_entry_safe(fi, fin, &li->f_head, list) {
- list_del(&fi->list);
- destroy_func_inst_data(fi);
- }
- put_string(li->path);
- kfree(li);
-}
-/**
- * @brief lib_inst_data find.
- *
- * @param head Pointer to the list head with lib_inst_data.
- * @param lib Pointer to the lib_inst_data looking for.
- * @return Pointer to the found lib_inst_data struct on success;\n
- * NULL on error.
- */
-struct lib_inst_data *lib_inst_data_find(struct list_head *head,
- struct lib_inst_data *lib)
+void bin_info_list_free(struct list_head *head)
{
- struct lib_inst_data *l;
+ struct pr_bin_desc *bin, *n;
- list_for_each_entry(l, head, list) {
- if (!strcmp(l->path, lib->path))
- return l;
+ list_for_each_entry_safe(bin, n, head, list) {
+ list_del(&bin->list);
+ pr_bin_desc_free(bin);
}
-
- return NULL;
}
-/**
- * @brief lib_inst_data lists splice
- *
- * @param dst Pointer to the destination list head.
- * @param src Pointer to the source list head.
- * @return u32 count of spliced elements.
- */
-u32 lib_inst_data_splice(struct list_head *dst, struct list_head *src)
+int bin_info_list_create(struct msg_buf *mb, struct list_head *head)
{
- struct lib_inst_data *l, *n, *s;
- u32 cnt = 0;
-
- list_for_each_entry_safe(l, n, src, list) {
- s = lib_inst_data_find(dst, l);
+ u32 i, cnt;
- if (s) {
- print_parse_debug("update lib %s\n", s->path);
- s->cnt_func += func_inst_data_splice(&s->f_head,
- &l->f_head);
-
- } else {
- print_parse_debug("add new lib %s\n", s->path);
-
- list_del(&l->list);
- list_add_tail(&l->list, dst);
- cnt++;
- }
+ if (get_u32(mb, &cnt)) {
+ print_err("failed to read count of binaries\n");
+ return -EINVAL;
}
+ print_parse_debug("bin count:i%d", cnt);
- return cnt;
-}
+ if (remained_mb(mb) / MIN_SIZE_LIB_INST < cnt) {
+ print_err("to match count of binaries(%u)\n", cnt);
+ return -EINVAL;
+ }
-/**
- * @brief lib_inst_data move from one list to another
- *
- * @param dst Pointer to the destination list head.
- * @param src Pointer to the source list head.
- * @return u32 Counter of moved elements.
- */
-u32 lib_inst_data_move(struct list_head *dst, struct list_head *src)
-{
- struct lib_inst_data *l, *n, *s;
- u32 cnt = 0;
-
- list_for_each_entry_safe(l, n, src, list) {
- s = lib_inst_data_find(dst, l);
-
- if (s) {
- print_parse_debug("update lib %s\n", s->path);
- l->cnt_func -= func_inst_data_move(&s->f_head,
- &l->f_head);
- if (list_empty(&l->f_head)) {
- list_del(&l->list);
- destroy_lib_inst_data(l);
- cnt++;
- }
+ for (i = 0; i < cnt; ++i) {
+ struct pr_bin_desc *bin;
+
+ print_parse_debug("bin #%d:\n", i_lib + 1);
+ bin = bin_info_by_lib(mb);
+ if (IS_ERR(bin)) {
+ bin_info_list_free(head);
+ return PTR_ERR(bin);
+ } else if (bin) {
+ list_add(&bin->list, head);
}
}
/* ============================================================================
- * == APP_INST ==
+ * == APP ==
* ============================================================================
*/
/**
- * @brief Creates and fills app_inst_data struct.
+ * @brief Creates and fills pr_app_desc struct.
*
* @param mb Pointer to the message buffer.
* @return Pointer to the filled app_inst_data struct on success;\n
* 0 on error.
*/
-struct app_inst_data *create_app_inst_data(struct msg_buf *mb)
+struct pr_app_desc *pr_app_desc_create(struct msg_buf *mb)
{
- struct app_inst_data *app_inst;
- struct func_inst_data *func, *func_n;
- struct lib_inst_data *lib, *lib_n;
- u32 cnt_func, i_func = 0, cnt_lib, i_lib = 0;
-
- app_inst = kmalloc(sizeof(*app_inst), GFP_KERNEL);
- if (app_inst == NULL) {
- print_err("out of memory\n");
- return NULL;
+ int cnt_probe, cnt_bin, ret = -EINVAL;
+ struct pr_app_info *app_info;
+ struct pr_app_desc *app;
+ LIST_HEAD(probe_head);
+ LIST_HEAD(bin_head);
+
+ app = kmalloc(sizeof(*app), GFP_KERNEL);
+ if (!app) {
+ print_err("%s: Out of memory\n", __func__);
+ return ERR_PTR(-ENOMEM);
}
- INIT_LIST_HEAD(&app_inst->list);
- INIT_LIST_HEAD(&app_inst->f_head);
- INIT_LIST_HEAD(&app_inst->l_head);
-
- if (create_app_info(mb, app_inst))
- goto err;
-
- if (get_u32(mb, &cnt_func)) {
- print_err("failed to read count of functions\n");
- goto free_app_inst;
- }
- print_parse_debug("func count:%d", cnt_func);
-
- if (remained_mb(mb) / MIN_SIZE_FUNC_INST < cnt_func) {
- print_err("to match count of functions(%u)\n", cnt_func);
+ app_info = pr_app_info_create(mb);
+ if (IS_ERR(app_info)) {
+ ret = PTR_ERR(app_info);
goto free_app_inst;
}
- if (cnt_func) {
- for (i_func = 0; i_func < cnt_func; ++i_func) {
- print_parse_debug("func #%d:\n", i_func + 1);
- func = create_func_inst_data(mb);
- if (func == NULL)
- goto free_func;
- list_add_tail(&func->list, &app_inst->f_head);
+ app->info = app_info;
+ app->pfg = NULL;
+ INIT_LIST_HEAD(&app->list);
+ INIT_LIST_HEAD(&app->bin_head);
+
+ cnt_probe = pr_probe_desc_list_create(mb, &probe_head);
+ if (cnt_probe < 0) {
+ ret = cnt_probe;
+ goto free_app_info;
+ } else if (cnt_probe) {
+ struct pr_bin_desc *bin;
+
+ bin = pr_bin_desc_create(app_info->path, &probe_head);
+ if (IS_ERR(bin)) {
+ pr_probe_desc_list_free(&probe_head);
+ ret = PTR_ERR(bin);
+ goto free_app_info;
}
- }
-
- if (get_u32(mb, &cnt_lib)) {
- print_err("failed to read count of libraries\n");
- goto free_func;
- }
- print_parse_debug("lib count:i%d", cnt_lib);
-
- if (remained_mb(mb) / MIN_SIZE_LIB_INST < cnt_lib) {
- print_err("to match count of libraries(%u)\n", cnt_lib);
- goto free_func;
- }
-
- if (cnt_lib) {
- for (i_lib = 0; i_lib < cnt_lib; ++i_lib) {
- print_parse_debug("lib #%d:\n", i_lib + 1);
- lib = create_lib_inst_data(mb);
- if (lib == NULL)
- goto free_lib;
- list_add_tail(&lib->list, &app_inst->l_head);
- }
+ /* add pr_bin_desc */
+ list_add(&bin->list, &app->bin_head);
}
- app_inst->cnt_func = cnt_func;
- app_inst->cnt_lib = cnt_lib;
-
- return app_inst;
-
-free_lib:
- list_for_each_entry_safe(lib, lib_n, &app_inst->l_head, list) {
- list_del(&lib->list);
- destroy_lib_inst_data(lib);
+ cnt_bin = bin_info_list_create(mb, &app->bin_head);
+ if (cnt_probe < 0) {
+ ret = cnt_bin;
+ goto free_bins;
}
-free_func:
- list_for_each_entry_safe(func, func_n, &app_inst->f_head, list) {
- list_del(&func->list);
- destroy_func_inst_data(func);
- }
+ return app;
+free_bins:
+ bin_info_list_free(&app->bin_head);
+free_app_info:
+ pr_app_info_free(app_info);
free_app_inst:
- put_string(app_inst->path);
- put_string(app_inst->id);
-
-err:
- kfree(app_inst);
-
- return NULL;
+ kfree(app);
+ return ERR_PTR(ret);
}
/**
- * @brief app_inst_data cleanup.
+ * @brief pr_app_desc cleanup.
*
* @param ai Pointer to the target app_inst_data.
* @return Void.
*/
-void destroy_app_inst_data(struct app_inst_data *ai)
+void pr_app_desc_free(struct pr_app_desc *app)
{
- struct func_inst_data *func, *func_n;
- struct lib_inst_data *lib, *lib_n;
-
- list_for_each_entry_safe(lib, lib_n, &ai->l_head, list) {
- list_del(&lib->list);
- destroy_lib_inst_data(lib);
- }
-
- list_for_each_entry_safe(func, func_n, &ai->f_head, list) {
- list_del(&func->list);
- destroy_func_inst_data(func);
- }
-
- put_string(ai->path);
- put_string(ai->id);
-
- kfree(ai);
+ bin_info_list_free(&app->bin_head);
+ pr_app_info_free(app->info);
+ kfree(app);
}
-/**
- * @brief find app_inst_data.
- *
- * @param head Pointer to the list head with app_inst_data.
- * @param ai Pointer to the target app_inst_data.
- * @return Pointer to the target app_inst_data.
- */
-struct app_inst_data *app_inst_data_find(struct list_head *head,
- struct app_inst_data *ai)
-{
- struct app_inst_data *p;
-
- list_for_each_entry(p, head, list) {
-
- print_parse_debug("app1: %d, %d, %s, %s\n",
- p->type, p->tgid, p->id, p->path);
-
- print_parse_debug("app2: %d, %d, %s, %s\n",
- ai->type, ai->tgid, ai->id, ai->path);
-
- if ((p->type == ai->type) &&
- (p->tgid == ai->tgid) &&
- !strcmp(p->id, ai->id) &&
- !strcmp(p->path, ai->path)) {
- return p;
- }
- }
-
- return NULL;
-}
-
-/**
- * @brief app_inst_data splice
- *
- * @param dst Pointer to the destination app_inst_data.
- * @param src Pointer to the source app_inst_data..
- * @return void.
- */
-void app_inst_data_splice(struct app_inst_data *dst,
- struct app_inst_data *src)
-{
- print_parse_debug("find app, splice func and lib to %s\n",
- dst->path);
-
- dst->cnt_func += func_inst_data_splice(&dst->f_head, &src->f_head);
- dst->cnt_lib += lib_inst_data_splice(&dst->l_head, &src->l_head);
-
- return;
-}
-
-/**
- * @brief app_inst_data move from one to another
- *
- * @param dst Pointer to the destination app_inst_data.
- * @param src Pointer to the source app_inst_data.
- * @return void.
- */
-void app_inst_data_move(struct app_inst_data *dst,
- struct app_inst_data *src)
-{
- print_parse_debug("find app, delete func and lib from %s\n",
- dst->path);
-
- dst->cnt_func -= func_inst_data_move(&dst->f_head, &src->f_head);
- dst->cnt_lib -= lib_inst_data_move(&dst->l_head, &src->l_head);
-
- return;
-}
/* ============================================================================
* == US_INST ==
u32 create_us_inst_data(struct msg_buf *mb,
struct list_head *head)
{
- struct app_inst_data *ai, *n;
- u32 cnt, i = 0;
+ u32 cnt, i;
print_parse_debug("us_inst_data:\n");
}
for (i = 0; i < cnt; ++i) {
+ struct pr_app_desc *app;
+
print_parse_debug("app #%d:\n", i + 1);
- ai = create_app_inst_data(mb);
- if (ai == NULL)
+ app = pr_app_desc_create(mb);
+ if (IS_ERR(app))
goto err;
- list_add_tail(&ai->list, head);
+ list_add_tail(&app->list, head);
}
return cnt;
err:
- list_for_each_entry_safe(ai, n, head, list) {
- list_del(&ai->list);
- destroy_app_inst_data(ai);
- }
-
+ destroy_us_inst_data(head);
return 0;
}
*/
void destroy_us_inst_data(struct list_head *head)
{
- struct app_inst_data *ai, *n;
- list_for_each_entry_safe(ai, n, head, list) {
- list_del(&ai->list);
- destroy_app_inst_data(ai);
+ struct pr_app_desc *app, *n;
+
+ list_for_each_entry_safe(app, n, head, list) {
+ list_del(&app->list);
+ pr_app_desc_free(app);
}
}
#include <linux/types.h>
#include <us_manager/probes/probes.h>
+struct img_ip;
struct msg_buf;
/**
};
/**
- * @struct app_info_data
- * @brief Basic application information.
- */
-struct app_info_data {
- enum APP_TYPE app_type; /**< Application type. */
- pid_t tgid; /**< Application PID. */
- char *app_id; /**< Application ID */
- char *exec_path; /**< Application execution path. */
-};
-
-/**
* @struct conf_data
* @brief Configuration struct.
*/
};
/**
- * @struct func_inst_data
- * @brief Application and library functions to set probes.
+ * @brief The pr_app_info struct
*/
-struct func_inst_data {
- struct list_head list;
- u64 addr; /**< Function address. */
- struct probe_desc p_desc; /**< Probe info. */
- int registered;
+struct pr_app_info {
+ enum APP_TYPE type; /**< Application type. */
+ pid_t tgid; /**< Application PID. */
+ char *id; /**< Application ID */
+ char *path; /**< Application execution path. */
+};
+
+/**
+ * @brief The pr_bin_info struct
+ */
+struct pr_bin_info {
+ char *path;
};
/**
- * @struct lib_inst_data
- * @brief Library struct.
+ * @brief The pr_app_desc struct
*/
-struct lib_inst_data {
+struct pr_app_desc {
struct list_head list;
- char *path; /**< Library path. */
- u32 cnt_func; /**< Function probes count in this library. */
- struct list_head f_head; /**< List head of func_inst_data */
+
+ struct pr_app_info *info;
+ struct pf_group *pfg;
+ struct list_head bin_head;
};
/**
- * @struct app_inst_data
- * @brief Application struct.
+ * @brief The pr_bin_desc struct
*/
-struct app_inst_data {
+struct pr_bin_desc {
+ struct list_head list;
+
+ struct pr_bin_info *info;
+
+ struct list_head probe_head;
+};
+
+struct pr_probe_desc {
struct list_head list;
- enum APP_TYPE type; /**< Application type. */
- pid_t tgid; /**< Application PID. */
- char *id; /**< Application ID */
- char *path; /**< Application execution path. */
- struct list_head f_head; /**< List head of func_inst_data */
- struct list_head l_head; /**< List head of lib_inst_data */
- u32 cnt_func; /**< Function probes count in app. */
- u32 cnt_lib; /**< Libs count. */
+
+ /* register info */
+ u64 addr;
+ struct probe_desc p_desc;
+
+ /* unregister info */
+ struct img_ip *ip;
};
-int create_app_info(struct msg_buf *mb, struct app_inst_data *ai);
+
+struct pr_app_info *pr_app_info_create(struct msg_buf *mb);
+void pr_app_info_free(struct pr_app_info *app_info);
+int pr_app_info_cmp(struct pr_app_info *app0, struct pr_app_info *app1);
+
+struct pr_bin_desc *pr_bin_desc_create(const char *path,
+ struct list_head *probe_list);
+void pr_bin_desc_free(struct pr_bin_desc *bin);
+
+int pr_bin_info_cmp(struct pr_bin_info *b0, struct pr_bin_info *b1);
+
+struct pr_probe_desc *pr_probe_desc_create(struct msg_buf *mb);
+void pr_probe_desc_free(struct pr_probe_desc *probe_info);
+int probe_inst_info_cmp(struct pr_probe_desc *p0, struct pr_probe_desc *p1);
struct conf_data *create_conf_data(struct msg_buf *mb);
void destroy_conf_data(struct conf_data *conf);
void save_config(const struct conf_data *conf);
void restore_config(struct conf_data *conf);
-struct func_inst_data *create_func_inst_data(struct msg_buf *mb);
-void destroy_func_inst_data(struct func_inst_data *func_inst);
-
-struct lib_inst_data *create_lib_inst_data(struct msg_buf *mb);
-void destroy_lib_inst_data(struct lib_inst_data *lib_inst);
-
-struct app_inst_data *create_app_inst_data(struct msg_buf *mb);
-void destroy_app_inst_data(struct app_inst_data *app_inst);
-struct app_inst_data *app_inst_data_find(struct list_head *head,
- struct app_inst_data *ai);
-void app_inst_data_move(struct app_inst_data *dst,
- struct app_inst_data *src);
-void app_inst_data_splice(struct app_inst_data *dst,
- struct app_inst_data *src);
+struct pr_app_desc *pr_app_desc_create(struct msg_buf *mb);
+void pr_app_desc_free(struct pr_app_desc *app);
u32 create_us_inst_data(struct msg_buf *mb, struct list_head *head);
void destroy_us_inst_data(struct list_head *head);
-/* empty functions for calculating size fields in structures */
-struct func_inst_data make_func_inst_data(void);
-struct lib_inst_data make_lib_inst_data(void);
-struct app_inst_data make_app_inst_data(void);
-struct us_inst_data make_us_inst_data(void);
-
/**
* @brief Constant defenitions.
*/
enum {
MIN_SIZE_STRING = 1,
- MIN_SIZE_FUNC_INST = sizeof(make_func_inst_data().addr) +
+ MIN_SIZE_FUNC_INST = 8 /* address size */ +
MIN_SIZE_STRING,
MIN_SIZE_LIB_INST = MIN_SIZE_STRING +
- sizeof(make_lib_inst_data().cnt_func),
+ 4 /* lib counter */,
MIN_SIZE_APP_INFO = SIZE_APP_TYPE + MIN_SIZE_STRING + MIN_SIZE_STRING,
MIN_SIZE_APP_INST = MIN_SIZE_APP_INFO +
- sizeof(make_app_inst_data().cnt_func) +
- sizeof(make_app_inst_data().cnt_lib)
+ 4 /* probe counter */ +
+ 4 /* lib counter */,
};
#endif /* _MSG_PARSER_H */
static void unreg_msg_handler(void)
{
set_msg_handler(NULL);
- pfg_put_all();
+ app_list_unreg_all();
}
static int once(void)
#include "usm_msg.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_msg_cb msg_cb = {
.msg_info = usm_msg_info,
.msg_status_info = usm_msg_status_info,
.msg_unmap = usm_msg_unmap
};
-static struct pfg_item *pfg_item_create(struct pf_group *pfg)
-{
- int ret;
- struct pfg_item *item;
-
- ret = pfg_msg_cb_set(pfg, &msg_cb);
- if (ret)
- return ERR_PTR(ret);
- item = kmalloc(sizeof(*item), GFP_KERNEL);
- if (item == NULL)
- return ERR_PTR(-ENOMEM);
-
- INIT_LIST_HEAD(&item->list);
- item->pfg = pfg;
-
- return item;
-}
-
-static void pfg_item_free(struct pfg_item *item)
+static int probe_inst_reg(struct pr_probe_desc *probe, struct pf_group *pfg,
+ struct dentry *dentry)
{
- pfg_msg_cb_reset(item->pfg);
- 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;
- }
+ probe->ip = pf_register_probe(pfg, dentry, probe->addr, &probe->p_desc);
+ if (IS_ERR(probe->ip))
+ return PTR_ERR(probe->ip);
- return false;
+ return 0;
}
-static int pfg_add(struct pf_group *pfg)
+static void probe_inst_unreg(struct pr_probe_desc *probe, 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 (IS_ERR(item))
- return PTR_ERR(item);
-
- spin_lock(&pfg_item_lock);
- list_add(&item->list, &pfg_item_list);
- spin_unlock(&pfg_item_lock);
- }
-
- return 0;
+ pf_unregister_probe(pfg, probe->ip);
}
-void pfg_put_all(void)
+static void do_bin_inst_unreg(struct list_head *head, struct pf_group *pfg)
{
- 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);
+ struct pr_probe_desc *probe;
- list_for_each_entry_safe(item, n, &tmp_list, list) {
- struct pf_group *pfg = item->pfg;
-
- list_del(&item->list);
- pfg_item_free(item);
- put_pf_group(pfg);
+ list_for_each_entry(probe, head, list) {
+ probe_inst_unreg(probe, pfg);
}
}
-static int mod_func_inst(struct func_inst_data *func, struct pf_group *pfg,
- struct dentry *dentry, enum MOD_TYPE mt)
+static void bin_inst_unreg(struct pr_bin_desc *bin, struct pf_group *pfg)
{
- int ret = 0;
-
- switch (mt) {
- case MT_ADD:
- if (func->registered == 0) {
- ret = pf_register_probe(pfg, dentry, func->addr,
- &func->p_desc);
- if (!ret)
- func->registered = 1;
- }
- break;
- case MT_DEL:
- if (func->registered == 1) {
- ret = pf_unregister_probe(pfg, dentry, func->addr,
- &func->p_desc);
- if (!ret)
- func->registered = 0;
- }
- break;
- default:
- printk(KERN_INFO "ERROR: mod_type=0x%x\n", mt);
- ret = -EINVAL;
- }
-
- return ret;
+ do_bin_inst_unreg(&bin->probe_head, pfg);
}
-static int mod_lib_inst(struct lib_inst_data *lib, struct pf_group *pfg,
- enum MOD_TYPE mt)
+static int bin_inst_reg(struct pr_bin_desc *bin, struct pf_group *pfg)
{
- struct func_inst_data *func;
- int ret = 0;
+ struct pr_probe_desc *probe, *n;
struct dentry *dentry;
+ LIST_HEAD(reg_head);
- dentry = dentry_by_path(lib->path);
+ dentry = dentry_by_path(bin->info->path);
if (dentry == NULL) {
- printk(KERN_INFO "Cannot get dentry by path %s\n", lib->path);
+ pr_warn("Cannot get dentry by path %s\n", bin->info->path);
return -EINVAL;
}
- list_for_each_entry(func, &lib->f_head, list) {
- ret = mod_func_inst(func, pfg, dentry, mt);
- if (ret) {
- printk(KERN_INFO "Cannot mod func inst, ret = %d\n",
- ret);
+ list_for_each_entry_safe(probe, n, &bin->probe_head, list) {
+ int ret;
+
+ ret = probe_inst_reg(probe, pfg, dentry);
+ if (!ret) {
+ list_move(&probe->list, ®_head);
+ } else {
+ do_bin_inst_unreg(®_head, pfg);
return ret;
}
}
- return ret;
+ list_splice(®_head, &bin->probe_head);
+ return 0;
}
-static int get_pfg_by_app_info(struct app_inst_data *ai,
- struct pf_group **pfg)
+static struct pf_group *get_pfg_by_app_info(struct pr_app_info *app)
{
+ struct pf_group *pfg = ERR_PTR(-EINVAL);
struct dentry *dentry;
- dentry = dentry_by_path(ai->path);
+ dentry = dentry_by_path(app->path);
if (dentry == NULL)
- return -EINVAL;
+ return pfg;
- switch (ai->type) {
+ switch (app->type) {
case AT_PID:
- if (ai->tgid == 0) {
- if (ai->path[0] == '\0')
- *pfg = get_pf_group_dumb(dentry);
+ if (app->tgid == 0) {
+ if (app->path[0] == '\0')
+ pfg = get_pf_group_dumb(dentry);
else
goto pf_dentry;
- } else
- *pfg = get_pf_group_by_tgid(ai->tgid, dentry);
+ } else {
+ pfg = get_pf_group_by_tgid(app->tgid, dentry);
+ }
break;
case AT_TIZEN_WEB_APP:
- *pfg = get_pf_group_by_comm(ai->id, dentry);
+ pfg = get_pf_group_by_comm(app->id, dentry);
break;
case AT_TIZEN_NATIVE_APP:
case AT_COMMON_EXEC:
pf_dentry:
- *pfg = get_pf_group_by_dentry(dentry, dentry);
+ pfg = get_pf_group_by_dentry(dentry, dentry);
break;
default:
- printk(KERN_INFO "ERROR: app_type=0x%x\n", ai->type);
- return -EINVAL;
+ pr_info("ERROR: app_type=0x%x\n", app->type);
+ break;
}
- return 0;
+ if (!pfg)
+ pfg = ERR_PTR(-ENOMEM);
+
+ if (!IS_ERR(pfg)) {
+ /* TODO: move to other location and chack return value */
+ pfg_msg_cb_set(pfg, &msg_cb);
+ }
+
+ return pfg;
+}
+
+static void do_us_app_inst_unreg(struct pr_app_desc *app,
+ struct list_head *head)
+{
+ struct pr_bin_desc *bin;
+
+ list_for_each_entry(bin, head, list) {
+ bin_inst_unreg(bin, app->pfg);
+ }
+ put_pf_group(app->pfg);
+ app->pfg = NULL;
+}
+
+static void us_app_inst_unreg(struct pr_app_desc *app)
+{
+ do_us_app_inst_unreg(app, &app->bin_head);
}
-static int mod_us_app_inst(struct app_inst_data *app_inst, enum MOD_TYPE mt)
+static int us_app_inst_reg(struct pr_app_desc *app)
{
- int ret;
struct pf_group *pfg;
- struct dentry *dentry;
- struct func_inst_data *func;
- struct lib_inst_data *lib;
+ struct pr_bin_desc *bin, *n;
+ LIST_HEAD(reg_head);
+
+ pfg = get_pfg_by_app_info(app->info);
+ if (IS_ERR(pfg))
+ return PTR_ERR(pfg);
+
+ app->pfg = pfg;
+ list_for_each_entry_safe(bin, n, &app->bin_head, list) {
+ int ret;
+
+ ret = bin_inst_reg(bin, app->pfg);
+ if (!ret) {
+ list_move(&bin->list, ®_head);
+ } else {
+ do_us_app_inst_unreg(app, ®_head);
+ return ret;
+ }
+ }
+
+ list_splice(®_head, &app->bin_head);
+ return 0;
+}
+
+
+static struct pr_probe_desc *find_probe(struct list_head *head,
+ struct pr_probe_desc *probe)
+{
+ struct pr_probe_desc *p;
+
+ list_for_each_entry(p, head, list) {
+ if (!probe_inst_info_cmp(probe, p))
+ return p;
+ }
- ret = get_pfg_by_app_info(app_inst, &pfg);
- if (ret) {
- printk(KERN_INFO "Cannot get pfg by app info, ret = %d\n", ret);
- return ret;
+ return NULL;
+}
+
+static struct pr_bin_desc *find_bin(struct list_head *head,
+ struct pr_bin_info *info)
+{
+ struct pr_bin_desc *bin;
+
+ list_for_each_entry(bin, head, list) {
+ if (!pr_bin_info_cmp(bin->info, info))
+ return bin;
+ }
+
+ return NULL;
+}
+
+static struct pr_app_desc *find_app(struct list_head *head,
+ struct pr_app_info *app_info)
+{
+ struct pr_app_desc *app;
+
+ list_for_each_entry(app, head, list) {
+ if (!pr_app_info_cmp(app->info, app_info))
+ return app;
}
- ret = pfg_add(pfg);
- if (ret) {
- put_pf_group(pfg);
- printk(KERN_INFO "Cannot pfg_add, ret=%d\n", ret);
- return ret;
+ return NULL;
+}
+
+static void us_probe_get_equal_elements(struct list_head *probe_head,
+ struct list_head *test_probe_head,
+ struct list_head *out_probe_head)
+{
+ struct pr_probe_desc *test_probe, *n;
+
+ list_for_each_entry_safe(test_probe, n, test_probe_head, list) {
+ struct pr_probe_desc *probe;
+
+ probe = find_probe(probe_head, test_probe);
+ if (probe) {
+ list_move(&probe->list, out_probe_head);
+
+ /* remove probe */
+ list_del(&test_probe->list);
+ pr_probe_desc_free(test_probe);
+ } else {
+ return;
+ }
}
+}
- list_for_each_entry(func, &app_inst->f_head, list) {
- /* TODO: */
- dentry = dentry_by_path(app_inst->path);
- if (dentry == NULL) {
- printk(KERN_INFO "Cannot find dentry by path %s\n",
- app_inst->path);
- return -EINVAL;
+static void us_bin_get_equal_elements(struct list_head *bin_head,
+ struct list_head *test_bin_head,
+ struct list_head *out_bin_head)
+{
+ struct pr_bin_desc *test_bin, *n;
+
+ list_for_each_entry_safe(test_bin, n, test_bin_head, list) {
+ struct pr_bin_desc *bin;
+ LIST_HEAD(out_probe_head);
+
+ bin = find_bin(bin_head, test_bin->info);
+ if (!bin)
+ return;
+
+ us_probe_get_equal_elements(&bin->probe_head,
+ &test_bin->probe_head,
+ &out_probe_head);
+
+ /* check all probes found */
+ if (list_empty(&test_bin->probe_head)) {
+ list_move(&test_bin->list, out_bin_head);
+ list_splice(&out_probe_head, &test_bin->probe_head);
+ } else {
+ list_splice(&out_probe_head, &bin->probe_head);
}
+ }
+}
- ret = mod_func_inst(func, pfg, dentry, mt);
- if (ret) {
- printk(KERN_INFO "Cannot mod func inst, ret = %d\n",
- ret);
- return ret;
+static void us_app_get_equal_elements(struct list_head *app_head,
+ struct list_head *test_app_head,
+ struct list_head *out_app_head)
+{
+ struct pr_app_desc *test_app, *n;
+
+ list_for_each_entry_safe(test_app, n, test_app_head, list) {
+ struct pr_app_desc *app;
+ LIST_HEAD(out_bin_head);
+
+ app = find_app(app_head, test_app->info);
+ if (!app)
+ return;
+
+ us_bin_get_equal_elements(&app->bin_head,
+ &test_app->bin_head,
+ &out_bin_head);
+
+ /* check all bins found */
+ if (list_empty(&test_app->bin_head)) {
+ list_move(&test_app->list, out_app_head);
+ list_splice(&out_bin_head, &test_app->bin_head);
+ } else {
+ list_splice(&out_bin_head, &app->bin_head);
}
}
+}
- list_for_each_entry(lib, &app_inst->l_head, list) {
- ret = mod_lib_inst(lib, pfg, mt);
- if (ret) {
- printk(KERN_INFO "Cannot mod lib inst, ret = %d\n",
- ret);
- return ret;
+
+static void bin_list_splice(struct list_head *list, struct list_head *head)
+{
+ struct pr_bin_desc *new_bin, *n;
+
+ list_for_each_entry_safe(new_bin, n, list, list) {
+ struct pr_bin_desc *bin;
+
+ bin = find_bin(head, new_bin->info);
+ if (bin) {
+ list_splice_init(&new_bin->probe_head,
+ &bin->probe_head);
+
+ list_del(&new_bin->list);
+ pr_bin_desc_free(new_bin);
+ } else {
+ list_move(&new_bin->list, head);
+ }
+ }
+}
+
+static void app_list_splice(struct list_head *list, struct list_head *head)
+{
+ struct pr_app_desc *new_app, *n;
+
+ list_for_each_entry_safe(new_app, n, list, list) {
+ struct pr_app_desc *app;
+
+ app = find_app(head, new_app->info);
+ if (app) {
+ bin_list_splice(&new_app->bin_head, &app->bin_head);
+
+ list_del(&new_app->list);
+ put_pf_group(app->pfg);
+ pr_app_desc_free(new_app);
+ } else {
+ list_move(&new_app->list, head);
}
}
+}
+
+static void app_list_free(struct list_head *head)
+{
+ struct pr_app_desc *app, *n;
+
+ list_for_each_entry_safe(app, n, head, list) {
+ list_del(&app->list);
+ pr_app_desc_free(app);
+ }
+}
+
+static void do_app_list_unreg(struct list_head *head)
+{
+ struct pr_app_desc *app;
+
+ list_for_each_entry(app, head, list) {
+ us_app_inst_unreg(app);
+ }
+}
+
+
+
+static LIST_HEAD(app_head);
+
+/* After call the 'head' list is empty, do not free it. */
+int app_list_unreg(struct list_head *head)
+{
+ LIST_HEAD(out_app_head);
+
+ us_app_get_equal_elements(&app_head, head, &out_app_head);
+
+ /* check all apps found */
+ if (!list_empty(head)) {
+ app_list_splice(&out_app_head, &app_head);
+ return -EINVAL;
+ }
+ do_app_list_unreg(&out_app_head);
+ app_list_free(&out_app_head);
return 0;
}
-/**
- * @brief Registers probes.
- *
- * @param us_inst Pointer to the target us_inst_data struct.
- * @param mt Modificator, indicates whether we install or remove probes.
- * @return 0 on suceess, error code on error.
- */
-int mod_us_inst(struct list_head *head, enum MOD_TYPE mt)
+/* After call the 'head' list is empty, do not free it. */
+int app_list_reg(struct list_head *head)
{
- int ret;
- struct app_inst_data *ai;
-
- list_for_each_entry(ai, head, list) {
- ret = mod_us_app_inst(ai, mt);
- if (ret) {
- printk(KERN_INFO "Cannot mod us app inst, ret = %d\n",
- ret);
+ LIST_HEAD(reg_head);
+ struct pr_app_desc *app, *n;
+
+ list_for_each_entry_safe(app, n, head, list) {
+ int ret;
+
+ ret = us_app_inst_reg(app);
+ if (!ret) {
+ list_move(&app->list, ®_head);
+ } else {
+ do_app_list_unreg(®_head);
+ list_move(®_head, head);
+ app_list_free(head);
return ret;
}
}
+ app_list_splice(®_head, &app_head);
return 0;
}
+
+void app_list_unreg_all(void)
+{
+ WARN_ON(app_list_unreg(&app_head));
+}
#ifndef _US_INST_H
#define _US_INST_H
-/**
- * @enum MOD_TYPE
- * @brief Type of mod_us_inst behaviour. */
-enum MOD_TYPE {
- MT_ADD, /**< Add probes. */
- MT_DEL /**< Remove probes. */
-};
-
-int mod_us_inst(struct list_head *head, enum MOD_TYPE mt);
-void pfg_put_all(void);
+int app_list_reg(struct list_head *head);
+int app_list_unreg(struct list_head *head);
+void app_list_unreg_all(void);
#endif /* _US_INST_H */
goto out;
}
- ret = pin_unregister(&__ui_data.p_main, __ui_data.pfg,
- __ui_data.app_dentry);
- if (ret)
- goto out;
-
+ pin_unregister(&__ui_data.p_main, __ui_data.pfg);
put_pf_group(__ui_data.pfg);
__ui_data.pfg = NULL;
__ui_data.enable = false;
#include "img_file.h"
#include "img_ip.h"
+#include <linux/err.h>
#include <linux/slab.h>
#include <linux/dcache.h>
+#include <linux/atomic.h>
+
+
+static atomic_t file_counter = ATOMIC_INIT(0);
static void img_del_ip_by_list(struct img_ip *ip);
file = kmalloc(sizeof(*file), GFP_ATOMIC);
if (file == NULL) {
pr_err("%s: failed to allocate memory\n", __func__);
- return NULL;
+ return ERR_PTR(-ENOMEM);
}
+ atomic_inc(&file_counter);
file->dentry = dentry;
INIT_LIST_HEAD(&file->list);
img_ip_put(ip);
}
+ atomic_dec(&file_counter);
kfree(file);
}
{
if (atomic_dec_and_test(&file->use))
img_file_free(file);
-
- return;
}
-/* called with mutex_[lock/unlock](&file->ips.mtx) */
-static struct img_ip *find_img_ip(struct img_file *file, unsigned long addr,
- struct probe_desc *pd)
-{
- struct img_ip *ip;
-
- list_for_each_entry(ip, &file->ips.head, list) {
- if ((ip->addr == addr) &&
- (ip->desc == pd))
- return ip;
- }
-
- return NULL;
-}
/**
* @brief Add instrumentation pointer
* the probe.
* @return Error code
*/
-int img_file_add_ip(struct img_file *file, unsigned long addr,
- struct probe_desc *pd)
+struct img_ip *img_file_add_ip(struct img_file *file, unsigned long addr,
+ struct probe_desc *pd)
{
- int ret = 0;
struct img_ip *ip;
- mutex_lock(&file->ips.mtx);
- ip = find_img_ip(file, addr, pd);
- if (ip) {
- /* ip already exists in img */
- goto unlock;
- }
-
- ip = img_ip_create(addr, pd);
- if (ip == NULL) {
- ret = -ENOMEM;
- goto unlock;
- }
+ ip = img_ip_create(addr, pd, file);
+ if (IS_ERR(ip))
+ return ip;
+ mutex_lock(&file->ips.mtx);
img_add_ip_by_list(file, ip);
-
-unlock:
mutex_unlock(&file->ips.mtx);
- return ret;
+
+ return ip;
}
/**
* @param addr Function address
* @return Error code
*/
-int img_file_del_ip(struct img_file *file, unsigned long addr,
- struct probe_desc *pd)
+void img_file_del_ip(struct img_file *file, struct img_ip *ip)
{
- struct img_ip *ip;
-
mutex_lock(&file->ips.mtx);
- ip = find_img_ip(file, addr, pd);
- if (ip == NULL) {
- printk(KERN_INFO "Warning: no ip found in img, addr = %lx\n",
- addr);
- mutex_unlock(&file->ips.mtx);
- return -EINVAL;
- }
-
img_del_ip_by_list(ip);
mutex_unlock(&file->ips.mtx);
img_ip_clean(ip);
img_ip_put(ip);
-
- return 0;
}
/**
return list_empty(&file->ips.head);
}
+bool img_file_is_unloadable(void)
+{
+ return !(atomic_read(&file_counter) + !img_ip_is_unloadable());
+}
+
/**
* @brief For debug
*
void img_file_get(struct img_file *file);
void img_file_put(struct img_file *file);
-int img_file_add_ip(struct img_file *file, unsigned long addr,
- struct probe_desc *pd);
-int img_file_del_ip(struct img_file *file, unsigned long addr,
- struct probe_desc *pd);
+struct img_ip *img_file_add_ip(struct img_file *file, unsigned long addr,
+ struct probe_desc *pd);
+void img_file_del_ip(struct img_file *file, struct img_ip *ip);
int img_file_empty(struct img_file *file);
+bool img_file_is_unloadable(void);
/* debug */
void img_file_print(struct img_file *file);
#include "img_ip.h"
+#include "img_file.h"
#include <us_manager/probes/use_probes.h>
#include <us_manager/sspt/sspt.h>
#include <us_manager/sspt/sspt_ip.h>
#include <linux/slab.h>
+#include <linux/atomic.h>
+
+
+static atomic_t ip_counter = ATOMIC_INIT(0);
/**
* @brief Create img_ip struct
* @param probe_i Pointer to the probe info data.
* @return Pointer to the created img_ip struct
*/
-struct img_ip *img_ip_create(unsigned long addr, struct probe_desc *pd)
+struct img_ip *img_ip_create(unsigned long addr, struct probe_desc *pd,
+ struct img_file *file)
{
struct img_ip *ip;
ip = kmalloc(sizeof(*ip), GFP_KERNEL);
if (!ip)
- return NULL;
+ return ERR_PTR(-ENOMEM);
+ atomic_inc(&ip_counter);
INIT_LIST_HEAD(&ip->list);
kref_init(&ip->ref);
INIT_LIST_HEAD(&ip->sspt.head);
ip->addr = addr;
ip->desc = pd;
+ ip->file = file;
return ip;
}
struct img_ip *ip = container_of(ref, struct img_ip, ref);
WARN_ON(!list_empty(&ip->sspt.head));
+
+ atomic_dec(&ip_counter);
kfree(ip);
}
mutex_unlock(&ip->sspt.mtx);
}
+bool img_ip_is_unloadable(void)
+{
+ return !atomic_read(&ip_counter);
+}
+
/**
* @brief For debug
*
struct sspt_ip;
+struct img_file;
struct probe_desc;
/**
struct img_ip {
/* img_file */
struct list_head list; /**< List for img_file */
+ struct img_file *file; /**< Pointer on the file (parent) */
struct kref ref;
struct probe_desc *desc; /**< Probe info */
};
-struct img_ip *img_ip_create(unsigned long addr, struct probe_desc *info);
+struct img_ip *img_ip_create(unsigned long addr, struct probe_desc *info,
+ struct img_file *file);
void img_ip_clean(struct img_ip *ip);
void img_ip_get(struct img_ip *ip);
void img_ip_put(struct img_ip *ip);
void img_ip_lock(struct img_ip *ip);
void img_ip_unlock(struct img_ip *ip);
+bool img_ip_is_unloadable(void);
+
/* debug */
void img_ip_print(struct img_ip *ip);
/* debug */
#include <linux/slab.h>
#include <linux/list.h>
#include <linux/mutex.h>
+#include <linux/atomic.h>
#include <us_manager/sspt/sspt_proc.h>
#include <us_manager/sspt/sspt_file.h>
#include "img_ip.h"
};
+static atomic_t proc_counter = ATOMIC_INIT(0);
+
static void img_del_file_by_list(struct img_file *file);
/**
proc = kmalloc(sizeof(*proc), GFP_ATOMIC);
if (proc) {
+ atomic_inc(&proc_counter);
INIT_LIST_HEAD(&proc->files.head);
mutex_init(&proc->files.mtx);
}
}
mutex_unlock(&proc->files.mtx);
+ atomic_dec(&proc_counter);
kfree(proc);
}
* @param probe_i Pointer to a probe_info struct related with the probe
* @return Error code
*/
-int img_proc_add_ip(struct img_proc *proc, struct dentry *dentry,
- unsigned long addr, struct probe_desc *pd)
+struct img_ip *img_proc_add_ip(struct img_proc *proc, struct dentry *dentry,
+ unsigned long addr, struct probe_desc *pd)
{
- int ret;
struct img_file *file;
mutex_lock(&proc->files.mtx);
file = img_file_find(proc, dentry);
-
if (!file) {
file = img_file_create(dentry);
- if (!file) {
+ if (IS_ERR(file)) {
mutex_unlock(&proc->files.mtx);
- return -ENOMEM;
+
+ /* handle type cast */
+ return ERR_PTR(PTR_ERR(file));
}
img_add_file_by_list(proc, file);
}
mutex_unlock(&proc->files.mtx);
- ret = img_file_add_ip(file, addr, pd);
- if (ret)
- printk(KERN_INFO "Cannot add ip to img file\n");
-
- return ret;
+ return img_file_add_ip(file, addr, pd);
}
/**
* @param args Function address
* @return Error code
*/
-int img_proc_del_ip(struct img_proc *proc,
- struct dentry *dentry,
- unsigned long addr,
- struct probe_desc *pd)
+void img_proc_del_ip(struct img_proc *proc, struct img_ip *ip)
{
- int ret = -EINVAL;
- struct img_file *file;
+ struct img_file *file = ip->file;
mutex_lock(&proc->files.mtx);
- file = img_file_find(proc, dentry);
- if (file) {
- ret = img_file_del_ip(file, addr, pd);
- if (img_file_empty(file)) {
- img_del_file_by_list(file);
- img_file_put(file);
- }
+ img_file_del_ip(file, ip);
+ if (img_file_empty(file)) {
+ img_del_file_by_list(file);
+ img_file_put(file);
}
mutex_unlock(&proc->files.mtx);
-
- return ret;
}
void img_proc_copy_to_sspt(struct img_proc *i_proc, struct sspt_proc *proc)
mutex_unlock(&i_proc->files.mtx);
}
+bool img_proc_is_unloadable(void)
+{
+ return !(atomic_read(&proc_counter) + !img_file_is_unloadable());
+}
+
/**
* @brief For debug
*
struct img_proc *img_proc_create(void);
void img_proc_free(struct img_proc *proc);
-int img_proc_add_ip(struct img_proc *proc, struct dentry *dentry,
- unsigned long addr, struct probe_desc *pd);
-int img_proc_del_ip(struct img_proc *proc, struct dentry *dentry,
- unsigned long addri, struct probe_desc *pd);
+struct img_ip *img_proc_add_ip(struct img_proc *proc, struct dentry *dentry,
+ unsigned long addr, struct probe_desc *pd);
+void img_proc_del_ip(struct img_proc *proc, struct img_ip *ip);
void img_proc_copy_to_sspt(struct img_proc *i_proc, struct sspt_proc *proc);
+bool img_proc_is_unloadable(void);
/* debug */
void img_proc_print(struct img_proc *proc);
#include <linux/list.h>
#include <linux/namei.h>
#include <linux/mman.h>
+#include <linux/atomic.h>
#include <linux/spinlock.h>
#include "pf_group.h"
#include "proc_filters.h"
};
+static atomic_t pfg_counter = ATOMIC_INIT(0);
+
static LIST_HEAD(pfg_list);
static DECLARE_RWSEM(pfg_list_sem);
pfg->msg_cb = NULL;
atomic_set(&pfg->usage, 1);
+ atomic_inc(&pfg_counter);
return pfg;
create_pfg_fail:
free_pl_struct(pl);
}
+ atomic_dec(&pfg_counter);
kfree(pfg);
}
+bool pfg_is_unloadable(void)
+{
+ return !(atomic_read(&pfg_counter) + !img_proc_is_unloadable());
+}
+
static int pfg_add_proc(struct pf_group *pfg, struct sspt_proc *proc)
{
struct pl_struct *pls;
* @param dentry Dentry of file
* @param offset Function offset
* @param probe_info Pointer to the related probe_info struct
- * @return Error code
+ * @return pointer to the img_ip struct or error
*/
-int pf_register_probe(struct pf_group *pfg, struct dentry *dentry,
- unsigned long offset, struct probe_desc *pd)
+struct img_ip *pf_register_probe(struct pf_group *pfg, struct dentry *dentry,
+ unsigned long offset, struct probe_desc *pd)
{
return img_proc_add_ip(pfg->i_proc, dentry, offset, pd);
}
* @brief Unregister prober from pf_grpup struct
*
* @param pfg Pointer to the pf_group struct
- * @param dentry Dentry of file
- * @param offset Function offset
- * @return Error code
+ * @param ip Pointer to the img_ip struct
+ * @return Void
*/
-int pf_unregister_probe(struct pf_group *pfg, struct dentry *dentry,
- unsigned long offset, struct probe_desc *pd)
+void pf_unregister_probe(struct pf_group *pfg, struct img_ip *ip)
{
- return img_proc_del_ip(pfg->i_proc, dentry, offset, pd);
+ WARN(IS_ERR_OR_NULL(ip), "invalid img_ip");
+ img_proc_del_ip(pfg->i_proc, ip);
}
EXPORT_SYMBOL_GPL(pf_unregister_probe);
#include <linux/types.h>
+struct img_ip;
struct dentry;
struct pf_group;
struct sspt_proc;
struct pf_group *get_pf_group_by_comm(char *comm, void *priv);
struct pf_group *get_pf_group_dumb(void *priv);
void put_pf_group(struct pf_group *pfg);
+bool pfg_is_unloadable(void);
int pfg_msg_cb_set(struct pf_group *pfg, struct pfg_msg_cb *msg_cb);
void pfg_msg_cb_reset(struct pf_group *pfg);
struct pfg_msg_cb *pfg_msg_cb_get(struct pf_group *pfg);
-int pf_register_probe(struct pf_group *pfg, struct dentry *dentry,
- unsigned long offset, struct probe_desc *pd);
-int pf_unregister_probe(struct pf_group *pfg, struct dentry *dentry,
- unsigned long offset, struct probe_desc *pd);
+struct img_ip *pf_register_probe(struct pf_group *pfg, struct dentry *dentry,
+ unsigned long offset, struct probe_desc *pd);
+void pf_unregister_probe(struct pf_group *pfg, struct img_ip *ip);
void install_all(void);
void uninstall_all(void);
int pin_register(struct probe_new *probe, struct pf_group *pfg,
struct dentry *dentry)
{
- int ret;
- ret = pf_register_probe(pfg, dentry, probe->offset, probe->desc);
- if (ret) {
- printk(KERN_ERR "%s: register probe failed (%d)\n",
- __FUNCTION__, ret);
- return ret;
+ struct img_ip *ip;
+
+ ip = pf_register_probe(pfg, dentry, probe->offset, probe->desc);
+ if (IS_ERR(ip)) {
+ pr_err("%s: register probe failed\n", __func__);
+ return PTR_ERR(ip);
}
+ probe->priv = ip;
return 0;
}
EXPORT_SYMBOL_GPL(pin_register);
-int pin_unregister(struct probe_new *probe, struct pf_group *pfg,
- struct dentry *dentry)
+void pin_unregister(struct probe_new *probe, struct pf_group *pfg)
{
- int ret;
+ struct img_ip *ip = probe->priv;
- ret = pf_unregister_probe(pfg, dentry, probe->offset, probe->desc);
- if (ret) {
- printk(KERN_ERR "%s: unregister probe failed (%d)\n",
- __FUNCTION__, ret);
- return ret;
- }
-
- return 0;
+ pf_unregister_probe(pfg, ip);
}
EXPORT_SYMBOL_GPL(pin_unregister);
};
struct probe_new {
+ /* reg data */
unsigned long offset;
struct probe_desc *desc;
+
+ /* unreg data */
+ void *priv;
};
int pin_register(struct probe_new *probe, struct pf_group *pfg,
struct dentry *dentry);
-int pin_unregister(struct probe_new *probe, struct pf_group *pfg,
- struct dentry *dentry);
+void pin_unregister(struct probe_new *probe, struct pf_group *pfg);
int pin_init(void);
exit_us_filter();
pin_exit();
sspt_proc_uninit();
+
+ WARN_ON(!pfg_is_unloadable());
}
SWAP_LIGHT_INIT_MODULE(usm_once, init_us_manager, exit_us_manager,
struct pf_group *pfg;
u64 inspserver_addr;
u64 tick_addr;
+
+ struct probe_new inspserver_probe;
+ struct probe_new tick_probe;
+
bool enable;
};
/* function tick handler */
static int tick_handler(struct uprobe *p, struct pt_regs *regs);
static struct probe_desc pin_tick_handler = MAKE_UPROBE(tick_handler);
-static struct probe_new tick_probe = {
- .desc = &pin_tick_handler
-};
/* function inspector port */
static int insport_rhandler(struct uretprobe_instance *ri,
struct pt_regs *regs);
static struct probe_desc pin_insport_rhandler =
MAKE_URPROBE(NULL, insport_rhandler, 0);
-static struct probe_new insport_probe = {
- .desc = &pin_insport_rhandler
-};
static int insport_rhandler(struct uretprobe_instance *ri,
struct pt_regs *regs)
static void __web_prof_disable(struct web_prof_data *data)
{
- pin_unregister(&tick_probe, data->pfg, data->lib_dentry);
- pin_unregister(&insport_probe, data->pfg, data->lib_dentry);
+ pin_unregister(&data->tick_probe, data->pfg);
+ pin_unregister(&data->inspserver_probe, data->pfg);
}
static int __web_prof_enable(struct web_prof_data *data)
{
int ret;
- tick_probe.offset = data->tick_addr;
- ret = pin_register(&tick_probe, data->pfg, data->lib_dentry);
+ data->tick_probe.offset = (unsigned long)data->tick_addr;
+ data->tick_probe.desc = &pin_tick_handler;
+ ret = pin_register(&data->tick_probe, data->pfg, data->lib_dentry);
if (ret)
goto fail0;
- insport_probe.offset = data->inspserver_addr;
- ret = pin_register(&insport_probe, data->pfg, data->lib_dentry);
+ data->inspserver_probe.offset = (unsigned long)data->inspserver_addr;
+ data->inspserver_probe.desc = &pin_insport_rhandler;
+ ret = pin_register(&data->inspserver_probe, data->pfg,
+ data->lib_dentry);
if (ret)
goto fail1;
return 0;
fail1:
- pin_unregister(&tick_probe, data->pfg, data->lib_dentry);
+ pin_unregister(&data->tick_probe, data->pfg);
fail0:
return ret;
}
return true;
}
-static int wsp_probe_register(struct pf_group *pfg, struct dentry *dentry,
- struct wsp_probe *wsp_probe)
-{
- struct probe_new *probe_new = &wsp_probe->probe;
-
- return pin_register(probe_new, pfg, dentry);
-}
-
-static void wsp_probe_unregister(struct pf_group *pfg, struct dentry *dentry,
- struct wsp_probe *wsp_probe)
-{
- struct probe_new *probe_new = &wsp_probe->probe;
-
- pin_unregister(probe_new, pfg, dentry);
-}
-
static int wsp_bin_register(struct pf_group *pfg, struct wsp_bin *bin)
{
int i, ret;
for (i = 0; i < bin->cnt; ++i) {
struct wsp_probe *p = &bin->probe_array[i];
- ret = wsp_probe_register(pfg, dentry, p);
+ ret = pin_register(&p->probe, pfg, dentry);
if (ret) {
pr_err("failed to register WSP probe (%lx:%d)\n",
p->probe.offset, ret);
for (i = 0; i < bin->cnt; ++i) {
struct wsp_probe *p = &bin->probe_array[i];
- wsp_probe_unregister(pfg, dentry, p);
+ pin_unregister(&p->probe, pfg);
}
}