[IMPROVE] Parser: implement system-wide instrumentation
[kernel/swap-modules.git] / parser / us_inst.c
1 /*
2  *  SWAP Parser
3  *  modules/parser/us_inst.c
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18  *
19  * Copyright (C) Samsung Electronics, 2013
20  *
21  * 2013  Vyacheslav Cherkashin: SWAP Parser implement
22  *
23  */
24
25
26 #include <linux/module.h>
27 #include <linux/version.h>
28 #include <linux/errno.h>
29 #include <linux/namei.h>
30 #include <us_manager/pf/pf_group.h>
31 #include "msg_parser.h"
32 #include "us_inst.h"
33
34 /* FIXME: create get_dentry() and put_dentry() */
35 static struct dentry *dentry_by_path(const char *path)
36 {
37         struct dentry *dentry;
38 #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 38)
39         struct path st_path;
40         if (kern_path(path, LOOKUP_FOLLOW, &st_path) != 0) {
41 #else /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 38) */
42         struct nameidata nd;
43         if (path_lookup(path, LOOKUP_FOLLOW, &nd) != 0) {
44 #endif /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 38) */
45                 printk("failed to lookup dentry for path %s!\n", path);
46                 return NULL;
47         }
48
49 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)
50         dentry = nd.dentry;
51         path_release(&nd);
52 #elif LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 38)
53         dentry = nd.path.dentry;
54         path_put(&nd.path);
55 #else /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 38) */
56         dentry = st_path.dentry;
57         path_put(&st_path);
58 #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25) */
59         return dentry;
60 }
61
62
63 static int mod_func_inst(struct func_inst_data *func, struct pf_group *pfg,
64                          struct dentry *dentry, enum MOD_TYPE mt)
65 {
66         int ret;
67
68         switch (mt) {
69         case MT_ADD:
70                 ret = pf_register_probe(pfg, dentry, func->addr, func->args,
71                                         func->ret_type);
72                 break;
73         case MT_DEL:
74                 ret = pf_unregister_probe(pfg, dentry, func->addr);
75                 break;
76         default:
77                 printk("ERROR: mod_type=0x%x\n", mt);
78                 ret = -EINVAL;
79         }
80
81         return ret;
82 }
83
84 static int mod_lib_inst(struct lib_inst_data *lib, struct pf_group *pfg,
85                         enum MOD_TYPE mt)
86 {
87         int ret = 0, i;
88         struct dentry *dentry;
89
90         dentry = dentry_by_path(lib->path);
91         if (dentry == NULL) {
92                 printk("Cannot get dentry by path %s\n", lib->path);
93                 return -EINVAL;
94         }
95
96         for (i = 0; i < lib->cnt_func; ++i) {
97                 ret = mod_func_inst(lib->func[i], pfg, dentry, mt);
98                 if (ret) {
99                         printk("Cannot mod func inst, ret = %d\n", ret);
100                         return ret;
101                 }
102         }
103
104         return ret;
105 }
106
107 static int get_pfg_by_app_info(struct app_info_data *app_info, struct pf_group **pfg)
108 {
109         struct dentry *dentry;
110
111         dentry = dentry_by_path(app_info->exec_path);
112         if (dentry == NULL)
113                 return -EINVAL;
114
115         switch (app_info->app_type) {
116         case AT_PID:
117                 if (app_info->tgid == 0) {
118                         if (app_info->exec_path[0] == '\0')
119                                 *pfg = get_pf_group_dumb(dentry);
120                         else
121                                 goto pf_dentry;
122                 } else
123                         *pfg = get_pf_group_by_tgid(app_info->tgid, dentry);
124                 break;
125         case AT_TIZEN_NATIVE_APP:
126         case AT_TIZEN_WEB_APP:
127         case AT_COMMON_EXEC:
128  pf_dentry:
129                 *pfg = get_pf_group_by_dentry(dentry, dentry);
130                 break;
131         default:
132                 printk("ERROR: app_type=0x%x\n", app_info->app_type);
133                 return -EINVAL;
134         }
135
136         return 0;
137 }
138
139 static int mod_us_app_inst(struct app_inst_data *app_inst, enum MOD_TYPE mt)
140 {
141         int ret, i;
142         struct pf_group *pfg;
143         struct dentry *dentry;
144
145         ret = get_pfg_by_app_info(app_inst->app_info, &pfg);
146         if (ret) {
147                 printk("Cannot get pfg by app info, ret = %d\n", ret);
148                 return ret;
149         }
150
151         for (i = 0; i < app_inst->cnt_func; ++i) {
152                 /* TODO: */
153                 dentry = dentry_by_path(app_inst->app_info->exec_path);
154                 if (dentry == NULL) {
155                         printk("Cannot find dentry by path %s\n",
156                                app_inst->app_info->exec_path);
157                         return -EINVAL;
158                 }
159
160                 ret = mod_func_inst(app_inst->func[i], pfg, dentry, mt);
161                 if (ret) {
162                         printk("Cannot mod func inst, ret = %d\n", ret);
163                         return ret;
164                 }
165         }
166
167         for (i = 0; i < app_inst->cnt_lib; ++i) {
168                 ret = mod_lib_inst(app_inst->lib[i], pfg, mt);
169                 if (ret) {
170                         printk("Cannot mod lib inst, ret = %d\n", ret);
171                         return ret;
172                 }
173         }
174
175         return 0;
176 }
177
178 int mod_us_inst(struct us_inst_data *us_inst, enum MOD_TYPE mt)
179 {
180         u32 i;
181         int ret;
182
183         for (i = 0; i < us_inst->cnt; ++i) {
184                 ret = mod_us_app_inst(us_inst->app_inst[i], mt);
185                 if (ret) {
186                         printk("Cannot mod us app inst, ret = %d\n", ret);
187                         return ret;
188                 }
189         }
190
191         return 0;
192 }