Merge branch 'tizen_2.4_dev' into tizen
[kernel/swap-modules.git] / webprobe / webprobe.c
1 /**
2  * webprobe/webprobe.c
3  * @author Ruslan Soloviev
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, 2014
24  *
25  * @section DESCRIPTION
26  *
27  * Web application profiling
28  */
29
30
31 #include <us_manager/us_manager.h>
32 #include <us_manager/sspt/sspt_ip.h>
33 #include <us_manager/probes/register_probes.h>
34 #include <us_manager/sspt/sspt.h>
35 #include <uprobe/swap_uprobes.h>
36 #include <parser/msg_cmd.h>
37 #include <linux/module.h>
38 #include <linux/slab.h>
39 #include <master/swap_initializer.h>
40
41 #include "webprobe_debugfs.h"
42 #include "webprobe_prof.h"
43 #include "web_msg.h"
44
45
46 static unsigned long inspserver_addr_local;
47 static unsigned long willexecute_addr_local;
48 static unsigned long didexecute_addr_local;
49
50 static int webprobe_copy(struct probe_info *dest,
51                          const struct probe_info *source)
52 {
53         memcpy(dest, source, sizeof(*source));
54
55         return 0;
56 }
57
58 static void webprobe_cleanup(struct probe_info *probe_i)
59 {
60 }
61
62 static struct uprobe *webprobe_get_uprobe(struct sspt_ip *ip)
63 {
64         return &ip->retprobe.up;
65 }
66
67 static int webprobe_register_probe(struct sspt_ip *ip)
68 {
69         return swap_register_uretprobe(&ip->retprobe);
70 }
71
72 static void webprobe_unregister_probe(struct sspt_ip *ip, int disarm)
73 {
74         if (ip->orig_addr == inspserver_addr_local)
75                 web_func_inst_remove(INSPSERVER_START);
76         else if (ip->orig_addr == willexecute_addr_local)
77                 web_func_inst_remove(WILL_EXECUTE);
78         else if (ip->orig_addr == didexecute_addr_local)
79                 web_func_inst_remove(DID_EXECUTE);
80
81         __swap_unregister_uretprobe(&ip->retprobe, disarm);
82 }
83
84 static int web_entry_handler(struct uretprobe_instance *ri,
85                              struct pt_regs *regs)
86 {
87         struct uretprobe *rp = ri->rp;
88         struct sspt_ip *ip;
89         unsigned long vaddr, page_vaddr;
90         struct vm_area_struct *vma;
91
92         if (rp == NULL)
93                 return 0;
94
95         ip = container_of(rp, struct sspt_ip, retprobe);
96         vaddr = (unsigned long)ip->orig_addr;
97         page_vaddr = vaddr & PAGE_MASK;
98
99         vma = find_vma_intersection(current->mm, page_vaddr, page_vaddr + 1);
100         if (vma && check_vma(vma)) {
101                 unsigned long addr = vaddr - vma->vm_start;
102                 struct dentry *d = vma->vm_file->f_path.dentry;
103
104                 if (addr == web_prof_addr(WILL_EXECUTE) &&
105                     d == web_prof_lib_dentry()) {
106                         willexecute_addr_local = ip->orig_addr;
107                         web_msg_entry(regs);
108                 } else if (addr == web_prof_addr(DID_EXECUTE) &&
109                            d == web_prof_lib_dentry()) {
110                         didexecute_addr_local = ip->orig_addr;
111                         web_msg_exit(regs);
112                 }
113         }
114
115         return 0;
116 }
117
118
119 static int web_ret_handler(struct uretprobe_instance *ri, struct pt_regs *regs)
120 {
121         struct uretprobe *rp = ri->rp;
122         struct sspt_ip *ip;
123         unsigned long vaddr, page_vaddr;
124         struct vm_area_struct *vma;
125
126         if (rp == NULL)
127                 return 0;
128
129         ip = container_of(rp, struct sspt_ip, retprobe);
130         vaddr = (unsigned long)ip->orig_addr;
131         page_vaddr = vaddr & PAGE_MASK;
132
133         vma = find_vma_intersection(current->mm, page_vaddr, page_vaddr + 1);
134         if (vma && check_vma(vma)) {
135                 unsigned long addr = vaddr - vma->vm_start;
136                 struct dentry *d = vma->vm_file->f_path.dentry;
137
138                 if (addr == web_prof_addr(INSPSERVER_START) &&
139                     d == web_prof_lib_dentry()) {
140                         inspserver_addr_local = ip->orig_addr;
141                         set_wrt_launcher_port((int)regs_return_value(regs));
142                 }
143         }
144
145         return 0;
146 }
147
148 static void webprobe_init(struct sspt_ip *ip)
149 {
150         ip->retprobe.entry_handler = web_entry_handler;
151         ip->retprobe.handler = web_ret_handler;
152         ip->retprobe.maxactive = 0;
153 }
154
155 static void webprobe_uninit(struct sspt_ip *ip)
156 {
157         webprobe_cleanup(&ip->desc->info);
158 }
159
160
161 static struct probe_iface webprobe_iface = {
162         .init = webprobe_init,
163         .uninit = webprobe_uninit,
164         .reg = webprobe_register_probe,
165         .unreg = webprobe_unregister_probe,
166         .get_uprobe = webprobe_get_uprobe,
167         .copy = webprobe_copy,
168         .cleanup = webprobe_cleanup
169 };
170
171 static int webprobe_module_init(void)
172 {
173         int ret = 0;
174
175         ret = swap_register_probe_type(SWAP_WEBPROBE, &webprobe_iface);
176         if (ret)
177                 pr_err("Cannot register probe type SWAP_WEBPROBE\n");
178
179         return ret;
180 }
181
182 static void webprobe_module_exit(void)
183 {
184         swap_unregister_probe_type(SWAP_WEBPROBE);
185 }
186
187 SWAP_LIGHT_INIT_MODULE(NULL, webprobe_module_init, webprobe_module_exit,
188                        webprobe_debugfs_init, webprobe_debugfs_exit);
189
190 MODULE_LICENSE("GPL");
191 MODULE_DESCRIPTION("SWAP webprobe");
192 MODULE_AUTHOR("Ruslan Soloviev <r.soloviev@samsung.com>"
193               "Anastasia Lyupa <a.lyupa@samsung.com>");