[REFACTOR] divide kprobe tests module
[kernel/swap-modules.git] / tests / kprobe_tests / kp_tests.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/delay.h>
25 #include <linux/module.h>
26 #include <linux/kthread.h>
27 #include <kprobe/swap_kprobes.h>
28 #include "kp_module.h"
29
30
31 static struct task_struct *cur_task;
32
33
34 static struct kprobe *kp_create(char *name,
35                                 int (*pre_h)(struct kprobe *, struct pt_regs *))
36 {
37         struct kprobe *p;
38
39         p = kzalloc(sizeof(*p), GFP_KERNEL);
40         if (p) {
41                 p->symbol_name = name;
42                 p->pre_handler = pre_h;
43         }
44
45         return p;
46 }
47
48 static void kp_free(struct kprobe *p)
49 {
50         memset(p, 0x10, sizeof(*p));
51 }
52
53 #define kp_reg(ptr, name, handler) \
54         do { \
55                 ptr = kp_create(name, handler); \
56                 swap_register_kprobe(ptr); \
57         } while (0)
58
59 #define kp_unreg(ptr) \
60         do { \
61                 swap_unregister_kprobe(ptr); \
62                 kp_free(ptr); \
63                 ptr = NULL; \
64         } while (0)
65
66
67 noinline char *my_kstrdup(const char *s, gfp_t gfp)
68 {
69         return kstrdup(s, gfp);
70 }
71
72 noinline void my_kfree(const void *data)
73 {
74         kfree(data);
75 }
76
77
78
79
80 /*
81  ******************************************************************************
82  *                                 recursion                                  *
83  ******************************************************************************
84  */
85 static int kstrdup_cnt;
86 static int kfree_cnt;
87
88 static struct kprobe *kp_kstrdup;
89 static int kstrdup_h(struct kprobe *kp, struct pt_regs *regs)
90 {
91         char *str;
92
93         str = my_kstrdup("from_kfree_h", GFP_ATOMIC);
94         my_kfree(str);
95
96         ++kstrdup_cnt;
97
98         return 0;
99 }
100
101 static struct kprobe *kp_kfree;
102 static int kfree_h(struct kprobe *kp, struct pt_regs *regs)
103 {
104         ++kfree_cnt;
105
106         return 0;
107 }
108
109 static void run_test_recursion(void)
110 {
111         char *str;
112
113         str = my_kstrdup("test_string_0", GFP_KERNEL);
114         my_kfree(str);
115
116         str = my_kstrdup("test_string_1", GFP_KERNEL);
117         my_kfree(str);
118 }
119
120 static void do_test_recursion(void)
121 {
122         kp_reg(kp_kfree, "my_kfree", kfree_h);
123         kp_reg(kp_kstrdup, "my_kstrdup", kstrdup_h);
124
125         run_test_recursion();
126
127         kp_unreg(kp_kstrdup);
128         kp_unreg(kp_kfree);
129 }
130
131
132 static void test_recursion(void)
133 {
134         olog("Recursion:\n");
135
136         kstrdup_cnt = 0;
137         kfree_cnt = 0;
138
139         do_test_recursion();
140
141         if (kstrdup_cnt == 2 && kfree_cnt == 2) {
142                 olog("    OK\n");
143         } else {
144                 olog("    ERROR: kstrdup_cnt=%d kfree_cnt=%d\n",
145                        kstrdup_cnt, kfree_cnt);
146         }
147 }
148
149
150
151
152 /*
153  ******************************************************************************
154  *            recursion and multiple handlers (Aggregate probe)               *
155  ******************************************************************************
156  */
157 static int kfree2_cnt;
158
159 static struct kprobe *kp_kfree2;
160 static int kfree2_h(struct kprobe *kp, struct pt_regs *regs)
161 {
162         if (current != cur_task || in_interrupt())
163                 return 0;
164
165         ++kfree2_cnt;
166         return 0;
167 }
168
169 static void pre_test_recursion_and_mh(void)
170 {
171         kstrdup_cnt = 0;
172         kfree_cnt = 0;
173         kfree2_cnt = 0;
174 }
175
176 static void post_test_recursion_and_mh(void)
177 {
178         if (kstrdup_cnt == 2 && kfree_cnt == 2 && kfree2_cnt == 2) {
179                 olog("    OK\n");
180         } else {
181                 olog("    ERROR: kstrdup_cnt=%d kfree_cnt=%d kfree2_cnt=%d\n",
182                      kstrdup_cnt, kfree_cnt, kfree2_cnt);
183         }
184 }
185
186 static void test_recursion_and_multiple_handlers(void)
187 {
188         olog("Recursion and multiple handlers:\n");
189
190         pre_test_recursion_and_mh();
191
192         kp_reg(kp_kfree2, "my_kfree", kfree2_h);
193         do_test_recursion();
194         kp_unreg(kp_kfree2);
195
196         post_test_recursion_and_mh();
197 }
198
199 static void test_recursion_and_multiple_handlers2(void)
200 {
201         olog("Recursion and multiple handlers [II]:\n");
202
203         pre_test_recursion_and_mh();
204
205         kp_reg(kp_kfree, "my_kfree", kfree_h);
206         kp_reg(kp_kstrdup, "my_kstrdup", kstrdup_h);
207         kp_reg(kp_kfree2, "my_kfree", kfree2_h);
208
209         run_test_recursion();
210
211         kp_unreg(kp_kstrdup);
212         kp_unreg(kp_kfree);
213         kp_unreg(kp_kfree2);
214
215         post_test_recursion_and_mh();
216 }
217
218
219
220
221 /*
222  ******************************************************************************
223  *                        swap_unregister_kprobe(), sync                      *
224  ******************************************************************************
225  */
226
227 static const char task_name[] = "my_task";
228
229 static int is_my_task(void)
230 {
231         return !strcmp(task_name, current->comm);
232 }
233
234 static int find_module_cnt;
235
236 static struct kprobe *kp_find_module;
237 static int find_module_h(struct kprobe *kp, struct pt_regs *regs)
238 {
239         if (is_my_task()) {
240                 might_sleep();
241                 ++find_module_cnt;
242
243                 /* sleep 0.5 sec */
244                 msleep(500);
245                 schedule();
246
247                 ++find_module_cnt;
248         }
249
250         return 0;
251 }
252
253 static int kthread_my_fn(void *data)
254 {
255         find_module("o_lo_lo");
256         find_module("o_lo_lo");
257
258         while (!kthread_should_stop()) {
259                 set_current_state(TASK_INTERRUPTIBLE);
260                 schedule();
261         }
262
263         return 0;
264 }
265
266
267 static void do_test_sync_unreg(unsigned int ms)
268 {
269         struct task_struct *task;
270
271         kp_reg(kp_find_module, "find_module", find_module_h);
272
273         task = kthread_run(kthread_my_fn, NULL, task_name);
274         if (IS_ERR(task)) {
275                 olog("ERROR: kthread_run()\n");
276                 goto unreg;
277         }
278
279         /* waiting for kthread_my_fn() call */
280         msleep(ms);
281 unreg:
282         kp_unreg(kp_find_module);
283         if (!IS_ERR(task))
284                 kthread_stop(task);
285 }
286
287 static void test_sync_unreg(void)
288 {
289         olog("Unreg kp:\n");
290
291         find_module_cnt = 0;
292
293         do_test_sync_unreg(200);
294
295         if (find_module_cnt == 2) {
296                 olog("    OK\n");
297         } else {
298                 olog("    ERROR: find_module_cnt=%d\n", find_module_cnt);
299         }
300 }
301
302
303
304 /*
305  ******************************************************************************
306  *             swap_unregister_kprobe(), sync and multiple handlers           *
307  ******************************************************************************
308  */
309 static int find_module2_cnt;
310
311 static struct kprobe *kp_find_module2;
312 static int find_module2_h(struct kprobe *kp, struct pt_regs *regs)
313 {
314         if (is_my_task()) {
315                 ++find_module2_cnt;
316
317                 /* sleep 0.5 sec */
318                 msleep(500);
319
320                 ++find_module2_cnt;
321         }
322
323         return 0;
324 }
325
326 static void pre_test_sync_unreg_and_mh(void)
327 {
328         find_module_cnt = 0;
329         find_module2_cnt = 0;
330 }
331
332 static void post_test_sync_unreg_and_mh(int cnt, int cnt2)
333 {
334         if (find_module_cnt == cnt && find_module2_cnt == cnt2) {
335                 olog("    OK\n");
336         } else {
337                 olog("    ERROR: find_module_cnt=%d find_module2_cnt=%d\n",
338                      find_module_cnt, find_module2_cnt);
339         }
340 }
341
342 static void do_test_sync_unreg_and_mh(unsigned int ms)
343 {
344         struct task_struct *task;
345
346         kp_reg(kp_find_module, "find_module", find_module_h);
347         kp_reg(kp_find_module2, "find_module", find_module2_h);
348
349         task = kthread_run(kthread_my_fn, NULL, task_name);
350         if (IS_ERR(task)) {
351                 olog("ERROR: kthread_run()\n");
352                 goto unreg;
353         }
354
355         /* waiting for kthread_my_fn() call */
356         msleep(ms);
357 unreg:
358         kp_unreg(kp_find_module2);
359         kp_unreg(kp_find_module);
360         if (!IS_ERR(task))
361                 kthread_stop(task);
362 }
363
364 static void test_sync_unreg_and_multiple_handlers(void)
365 {
366         olog("Unreg kp and multiple handlers:\n");
367
368         pre_test_sync_unreg_and_mh();
369
370         do_test_sync_unreg_and_mh(700);
371
372         post_test_sync_unreg_and_mh(2, 2);
373 }
374
375 static void do_test_sync_unreg_and_mh2(unsigned int ms)
376 {
377         struct task_struct *task;
378
379         kp_reg(kp_find_module, "find_module", find_module_h);
380         kp_reg(kp_find_module2, "find_module", find_module2_h);
381
382         task = kthread_run(kthread_my_fn, NULL, task_name);
383         if (IS_ERR(task)) {
384                 olog("ERROR: kthread_run()\n");
385                 goto unreg;
386         }
387
388         /* waiting for kthread_my_fn() call */
389         msleep(ms);
390 unreg:
391         kp_unreg(kp_find_module);
392         kp_unreg(kp_find_module2);
393         if (!IS_ERR(task))
394                 kthread_stop(task);
395 }
396
397 static void test_sync_unreg_and_multiple_handlers2(void)
398 {
399         olog("Unreg kp and multiple handlers [II]:\n");
400
401         pre_test_sync_unreg_and_mh();
402
403         do_test_sync_unreg_and_mh2(700);
404
405         post_test_sync_unreg_and_mh(2, 2);
406 }
407
408 int kp_tests_run(void)
409 {
410         cur_task = current;
411
412         test_recursion();
413         test_recursion_and_multiple_handlers();
414         test_recursion_and_multiple_handlers2();
415         // add 3
416
417         test_sync_unreg();
418         test_sync_unreg_and_multiple_handlers();
419         test_sync_unreg_and_multiple_handlers2();
420
421         return 0;
422 }