Merge branch 'cpus4096-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux-2.6] / kernel / test_kprobes.c
1 /*
2  * test_kprobes.c - simple sanity test for *probes
3  *
4  * Copyright IBM Corp. 2008
5  *
6  * This program is free software;  you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it would be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
14  * the GNU General Public License for more details.
15  */
16
17 #include <linux/kernel.h>
18 #include <linux/kprobes.h>
19 #include <linux/random.h>
20
21 #define div_factor 3
22
23 static u32 rand1, preh_val, posth_val, jph_val;
24 static int errors, handler_errors, num_tests;
25 static u32 (*target)(u32 value);
26 static u32 (*target2)(u32 value);
27
28 static noinline u32 kprobe_target(u32 value)
29 {
30         return (value / div_factor);
31 }
32
33 static int kp_pre_handler(struct kprobe *p, struct pt_regs *regs)
34 {
35         preh_val = (rand1 / div_factor);
36         return 0;
37 }
38
39 static void kp_post_handler(struct kprobe *p, struct pt_regs *regs,
40                 unsigned long flags)
41 {
42         if (preh_val != (rand1 / div_factor)) {
43                 handler_errors++;
44                 printk(KERN_ERR "Kprobe smoke test failed: "
45                                 "incorrect value in post_handler\n");
46         }
47         posth_val = preh_val + div_factor;
48 }
49
50 static struct kprobe kp = {
51         .symbol_name = "kprobe_target",
52         .pre_handler = kp_pre_handler,
53         .post_handler = kp_post_handler
54 };
55
56 static int test_kprobe(void)
57 {
58         int ret;
59
60         ret = register_kprobe(&kp);
61         if (ret < 0) {
62                 printk(KERN_ERR "Kprobe smoke test failed: "
63                                 "register_kprobe returned %d\n", ret);
64                 return ret;
65         }
66
67         ret = target(rand1);
68         unregister_kprobe(&kp);
69
70         if (preh_val == 0) {
71                 printk(KERN_ERR "Kprobe smoke test failed: "
72                                 "kprobe pre_handler not called\n");
73                 handler_errors++;
74         }
75
76         if (posth_val == 0) {
77                 printk(KERN_ERR "Kprobe smoke test failed: "
78                                 "kprobe post_handler not called\n");
79                 handler_errors++;
80         }
81
82         return 0;
83 }
84
85 static noinline u32 kprobe_target2(u32 value)
86 {
87         return (value / div_factor) + 1;
88 }
89
90 static int kp_pre_handler2(struct kprobe *p, struct pt_regs *regs)
91 {
92         preh_val = (rand1 / div_factor) + 1;
93         return 0;
94 }
95
96 static void kp_post_handler2(struct kprobe *p, struct pt_regs *regs,
97                 unsigned long flags)
98 {
99         if (preh_val != (rand1 / div_factor) + 1) {
100                 handler_errors++;
101                 printk(KERN_ERR "Kprobe smoke test failed: "
102                                 "incorrect value in post_handler2\n");
103         }
104         posth_val = preh_val + div_factor;
105 }
106
107 static struct kprobe kp2 = {
108         .symbol_name = "kprobe_target2",
109         .pre_handler = kp_pre_handler2,
110         .post_handler = kp_post_handler2
111 };
112
113 static int test_kprobes(void)
114 {
115         int ret;
116         struct kprobe *kps[2] = {&kp, &kp2};
117
118         kp.addr = 0; /* addr should be cleard for reusing kprobe. */
119         ret = register_kprobes(kps, 2);
120         if (ret < 0) {
121                 printk(KERN_ERR "Kprobe smoke test failed: "
122                                 "register_kprobes returned %d\n", ret);
123                 return ret;
124         }
125
126         preh_val = 0;
127         posth_val = 0;
128         ret = target(rand1);
129
130         if (preh_val == 0) {
131                 printk(KERN_ERR "Kprobe smoke test failed: "
132                                 "kprobe pre_handler not called\n");
133                 handler_errors++;
134         }
135
136         if (posth_val == 0) {
137                 printk(KERN_ERR "Kprobe smoke test failed: "
138                                 "kprobe post_handler not called\n");
139                 handler_errors++;
140         }
141
142         preh_val = 0;
143         posth_val = 0;
144         ret = target2(rand1);
145
146         if (preh_val == 0) {
147                 printk(KERN_ERR "Kprobe smoke test failed: "
148                                 "kprobe pre_handler2 not called\n");
149                 handler_errors++;
150         }
151
152         if (posth_val == 0) {
153                 printk(KERN_ERR "Kprobe smoke test failed: "
154                                 "kprobe post_handler2 not called\n");
155                 handler_errors++;
156         }
157
158         unregister_kprobes(kps, 2);
159         return 0;
160
161 }
162
163 static u32 j_kprobe_target(u32 value)
164 {
165         if (value != rand1) {
166                 handler_errors++;
167                 printk(KERN_ERR "Kprobe smoke test failed: "
168                                 "incorrect value in jprobe handler\n");
169         }
170
171         jph_val = rand1;
172         jprobe_return();
173         return 0;
174 }
175
176 static struct jprobe jp = {
177         .entry          = j_kprobe_target,
178         .kp.symbol_name = "kprobe_target"
179 };
180
181 static int test_jprobe(void)
182 {
183         int ret;
184
185         ret = register_jprobe(&jp);
186         if (ret < 0) {
187                 printk(KERN_ERR "Kprobe smoke test failed: "
188                                 "register_jprobe returned %d\n", ret);
189                 return ret;
190         }
191
192         ret = target(rand1);
193         unregister_jprobe(&jp);
194         if (jph_val == 0) {
195                 printk(KERN_ERR "Kprobe smoke test failed: "
196                                 "jprobe handler not called\n");
197                 handler_errors++;
198         }
199
200         return 0;
201 }
202
203 static struct jprobe jp2 = {
204         .entry          = j_kprobe_target,
205         .kp.symbol_name = "kprobe_target2"
206 };
207
208 static int test_jprobes(void)
209 {
210         int ret;
211         struct jprobe *jps[2] = {&jp, &jp2};
212
213         jp.kp.addr = 0; /* addr should be cleard for reusing kprobe. */
214         ret = register_jprobes(jps, 2);
215         if (ret < 0) {
216                 printk(KERN_ERR "Kprobe smoke test failed: "
217                                 "register_jprobes returned %d\n", ret);
218                 return ret;
219         }
220
221         jph_val = 0;
222         ret = target(rand1);
223         if (jph_val == 0) {
224                 printk(KERN_ERR "Kprobe smoke test failed: "
225                                 "jprobe handler not called\n");
226                 handler_errors++;
227         }
228
229         jph_val = 0;
230         ret = target2(rand1);
231         if (jph_val == 0) {
232                 printk(KERN_ERR "Kprobe smoke test failed: "
233                                 "jprobe handler2 not called\n");
234                 handler_errors++;
235         }
236         unregister_jprobes(jps, 2);
237
238         return 0;
239 }
240 #ifdef CONFIG_KRETPROBES
241 static u32 krph_val;
242
243 static int entry_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
244 {
245         krph_val = (rand1 / div_factor);
246         return 0;
247 }
248
249 static int return_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
250 {
251         unsigned long ret = regs_return_value(regs);
252
253         if (ret != (rand1 / div_factor)) {
254                 handler_errors++;
255                 printk(KERN_ERR "Kprobe smoke test failed: "
256                                 "incorrect value in kretprobe handler\n");
257         }
258         if (krph_val == 0) {
259                 handler_errors++;
260                 printk(KERN_ERR "Kprobe smoke test failed: "
261                                 "call to kretprobe entry handler failed\n");
262         }
263
264         krph_val = rand1;
265         return 0;
266 }
267
268 static struct kretprobe rp = {
269         .handler        = return_handler,
270         .entry_handler  = entry_handler,
271         .kp.symbol_name = "kprobe_target"
272 };
273
274 static int test_kretprobe(void)
275 {
276         int ret;
277
278         ret = register_kretprobe(&rp);
279         if (ret < 0) {
280                 printk(KERN_ERR "Kprobe smoke test failed: "
281                                 "register_kretprobe returned %d\n", ret);
282                 return ret;
283         }
284
285         ret = target(rand1);
286         unregister_kretprobe(&rp);
287         if (krph_val != rand1) {
288                 printk(KERN_ERR "Kprobe smoke test failed: "
289                                 "kretprobe handler not called\n");
290                 handler_errors++;
291         }
292
293         return 0;
294 }
295
296 static int return_handler2(struct kretprobe_instance *ri, struct pt_regs *regs)
297 {
298         unsigned long ret = regs_return_value(regs);
299
300         if (ret != (rand1 / div_factor) + 1) {
301                 handler_errors++;
302                 printk(KERN_ERR "Kprobe smoke test failed: "
303                                 "incorrect value in kretprobe handler2\n");
304         }
305         if (krph_val == 0) {
306                 handler_errors++;
307                 printk(KERN_ERR "Kprobe smoke test failed: "
308                                 "call to kretprobe entry handler failed\n");
309         }
310
311         krph_val = rand1;
312         return 0;
313 }
314
315 static struct kretprobe rp2 = {
316         .handler        = return_handler2,
317         .entry_handler  = entry_handler,
318         .kp.symbol_name = "kprobe_target2"
319 };
320
321 static int test_kretprobes(void)
322 {
323         int ret;
324         struct kretprobe *rps[2] = {&rp, &rp2};
325
326         rp.kp.addr = 0; /* addr should be cleard for reusing kprobe. */
327         ret = register_kretprobes(rps, 2);
328         if (ret < 0) {
329                 printk(KERN_ERR "Kprobe smoke test failed: "
330                                 "register_kretprobe returned %d\n", ret);
331                 return ret;
332         }
333
334         krph_val = 0;
335         ret = target(rand1);
336         if (krph_val != rand1) {
337                 printk(KERN_ERR "Kprobe smoke test failed: "
338                                 "kretprobe handler not called\n");
339                 handler_errors++;
340         }
341
342         krph_val = 0;
343         ret = target2(rand1);
344         if (krph_val != rand1) {
345                 printk(KERN_ERR "Kprobe smoke test failed: "
346                                 "kretprobe handler2 not called\n");
347                 handler_errors++;
348         }
349         unregister_kretprobes(rps, 2);
350         return 0;
351 }
352 #endif /* CONFIG_KRETPROBES */
353
354 int init_test_probes(void)
355 {
356         int ret;
357
358         target = kprobe_target;
359         target2 = kprobe_target2;
360
361         do {
362                 rand1 = random32();
363         } while (rand1 <= div_factor);
364
365         printk(KERN_INFO "Kprobe smoke test started\n");
366         num_tests++;
367         ret = test_kprobe();
368         if (ret < 0)
369                 errors++;
370
371         num_tests++;
372         ret = test_kprobes();
373         if (ret < 0)
374                 errors++;
375
376         num_tests++;
377         ret = test_jprobe();
378         if (ret < 0)
379                 errors++;
380
381         num_tests++;
382         ret = test_jprobes();
383         if (ret < 0)
384                 errors++;
385
386 #ifdef CONFIG_KRETPROBES
387         num_tests++;
388         ret = test_kretprobe();
389         if (ret < 0)
390                 errors++;
391
392         num_tests++;
393         ret = test_kretprobes();
394         if (ret < 0)
395                 errors++;
396 #endif /* CONFIG_KRETPROBES */
397
398         if (errors)
399                 printk(KERN_ERR "BUG: Kprobe smoke test: %d out of "
400                                 "%d tests failed\n", errors, num_tests);
401         else if (handler_errors)
402                 printk(KERN_ERR "BUG: Kprobe smoke test: %d error(s) "
403                                 "running handlers\n", handler_errors);
404         else
405                 printk(KERN_INFO "Kprobe smoke test passed successfully\n");
406
407         return 0;
408 }