Branch data Line data Source code
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 : 0 : static noinline u32 kprobe_target(u32 value)
29 : : {
30 : 0 : return (value / div_factor);
31 : : }
32 : :
33 : 0 : static int kp_pre_handler(struct kprobe *p, struct pt_regs *regs)
34 : : {
35 : 0 : preh_val = (rand1 / div_factor);
36 : 0 : return 0;
37 : : }
38 : :
39 : 0 : static void kp_post_handler(struct kprobe *p, struct pt_regs *regs,
40 : : unsigned long flags)
41 : : {
42 [ # # ]: 0 : if (preh_val != (rand1 / div_factor)) {
43 : 0 : handler_errors++;
44 : 0 : printk(KERN_ERR "Kprobe smoke test failed: "
45 : : "incorrect value in post_handler\n");
46 : : }
47 : 0 : posth_val = preh_val + div_factor;
48 : 0 : }
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 : 0 : static int test_kprobe(void)
57 : : {
58 : : int ret;
59 : :
60 : 0 : ret = register_kprobe(&kp);
61 [ # # ]: 0 : if (ret < 0) {
62 : 0 : printk(KERN_ERR "Kprobe smoke test failed: "
63 : : "register_kprobe returned %d\n", ret);
64 : 0 : return ret;
65 : : }
66 : :
67 : 0 : ret = target(rand1);
68 : 0 : unregister_kprobe(&kp);
69 : :
70 [ # # ]: 0 : if (preh_val == 0) {
71 : 0 : printk(KERN_ERR "Kprobe smoke test failed: "
72 : : "kprobe pre_handler not called\n");
73 : 0 : handler_errors++;
74 : : }
75 : :
76 [ # # ]: 0 : if (posth_val == 0) {
77 : 0 : printk(KERN_ERR "Kprobe smoke test failed: "
78 : : "kprobe post_handler not called\n");
79 : 0 : handler_errors++;
80 : : }
81 : :
82 : : return 0;
83 : : }
84 : :
85 : 0 : static noinline u32 kprobe_target2(u32 value)
86 : : {
87 : 0 : return (value / div_factor) + 1;
88 : : }
89 : :
90 : 0 : static int kp_pre_handler2(struct kprobe *p, struct pt_regs *regs)
91 : : {
92 : 0 : preh_val = (rand1 / div_factor) + 1;
93 : 0 : return 0;
94 : : }
95 : :
96 : 0 : static void kp_post_handler2(struct kprobe *p, struct pt_regs *regs,
97 : : unsigned long flags)
98 : : {
99 [ # # ]: 0 : if (preh_val != (rand1 / div_factor) + 1) {
100 : 0 : handler_errors++;
101 : 0 : printk(KERN_ERR "Kprobe smoke test failed: "
102 : : "incorrect value in post_handler2\n");
103 : : }
104 : 0 : posth_val = preh_val + div_factor;
105 : 0 : }
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 : 0 : static int test_kprobes(void)
114 : : {
115 : : int ret;
116 : 0 : struct kprobe *kps[2] = {&kp, &kp2};
117 : :
118 : : /* addr and flags should be cleard for reusing kprobe. */
119 : 0 : kp.addr = NULL;
120 : 0 : kp.flags = 0;
121 : 0 : ret = register_kprobes(kps, 2);
122 [ # # ]: 0 : if (ret < 0) {
123 : 0 : printk(KERN_ERR "Kprobe smoke test failed: "
124 : : "register_kprobes returned %d\n", ret);
125 : 0 : return ret;
126 : : }
127 : :
128 : 0 : preh_val = 0;
129 : 0 : posth_val = 0;
130 : 0 : ret = target(rand1);
131 : :
132 [ # # ]: 0 : if (preh_val == 0) {
133 : 0 : printk(KERN_ERR "Kprobe smoke test failed: "
134 : : "kprobe pre_handler not called\n");
135 : 0 : handler_errors++;
136 : : }
137 : :
138 [ # # ]: 0 : if (posth_val == 0) {
139 : 0 : printk(KERN_ERR "Kprobe smoke test failed: "
140 : : "kprobe post_handler not called\n");
141 : 0 : handler_errors++;
142 : : }
143 : :
144 : 0 : preh_val = 0;
145 : 0 : posth_val = 0;
146 : 0 : ret = target2(rand1);
147 : :
148 [ # # ]: 0 : if (preh_val == 0) {
149 : 0 : printk(KERN_ERR "Kprobe smoke test failed: "
150 : : "kprobe pre_handler2 not called\n");
151 : 0 : handler_errors++;
152 : : }
153 : :
154 [ # # ]: 0 : if (posth_val == 0) {
155 : 0 : printk(KERN_ERR "Kprobe smoke test failed: "
156 : : "kprobe post_handler2 not called\n");
157 : 0 : handler_errors++;
158 : : }
159 : :
160 : 0 : unregister_kprobes(kps, 2);
161 : 0 : return 0;
162 : :
163 : : }
164 : :
165 : 0 : static u32 j_kprobe_target(u32 value)
166 : : {
167 [ # # ]: 0 : if (value != rand1) {
168 : 0 : handler_errors++;
169 : 0 : printk(KERN_ERR "Kprobe smoke test failed: "
170 : : "incorrect value in jprobe handler\n");
171 : : }
172 : :
173 : 0 : jph_val = rand1;
174 : 0 : jprobe_return();
175 : 0 : return 0;
176 : : }
177 : :
178 : : static struct jprobe jp = {
179 : : .entry = j_kprobe_target,
180 : : .kp.symbol_name = "kprobe_target"
181 : : };
182 : :
183 : 0 : static int test_jprobe(void)
184 : : {
185 : : int ret;
186 : :
187 : 0 : ret = register_jprobe(&jp);
188 [ # # ]: 0 : if (ret < 0) {
189 : 0 : printk(KERN_ERR "Kprobe smoke test failed: "
190 : : "register_jprobe returned %d\n", ret);
191 : 0 : return ret;
192 : : }
193 : :
194 : 0 : ret = target(rand1);
195 : 0 : unregister_jprobe(&jp);
196 [ # # ]: 0 : if (jph_val == 0) {
197 : 0 : printk(KERN_ERR "Kprobe smoke test failed: "
198 : : "jprobe handler not called\n");
199 : 0 : handler_errors++;
200 : : }
201 : :
202 : : return 0;
203 : : }
204 : :
205 : : static struct jprobe jp2 = {
206 : : .entry = j_kprobe_target,
207 : : .kp.symbol_name = "kprobe_target2"
208 : : };
209 : :
210 : 0 : static int test_jprobes(void)
211 : : {
212 : : int ret;
213 : 0 : struct jprobe *jps[2] = {&jp, &jp2};
214 : :
215 : : /* addr and flags should be cleard for reusing kprobe. */
216 : 0 : jp.kp.addr = NULL;
217 : 0 : jp.kp.flags = 0;
218 : 0 : ret = register_jprobes(jps, 2);
219 [ # # ]: 0 : if (ret < 0) {
220 : 0 : printk(KERN_ERR "Kprobe smoke test failed: "
221 : : "register_jprobes returned %d\n", ret);
222 : 0 : return ret;
223 : : }
224 : :
225 : 0 : jph_val = 0;
226 : 0 : ret = target(rand1);
227 [ # # ]: 0 : if (jph_val == 0) {
228 : 0 : printk(KERN_ERR "Kprobe smoke test failed: "
229 : : "jprobe handler not called\n");
230 : 0 : handler_errors++;
231 : : }
232 : :
233 : 0 : jph_val = 0;
234 : 0 : ret = target2(rand1);
235 [ # # ]: 0 : if (jph_val == 0) {
236 : 0 : printk(KERN_ERR "Kprobe smoke test failed: "
237 : : "jprobe handler2 not called\n");
238 : 0 : handler_errors++;
239 : : }
240 : 0 : unregister_jprobes(jps, 2);
241 : :
242 : 0 : return 0;
243 : : }
244 : : #ifdef CONFIG_KRETPROBES
245 : : static u32 krph_val;
246 : :
247 : 0 : static int entry_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
248 : : {
249 : 0 : krph_val = (rand1 / div_factor);
250 : 0 : return 0;
251 : : }
252 : :
253 : 0 : static int return_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
254 : : {
255 : : unsigned long ret = regs_return_value(regs);
256 : :
257 [ # # ]: 0 : if (ret != (rand1 / div_factor)) {
258 : 0 : handler_errors++;
259 : 0 : printk(KERN_ERR "Kprobe smoke test failed: "
260 : : "incorrect value in kretprobe handler\n");
261 : : }
262 [ # # ]: 0 : if (krph_val == 0) {
263 : 0 : handler_errors++;
264 : 0 : printk(KERN_ERR "Kprobe smoke test failed: "
265 : : "call to kretprobe entry handler failed\n");
266 : : }
267 : :
268 : 0 : krph_val = rand1;
269 : 0 : return 0;
270 : : }
271 : :
272 : : static struct kretprobe rp = {
273 : : .handler = return_handler,
274 : : .entry_handler = entry_handler,
275 : : .kp.symbol_name = "kprobe_target"
276 : : };
277 : :
278 : 0 : static int test_kretprobe(void)
279 : : {
280 : : int ret;
281 : :
282 : 0 : ret = register_kretprobe(&rp);
283 [ # # ]: 0 : if (ret < 0) {
284 : 0 : printk(KERN_ERR "Kprobe smoke test failed: "
285 : : "register_kretprobe returned %d\n", ret);
286 : 0 : return ret;
287 : : }
288 : :
289 : 0 : ret = target(rand1);
290 : 0 : unregister_kretprobe(&rp);
291 [ # # ]: 0 : if (krph_val != rand1) {
292 : 0 : printk(KERN_ERR "Kprobe smoke test failed: "
293 : : "kretprobe handler not called\n");
294 : 0 : handler_errors++;
295 : : }
296 : :
297 : : return 0;
298 : : }
299 : :
300 : 0 : static int return_handler2(struct kretprobe_instance *ri, struct pt_regs *regs)
301 : : {
302 : : unsigned long ret = regs_return_value(regs);
303 : :
304 [ # # ]: 0 : if (ret != (rand1 / div_factor) + 1) {
305 : 0 : handler_errors++;
306 : 0 : printk(KERN_ERR "Kprobe smoke test failed: "
307 : : "incorrect value in kretprobe handler2\n");
308 : : }
309 [ # # ]: 0 : if (krph_val == 0) {
310 : 0 : handler_errors++;
311 : 0 : printk(KERN_ERR "Kprobe smoke test failed: "
312 : : "call to kretprobe entry handler failed\n");
313 : : }
314 : :
315 : 0 : krph_val = rand1;
316 : 0 : return 0;
317 : : }
318 : :
319 : : static struct kretprobe rp2 = {
320 : : .handler = return_handler2,
321 : : .entry_handler = entry_handler,
322 : : .kp.symbol_name = "kprobe_target2"
323 : : };
324 : :
325 : 0 : static int test_kretprobes(void)
326 : : {
327 : : int ret;
328 : 0 : struct kretprobe *rps[2] = {&rp, &rp2};
329 : :
330 : : /* addr and flags should be cleard for reusing kprobe. */
331 : 0 : rp.kp.addr = NULL;
332 : 0 : rp.kp.flags = 0;
333 : 0 : ret = register_kretprobes(rps, 2);
334 [ # # ]: 0 : if (ret < 0) {
335 : 0 : printk(KERN_ERR "Kprobe smoke test failed: "
336 : : "register_kretprobe returned %d\n", ret);
337 : 0 : return ret;
338 : : }
339 : :
340 : 0 : krph_val = 0;
341 : 0 : ret = target(rand1);
342 [ # # ]: 0 : if (krph_val != rand1) {
343 : 0 : printk(KERN_ERR "Kprobe smoke test failed: "
344 : : "kretprobe handler not called\n");
345 : 0 : handler_errors++;
346 : : }
347 : :
348 : 0 : krph_val = 0;
349 : 0 : ret = target2(rand1);
350 [ # # ]: 0 : if (krph_val != rand1) {
351 : 0 : printk(KERN_ERR "Kprobe smoke test failed: "
352 : : "kretprobe handler2 not called\n");
353 : 0 : handler_errors++;
354 : : }
355 : 0 : unregister_kretprobes(rps, 2);
356 : 0 : return 0;
357 : : }
358 : : #endif /* CONFIG_KRETPROBES */
359 : :
360 : 0 : int init_test_probes(void)
361 : : {
362 : : int ret;
363 : :
364 : 0 : target = kprobe_target;
365 : 0 : target2 = kprobe_target2;
366 : :
367 : : do {
368 : 0 : rand1 = prandom_u32();
369 [ # # ]: 0 : } while (rand1 <= div_factor);
370 : :
371 : 0 : printk(KERN_INFO "Kprobe smoke test started\n");
372 : 0 : num_tests++;
373 : 0 : ret = test_kprobe();
374 [ # # ]: 0 : if (ret < 0)
375 : 0 : errors++;
376 : :
377 : 0 : num_tests++;
378 : 0 : ret = test_kprobes();
379 [ # # ]: 0 : if (ret < 0)
380 : 0 : errors++;
381 : :
382 : 0 : num_tests++;
383 : 0 : ret = test_jprobe();
384 [ # # ]: 0 : if (ret < 0)
385 : 0 : errors++;
386 : :
387 : 0 : num_tests++;
388 : 0 : ret = test_jprobes();
389 [ # # ]: 0 : if (ret < 0)
390 : 0 : errors++;
391 : :
392 : : #ifdef CONFIG_KRETPROBES
393 : 0 : num_tests++;
394 : 0 : ret = test_kretprobe();
395 [ # # ]: 0 : if (ret < 0)
396 : 0 : errors++;
397 : :
398 : 0 : num_tests++;
399 : 0 : ret = test_kretprobes();
400 [ # # ]: 0 : if (ret < 0)
401 : 0 : errors++;
402 : : #endif /* CONFIG_KRETPROBES */
403 : :
404 [ # # ]: 0 : if (errors)
405 : 0 : printk(KERN_ERR "BUG: Kprobe smoke test: %d out of "
406 : : "%d tests failed\n", errors, num_tests);
407 [ # # ]: 0 : else if (handler_errors)
408 : 0 : printk(KERN_ERR "BUG: Kprobe smoke test: %d error(s) "
409 : : "running handlers\n", handler_errors);
410 : : else
411 : 0 : printk(KERN_INFO "Kprobe smoke test passed successfully\n");
412 : :
413 : 0 : return 0;
414 : : }
|