[FIX] __switch_to for ARM
[kernel/swap-modules.git] / tests / kprobe_tests / kp_tests_module.c
1 /*
2  * This program is free software; you can redistribute it and/or modify
3  * it under the terms of the GNU General Public License as published by
4  * the Free Software Foundation; either version 2 of the License, or
5  * (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software
14  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
15  *
16  * Copyright (C) Samsung Electronics, 2016
17  *
18  * 2016         Vyacheslav Cherkashin <v.cherkashin@samsung.com>
19  *
20  */
21
22
23 #include <linux/slab.h>
24 #include <linux/string.h>
25 #include <linux/delay.h>
26 #include <linux/module.h>
27 #include <linux/kthread.h>
28 #include <ksyms/ksyms.h>
29 #include <kprobe/swap_kprobes.h>
30 #include <master/swap_initializer.h>
31
32
33 static struct task_struct *cur_task;
34
35
36
37 /*
38  ******************************************************************************
39  *                                    log                                     *
40  ******************************************************************************
41  */
42 static long write_to_stdout(const char *buf, size_t len)
43 {
44         static asmlinkage long (*sys_write)(unsigned int, const char __user *, size_t) = NULL;
45         long ret = -ESRCH;
46
47         if (sys_write == NULL)
48                 sys_write = (void *)swap_ksyms("sys_write");
49
50         if (sys_write) {
51                 mm_segment_t fs = get_fs();
52                 set_fs(get_ds());
53                 ret = sys_write(1, buf, len);
54                 set_fs(fs);
55         }
56
57         return ret;
58 }
59
60 static void olog(const char *fmt, ...)
61 {
62         char buf[256];
63         va_list args;
64
65         va_start(args, fmt);
66         vsnprintf(buf, sizeof(buf), fmt, args);
67         va_end(args);
68
69         printk("%s", buf);
70         write_to_stdout(buf, strlen(buf));
71 }
72
73
74
75
76 static struct kprobe *kp_create(char *name,
77                                 int (*pre_h)(struct kprobe *, struct pt_regs *))
78 {
79         struct kprobe *p;
80
81         p = kzalloc(sizeof(*p), GFP_KERNEL);
82         if (p) {
83                 p->symbol_name = name;
84                 p->pre_handler = pre_h;
85         }
86
87         return p;
88 }
89
90 static void kp_free(struct kprobe *p)
91 {
92         memset(p, 0x10, sizeof(*p));
93 }
94
95 #define kp_reg(ptr, name, handler) \
96         do { \
97                 ptr = kp_create(name, handler); \
98                 swap_register_kprobe(ptr); \
99         } while (0)
100
101 #define kp_unreg(ptr) \
102         do { \
103                 swap_unregister_kprobe(ptr); \
104                 kp_free(ptr); \
105                 ptr = NULL; \
106         } while (0)
107
108
109 noinline char *my_kstrdup(const char *s, gfp_t gfp)
110 {
111         return kstrdup(s, gfp);
112 }
113
114 noinline void my_kfree(const void *data)
115 {
116         kfree(data);
117 }
118
119
120
121
122 /*
123  ******************************************************************************
124  *                                 recursion                                  *
125  ******************************************************************************
126  */
127 static int kstrdup_cnt;
128 static int kfree_cnt;
129
130 static struct kprobe *kp_kstrdup;
131 static int kstrdup_h(struct kprobe *kp, struct pt_regs *regs)
132 {
133         char *str;
134
135         str = my_kstrdup("from_kfree_h", GFP_ATOMIC);
136         my_kfree(str);
137
138         ++kstrdup_cnt;
139
140         return 0;
141 }
142
143 static struct kprobe *kp_kfree;
144 static int kfree_h(struct kprobe *kp, struct pt_regs *regs)
145 {
146         ++kfree_cnt;
147
148         return 0;
149 }
150
151 static void run_test_recursion(void)
152 {
153         char *str;
154
155         str = my_kstrdup("test_string_0", GFP_KERNEL);
156         my_kfree(str);
157
158         str = my_kstrdup("test_string_1", GFP_KERNEL);
159         my_kfree(str);
160 }
161
162 static void do_test_recursion(void)
163 {
164         kp_reg(kp_kfree, "my_kfree", kfree_h);
165         kp_reg(kp_kstrdup, "my_kstrdup", kstrdup_h);
166
167         run_test_recursion();
168
169         kp_unreg(kp_kstrdup);
170         kp_unreg(kp_kfree);
171 }
172
173
174 static void test_recursion(void)
175 {
176         olog("Recursion:\n");
177
178         kstrdup_cnt = 0;
179         kfree_cnt = 0;
180
181         do_test_recursion();
182
183         if (kstrdup_cnt == 2 && kfree_cnt == 2) {
184                 olog("    OK\n");
185         } else {
186                 olog("    ERROR: kstrdup_cnt=%d kfree_cnt=%d\n",
187                        kstrdup_cnt, kfree_cnt);
188         }
189 }
190
191
192
193
194 /*
195  ******************************************************************************
196  *            recursion and multiple handlers (Aggregate probe)               *
197  ******************************************************************************
198  */
199 static int kfree2_cnt;
200
201 static struct kprobe *kp_kfree2;
202 static int kfree2_h(struct kprobe *kp, struct pt_regs *regs)
203 {
204         if (current != cur_task || in_interrupt())
205                 return 0;
206
207         ++kfree2_cnt;
208         return 0;
209 }
210
211 static void pre_test_recursion_and_mh(void)
212 {
213         kstrdup_cnt = 0;
214         kfree_cnt = 0;
215         kfree2_cnt = 0;
216 }
217
218 static void post_test_recursion_and_mh(void)
219 {
220         if (kstrdup_cnt == 2 && kfree_cnt == 2 && kfree2_cnt == 2) {
221                 olog("    OK\n");
222         } else {
223                 olog("    ERROR: kstrdup_cnt=%d kfree_cnt=%d kfree2_cnt=%d\n",
224                      kstrdup_cnt, kfree_cnt, kfree2_cnt);
225         }
226 }
227
228 static void test_recursion_and_multiple_handlers(void)
229 {
230         olog("Recursion and multiple handlers:\n");
231
232         pre_test_recursion_and_mh();
233
234         kp_reg(kp_kfree2, "my_kfree", kfree2_h);
235         do_test_recursion();
236         kp_unreg(kp_kfree2);
237
238         post_test_recursion_and_mh();
239 }
240
241 static void test_recursion_and_multiple_handlers2(void)
242 {
243         olog("Recursion and multiple handlers [II]:\n");
244
245         pre_test_recursion_and_mh();
246
247         kp_reg(kp_kfree, "my_kfree", kfree_h);
248         kp_reg(kp_kstrdup, "my_kstrdup", kstrdup_h);
249         kp_reg(kp_kfree2, "my_kfree", kfree2_h);
250
251         run_test_recursion();
252
253         kp_unreg(kp_kstrdup);
254         kp_unreg(kp_kfree);
255         kp_unreg(kp_kfree2);
256
257         post_test_recursion_and_mh();
258 }
259
260
261
262
263 /*
264  ******************************************************************************
265  *                        swap_unregister_kprobe(), sync                      *
266  ******************************************************************************
267  */
268
269 static const char task_name[] = "my_task";
270
271 static int is_my_task(void)
272 {
273         return !strcmp(task_name, current->comm);
274 }
275
276 static int find_module_cnt;
277
278 static struct kprobe *kp_find_module;
279 static int find_module_h(struct kprobe *kp, struct pt_regs *regs)
280 {
281         if (is_my_task()) {
282                 might_sleep();
283                 ++find_module_cnt;
284
285                 /* sleep 0.5 sec */
286                 msleep(500);
287                 schedule();
288
289                 ++find_module_cnt;
290         }
291
292         return 0;
293 }
294
295 static int kthread_my_fn(void *data)
296 {
297         find_module("o_lo_lo");
298         find_module("o_lo_lo");
299
300         while (!kthread_should_stop()) {
301                 set_current_state(TASK_INTERRUPTIBLE);
302                 schedule();
303         }
304
305         return 0;
306 }
307
308
309 static void do_test_sync_unreg(unsigned int ms)
310 {
311         struct task_struct *task;
312
313         kp_reg(kp_find_module, "find_module", find_module_h);
314
315         task = kthread_run(kthread_my_fn, NULL, task_name);
316         if (IS_ERR(task)) {
317                 olog("ERROR: kthread_run()\n");
318                 goto unreg;
319         }
320
321         /* waiting for kthread_my_fn() call */
322         msleep(ms);
323 unreg:
324         kp_unreg(kp_find_module);
325         if (!IS_ERR(task))
326                 kthread_stop(task);
327 }
328
329 static void test_sync_unreg(void)
330 {
331         olog("Unreg kp:\n");
332
333         find_module_cnt = 0;
334
335         do_test_sync_unreg(200);
336
337         if (find_module_cnt == 2) {
338                 olog("    OK\n");
339         } else {
340                 olog("    ERROR: find_module_cnt=%d\n", find_module_cnt);
341         }
342 }
343
344
345
346 /*
347  ******************************************************************************
348  *             swap_unregister_kprobe(), sync and multiple handlers           *
349  ******************************************************************************
350  */
351 static int find_module2_cnt;
352
353 static struct kprobe *kp_find_module2;
354 static int find_module2_h(struct kprobe *kp, struct pt_regs *regs)
355 {
356         if (is_my_task()) {
357                 ++find_module2_cnt;
358
359                 /* sleep 0.5 sec */
360                 msleep(500);
361
362                 ++find_module2_cnt;
363         }
364
365         return 0;
366 }
367
368 static void pre_test_sync_unreg_and_mh(void)
369 {
370         find_module_cnt = 0;
371         find_module2_cnt = 0;
372 }
373
374 static void post_test_sync_unreg_and_mh(int cnt, int cnt2)
375 {
376         if (find_module_cnt == cnt && find_module2_cnt == cnt2) {
377                 olog("    OK\n");
378         } else {
379                 olog("    ERROR: find_module_cnt=%d find_module2_cnt=%d\n",
380                      find_module_cnt, find_module2_cnt);
381         }
382 }
383
384 static void do_test_sync_unreg_and_mh(unsigned int ms)
385 {
386         struct task_struct *task;
387
388         kp_reg(kp_find_module, "find_module", find_module_h);
389         kp_reg(kp_find_module2, "find_module", find_module2_h);
390
391         task = kthread_run(kthread_my_fn, NULL, task_name);
392         if (IS_ERR(task)) {
393                 olog("ERROR: kthread_run()\n");
394                 goto unreg;
395         }
396
397         /* waiting for kthread_my_fn() call */
398         msleep(ms);
399 unreg:
400         kp_unreg(kp_find_module2);
401         kp_unreg(kp_find_module);
402         if (!IS_ERR(task))
403                 kthread_stop(task);
404 }
405
406 static void test_sync_unreg_and_multiple_handlers(void)
407 {
408         olog("Unreg kp and multiple handlers:\n");
409
410         pre_test_sync_unreg_and_mh();
411
412         do_test_sync_unreg_and_mh(700);
413
414         post_test_sync_unreg_and_mh(2, 2);
415 }
416
417 static void do_test_sync_unreg_and_mh2(unsigned int ms)
418 {
419         struct task_struct *task;
420
421         kp_reg(kp_find_module, "find_module", find_module_h);
422         kp_reg(kp_find_module2, "find_module", find_module2_h);
423
424         task = kthread_run(kthread_my_fn, NULL, task_name);
425         if (IS_ERR(task)) {
426                 olog("ERROR: kthread_run()\n");
427                 goto unreg;
428         }
429
430         /* waiting for kthread_my_fn() call */
431         msleep(ms);
432 unreg:
433         kp_unreg(kp_find_module);
434         kp_unreg(kp_find_module2);
435         if (!IS_ERR(task))
436                 kthread_stop(task);
437 }
438
439 static void test_sync_unreg_and_multiple_handlers2(void)
440 {
441         olog("Unreg kp and multiple handlers [II]:\n");
442
443         pre_test_sync_unreg_and_mh();
444
445         do_test_sync_unreg_and_mh2(700);
446
447         post_test_sync_unreg_and_mh(2, 2);
448 }
449
450
451 static void print_mod_info(void)
452 {
453         struct module *mod = THIS_MODULE;
454
455         printk("### MOD_INFO:\n");
456         printk("    core: %p..%p\n", mod->module_init, mod->module_init + mod->init_text_size);
457         printk("    init: %p..%p\n", mod->module_core, mod->module_core + mod->core_text_size);
458         printk("\n");
459 }
460
461 static int test_init(void)
462 {
463         cur_task = current;
464
465         print_mod_info();
466
467         olog("### Begin tests ###\n");
468         test_recursion();
469         test_recursion_and_multiple_handlers();
470         test_recursion_and_multiple_handlers2();
471         // add 3
472
473         test_sync_unreg();
474         test_sync_unreg_and_multiple_handlers();
475         test_sync_unreg_and_multiple_handlers2();
476         olog("### End tests ###\n");
477
478         return -1;
479 }
480
481 static void test_exit(void)
482 {
483 }
484
485
486 SWAP_LIGHT_INIT_MODULE(NULL, test_init, test_exit, NULL, NULL);
487
488 MODULE_LICENSE("GPL");