56acc58337d99322a97f2b85b9f88d2449240dfc
[kernel/swap-modules.git] / ks_features / ks_features.c
1 #include <linux/module.h>
2 #include <asm/errno.h>
3 #include <ksyms.h>
4 #include <dbi_kprobes.h>
5 #include "ks_features.h"
6 #include "syscall_list.h"
7 #include "features_data.c"
8
9
10 struct ks_probe {
11         struct jprobe jp;
12         struct kretprobe rp;
13         int counter;
14         char *args;
15 };
16
17 #define CREATE_JP(name)                                         \
18 {                                                               \
19         .entry = NULL,                                          \
20         .pre_entry = NULL                                       \
21 }
22
23 #define CREATE_RP(name)                                         \
24 {                                                               \
25         .entry_handler = NULL,                                  \
26         .handler = NULL                                         \
27 }
28
29 #define X(name, args) #name
30 static const char *const syscall_name[] = {
31         SYSCALL_LIST
32 };
33 #undef X
34
35 enum {
36         syscall_name_cnt = sizeof(syscall_name) / sizeof(char *)
37 };
38
39
40 #define X(name, args__)                                         \
41 {                                                               \
42         .jp = CREATE_JP(name),                                  \
43         .rp = CREATE_RP(name),                                  \
44         .counter = 0,                                           \
45         .args = #args__                                         \
46 }
47
48 static struct ks_probe ksp[] = {
49         SYSCALL_LIST
50 };
51 #undef X
52
53
54 static char *get_sys_name(size_t id)
55 {
56         return syscall_name[id];
57 }
58
59 static int get_counter(size_t id)
60 {
61         return ksp[id].counter;
62 }
63
64 static void inc_counter(size_t id)
65 {
66         ++ksp[id].counter;
67 }
68
69 static void dec_counter(size_t id)
70 {
71         --ksp[id].counter;
72 }
73
74 /* ========================= HEANDLERS ========================= */
75 /* FIXME: */
76 #include <ec_probe.h>
77 #include <picl.h>
78 #include <storage.h>
79
80 DEFINE_PER_CPU(void *, gp_priv_arg) = NULL;
81
82 static unsigned long pre_handler(void *priv_arg, struct pt_regs *regs)
83 {
84         __get_cpu_var(gp_priv_arg) = priv_arg;
85
86         return 0;
87 }
88
89 static void j_handler(unsigned long arg0, unsigned long arg1,
90                       unsigned long arg2, unsigned long arg3,
91                       unsigned long arg4, unsigned long arg5)
92 {
93         struct ks_probe *ksp = (struct ks_probe *)__get_cpu_var(gp_priv_arg);
94
95         pack_event_info(KS_PROBE_ID, RECORD_ENTRY, "psxxxxxx", ksp->jp.kp.addr,
96                         ksp->args,
97                         arg0, arg1, arg2, arg3, arg4, arg5);
98         dbi_jprobe_return();
99 }
100
101 static int ret_handler(struct kretprobe_instance *ri, struct pt_regs *regs, void *priv_arg)
102 {
103         int ret_val;
104         struct ks_probe *ksp = (struct ks_probe *)priv_arg;
105
106         ret_val = regs_return_value(regs);
107         pack_event_info(KS_PROBE_ID, RECORD_RET, "pd", ksp->rp.kp.addr, ret_val);
108
109         return 0;
110 }
111 /* ========================= HEANDLERS ========================= */
112
113
114
115 static int register_syscall(size_t id)
116 {
117         int ret;
118         printk("register_syscall: %s\n", get_sys_name(id));
119
120         if (ksp[id].jp.kp.addr == NULL)
121                 return 0;
122
123         ksp[id].jp.pre_entry = pre_handler;
124         ksp[id].jp.entry = j_handler;
125         ksp[id].jp.priv_arg = &ksp[id];
126
127         ksp[id].rp.handler = ret_handler;
128         ksp[id].rp.priv_arg = &ksp[id];
129
130         ret = dbi_register_jprobe(&ksp[id].jp);
131         if (ret)
132                 return ret;
133
134         ret = dbi_register_kretprobe(&ksp[id].rp);
135         if (ret)
136                 dbi_unregister_jprobe(&ksp[id].jp);
137
138         return ret;
139 }
140
141 static int unregister_syscall(size_t id)
142 {
143         printk("unregister_syscall: %s\n", get_sys_name(id));
144
145         if (ksp[id].jp.kp.addr == NULL)
146                 return 0;
147
148         dbi_unregister_kretprobe(&ksp[id].rp);
149         dbi_unregister_jprobe(&ksp[id].jp);
150
151         return 0;
152 }
153
154 static int install_features(struct feature *f)
155 {
156         size_t i, id;
157
158         for (i = 0; i < f->cnt; ++i) {
159                 id = f->feature_list[i];
160
161                 if (get_counter(id) == 0) {
162                         int ret = register_syscall(id);
163                         if (ret) {
164                                 /* TODO: error */
165                                 return ret;
166                         }
167                 }
168
169                 inc_counter(id);
170         }
171
172         return 0;
173 }
174
175 static int uninstall_features(struct feature *f)
176 {
177         size_t i, id;
178
179         for (i = 0; i < f->cnt; ++i) {
180                 id = f->feature_list[i];
181
182                 if (get_counter(id) == 0) {
183                         /* TODO: error */
184                         return -EINVAL;
185                 }
186
187                 dec_counter(id);
188
189                 if (get_counter(id) == 0) {
190                         int ret = unregister_syscall(id);
191                         if (ret) {
192                                 /* TODO: error */
193                                 return ret;
194                         }
195                 }
196         }
197
198         return 0;
199 }
200
201 static struct feature *get_feature(enum feature_id id)
202 {
203         if (id < 0 || id >= (int)feature_cnt)
204                 return NULL;
205
206         return &features[id];
207 }
208
209 int set_feature(enum feature_id id)
210 {
211         struct feature *f = get_feature(id);
212
213         if (f == NULL)
214                 return -EINVAL;
215
216         return install_features(f);
217 }
218 EXPORT_SYMBOL_GPL(set_feature);
219
220 int unset_feature(enum feature_id id)
221 {
222         struct feature *f = get_feature(id);
223
224         if (f == NULL)
225                 return -EINVAL;
226
227         return uninstall_features(f);
228 }
229 EXPORT_SYMBOL_GPL(unset_feature);
230
231 static int __init init_ks_feature(void)
232 {
233         int i;
234         unsigned long addr, ni_syscall;
235         char *name;
236
237         ni_syscall = swap_ksyms("sys_ni_syscall");
238
239         for (i = 0; i < syscall_name_cnt; ++i) {
240                 name = get_sys_name(i);
241                 addr = swap_ksyms(name);
242                 if (addr == 0) {
243                         printk("%s() not found\n", name);
244                         return -EFAULT;
245                 }
246
247                 if (ni_syscall == addr) {
248                         printk("INFO: %s is not install\n", get_sys_name(i));
249                         addr = 0;
250                 }
251
252                 ksp[i].jp.kp.addr = ksp[i].rp.kp.addr = addr;
253         }
254
255         return 0;
256 }
257
258 static void __exit exit_ks_feature(void)
259 {
260 }
261
262 module_init(init_ks_feature);
263 module_exit(exit_ks_feature);
264
265 MODULE_LICENSE("GPL");
266
267 /* debug */
268 static void print_feature(struct feature *f)
269 {
270         size_t i;
271
272         for (i = 0; i < f->cnt; ++i) {
273                 printk("    feature[%3u]: %s\n", i, get_sys_name(f->feature_list[i]));
274         }
275 }
276
277 void print_features(void)
278 {
279         int i;
280
281         printk("print_features:\n");
282         for (i = 0; i < feature_cnt; ++i) {
283                 printk("feature: %d\n", i);
284                 print_feature(&features[i]);
285         }
286 }
287
288 void print_all_syscall(void)
289 {
290         int i;
291
292         printk("SYSCALL:\n");
293         for (i = 0; i < syscall_name_cnt; ++i) {
294                 printk("    [%2d] %s\n", get_counter(i), get_sys_name(i));
295         }
296 }
297 /* debug */