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