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