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