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.
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.
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.
16 * Copyright (C) Samsung Electronics, 2016
18 * 2016 Vyacheslav Cherkashin <v.cherkashin@samsung.com>
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>
33 static struct task_struct *cur_task;
38 ******************************************************************************
40 ******************************************************************************
42 static long write_to_stdout(const char *buf, size_t len)
44 static asmlinkage long (*sys_write)(unsigned int, const char __user *, size_t) = NULL;
47 if (sys_write == NULL)
48 sys_write = (void *)swap_ksyms("sys_write");
51 mm_segment_t fs = get_fs();
53 ret = sys_write(1, buf, len);
60 static void olog(const char *fmt, ...)
66 vsnprintf(buf, sizeof(buf), fmt, args);
70 write_to_stdout(buf, strlen(buf));
76 static struct kprobe *kp_create(char *name,
77 int (*pre_h)(struct kprobe *, struct pt_regs *))
81 p = kzalloc(sizeof(*p), GFP_KERNEL);
83 p->symbol_name = name;
84 p->pre_handler = pre_h;
90 static void kp_free(struct kprobe *p)
92 memset(p, 0x10, sizeof(*p));
95 #define kp_reg(ptr, name, handler) \
97 ptr = kp_create(name, handler); \
98 swap_register_kprobe(ptr); \
101 #define kp_unreg(ptr) \
103 swap_unregister_kprobe(ptr); \
109 noinline char *my_kstrdup(const char *s, gfp_t gfp)
111 return kstrdup(s, gfp);
114 noinline void my_kfree(const void *data)
123 ******************************************************************************
125 ******************************************************************************
127 static int kstrdup_cnt;
128 static int kfree_cnt;
130 static struct kprobe *kp_kstrdup;
131 static int kstrdup_h(struct kprobe *kp, struct pt_regs *regs)
135 str = my_kstrdup("from_kfree_h", GFP_ATOMIC);
143 static struct kprobe *kp_kfree;
144 static int kfree_h(struct kprobe *kp, struct pt_regs *regs)
151 static void run_test_recursion(void)
155 str = my_kstrdup("test_string_0", GFP_KERNEL);
158 str = my_kstrdup("test_string_1", GFP_KERNEL);
162 static void do_test_recursion(void)
164 kp_reg(kp_kfree, "my_kfree", kfree_h);
165 kp_reg(kp_kstrdup, "my_kstrdup", kstrdup_h);
167 run_test_recursion();
169 kp_unreg(kp_kstrdup);
174 static void test_recursion(void)
176 olog("Recursion:\n");
183 if (kstrdup_cnt == 2 && kfree_cnt == 2) {
186 olog(" ERROR: kstrdup_cnt=%d kfree_cnt=%d\n",
187 kstrdup_cnt, kfree_cnt);
195 ******************************************************************************
196 * recursion and multiple handlers (Aggregate probe) *
197 ******************************************************************************
199 static int kfree2_cnt;
201 static struct kprobe *kp_kfree2;
202 static int kfree2_h(struct kprobe *kp, struct pt_regs *regs)
204 if (current != cur_task || in_interrupt())
211 static void pre_test_recursion_and_mh(void)
218 static void post_test_recursion_and_mh(void)
220 if (kstrdup_cnt == 2 && kfree_cnt == 2 && kfree2_cnt == 2) {
223 olog(" ERROR: kstrdup_cnt=%d kfree_cnt=%d kfree2_cnt=%d\n",
224 kstrdup_cnt, kfree_cnt, kfree2_cnt);
228 static void test_recursion_and_multiple_handlers(void)
230 olog("Recursion and multiple handlers:\n");
232 pre_test_recursion_and_mh();
234 kp_reg(kp_kfree2, "my_kfree", kfree2_h);
238 post_test_recursion_and_mh();
241 static void test_recursion_and_multiple_handlers2(void)
243 olog("Recursion and multiple handlers [II]:\n");
245 pre_test_recursion_and_mh();
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);
251 run_test_recursion();
253 kp_unreg(kp_kstrdup);
257 post_test_recursion_and_mh();
264 ******************************************************************************
265 * swap_unregister_kprobe(), sync *
266 ******************************************************************************
269 static const char task_name[] = "my_task";
271 static int is_my_task(void)
273 return !strcmp(task_name, current->comm);
276 static int find_module_cnt;
278 static struct kprobe *kp_find_module;
279 static int find_module_h(struct kprobe *kp, struct pt_regs *regs)
295 static int kthread_my_fn(void *data)
297 find_module("o_lo_lo");
298 find_module("o_lo_lo");
300 while (!kthread_should_stop()) {
301 set_current_state(TASK_INTERRUPTIBLE);
309 static void do_test_sync_unreg(unsigned int ms)
311 struct task_struct *task;
313 kp_reg(kp_find_module, "find_module", find_module_h);
315 task = kthread_run(kthread_my_fn, NULL, task_name);
317 olog("ERROR: kthread_run()\n");
321 /* waiting for kthread_my_fn() call */
324 kp_unreg(kp_find_module);
329 static void test_sync_unreg(void)
335 do_test_sync_unreg(200);
337 if (find_module_cnt == 2) {
340 olog(" ERROR: find_module_cnt=%d\n", find_module_cnt);
347 ******************************************************************************
348 * swap_unregister_kprobe(), sync and multiple handlers *
349 ******************************************************************************
351 static int find_module2_cnt;
353 static struct kprobe *kp_find_module2;
354 static int find_module2_h(struct kprobe *kp, struct pt_regs *regs)
368 static void pre_test_sync_unreg_and_mh(void)
371 find_module2_cnt = 0;
374 static void post_test_sync_unreg_and_mh(int cnt, int cnt2)
376 if (find_module_cnt == cnt && find_module2_cnt == cnt2) {
379 olog(" ERROR: find_module_cnt=%d find_module2_cnt=%d\n",
380 find_module_cnt, find_module2_cnt);
384 static void do_test_sync_unreg_and_mh(unsigned int ms)
386 struct task_struct *task;
388 kp_reg(kp_find_module, "find_module", find_module_h);
389 kp_reg(kp_find_module2, "find_module", find_module2_h);
391 task = kthread_run(kthread_my_fn, NULL, task_name);
393 olog("ERROR: kthread_run()\n");
397 /* waiting for kthread_my_fn() call */
400 kp_unreg(kp_find_module2);
401 kp_unreg(kp_find_module);
406 static void test_sync_unreg_and_multiple_handlers(void)
408 olog("Unreg kp and multiple handlers:\n");
410 pre_test_sync_unreg_and_mh();
412 do_test_sync_unreg_and_mh(700);
414 post_test_sync_unreg_and_mh(2, 2);
417 static void do_test_sync_unreg_and_mh2(unsigned int ms)
419 struct task_struct *task;
421 kp_reg(kp_find_module, "find_module", find_module_h);
422 kp_reg(kp_find_module2, "find_module", find_module2_h);
424 task = kthread_run(kthread_my_fn, NULL, task_name);
426 olog("ERROR: kthread_run()\n");
430 /* waiting for kthread_my_fn() call */
433 kp_unreg(kp_find_module);
434 kp_unreg(kp_find_module2);
439 static void test_sync_unreg_and_multiple_handlers2(void)
441 olog("Unreg kp and multiple handlers [II]:\n");
443 pre_test_sync_unreg_and_mh();
445 do_test_sync_unreg_and_mh2(700);
447 post_test_sync_unreg_and_mh(2, 2);
451 static void print_mod_info(void)
453 struct module *mod = THIS_MODULE;
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);
461 static int test_init(void)
467 olog("### Begin tests ###\n");
469 test_recursion_and_multiple_handlers();
470 test_recursion_and_multiple_handlers2();
474 test_sync_unreg_and_multiple_handlers();
475 test_sync_unreg_and_multiple_handlers2();
476 olog("### End tests ###\n");
481 static void test_exit(void)
486 SWAP_LIGHT_INIT_MODULE(NULL, test_init, test_exit, NULL, NULL);
488 MODULE_LICENSE("GPL");