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