Blame view

kernel/test_kprobes.c 7.37 KB
8c1c93564   Ananth N Mavinakayanahalli   x86: kprobes: add...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
  /*
   * test_kprobes.c - simple sanity test for *probes
   *
   * Copyright IBM Corp. 2008
   *
   * This program is free software;  you can redistribute it and/or modify
   * it under the terms of the GNU General Public License as published by
   * the Free Software Foundation; either version 2 of the License, or
   * (at your option) any later version.
   *
   * This program is distributed in the hope that it would be useful, but
   * WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
   * the GNU General Public License for more details.
   */
4878b14b4   Fabian Frederick   kernel/test_kprob...
16
  #define pr_fmt(fmt) "Kprobe smoke test: " fmt
8c1c93564   Ananth N Mavinakayanahalli   x86: kprobes: add...
17
18
19
20
21
22
23
24
  #include <linux/kernel.h>
  #include <linux/kprobes.h>
  #include <linux/random.h>
  
  #define div_factor 3
  
  static u32 rand1, preh_val, posth_val, jph_val;
  static int errors, handler_errors, num_tests;
8e1144050   Masami Hiramatsu   kprobes: indirect...
25
  static u32 (*target)(u32 value);
12da3b888   Masami Hiramatsu   kprobes: add test...
26
  static u32 (*target2)(u32 value);
8c1c93564   Ananth N Mavinakayanahalli   x86: kprobes: add...
27
28
29
  
  static noinline u32 kprobe_target(u32 value)
  {
8c1c93564   Ananth N Mavinakayanahalli   x86: kprobes: add...
30
31
32
33
34
35
36
37
38
39
40
41
42
43
  	return (value / div_factor);
  }
  
  static int kp_pre_handler(struct kprobe *p, struct pt_regs *regs)
  {
  	preh_val = (rand1 / div_factor);
  	return 0;
  }
  
  static void kp_post_handler(struct kprobe *p, struct pt_regs *regs,
  		unsigned long flags)
  {
  	if (preh_val != (rand1 / div_factor)) {
  		handler_errors++;
4878b14b4   Fabian Frederick   kernel/test_kprob...
44
45
  		pr_err("incorrect value in post_handler
  ");
8c1c93564   Ananth N Mavinakayanahalli   x86: kprobes: add...
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
  	}
  	posth_val = preh_val + div_factor;
  }
  
  static struct kprobe kp = {
  	.symbol_name = "kprobe_target",
  	.pre_handler = kp_pre_handler,
  	.post_handler = kp_post_handler
  };
  
  static int test_kprobe(void)
  {
  	int ret;
  
  	ret = register_kprobe(&kp);
  	if (ret < 0) {
4878b14b4   Fabian Frederick   kernel/test_kprob...
62
63
  		pr_err("register_kprobe returned %d
  ", ret);
8c1c93564   Ananth N Mavinakayanahalli   x86: kprobes: add...
64
65
  		return ret;
  	}
8e1144050   Masami Hiramatsu   kprobes: indirect...
66
  	ret = target(rand1);
8c1c93564   Ananth N Mavinakayanahalli   x86: kprobes: add...
67
68
69
  	unregister_kprobe(&kp);
  
  	if (preh_val == 0) {
4878b14b4   Fabian Frederick   kernel/test_kprob...
70
71
  		pr_err("kprobe pre_handler not called
  ");
8c1c93564   Ananth N Mavinakayanahalli   x86: kprobes: add...
72
73
74
75
  		handler_errors++;
  	}
  
  	if (posth_val == 0) {
4878b14b4   Fabian Frederick   kernel/test_kprob...
76
77
  		pr_err("kprobe post_handler not called
  ");
8c1c93564   Ananth N Mavinakayanahalli   x86: kprobes: add...
78
79
80
81
82
  		handler_errors++;
  	}
  
  	return 0;
  }
12da3b888   Masami Hiramatsu   kprobes: add test...
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
  static noinline u32 kprobe_target2(u32 value)
  {
  	return (value / div_factor) + 1;
  }
  
  static int kp_pre_handler2(struct kprobe *p, struct pt_regs *regs)
  {
  	preh_val = (rand1 / div_factor) + 1;
  	return 0;
  }
  
  static void kp_post_handler2(struct kprobe *p, struct pt_regs *regs,
  		unsigned long flags)
  {
  	if (preh_val != (rand1 / div_factor) + 1) {
  		handler_errors++;
4878b14b4   Fabian Frederick   kernel/test_kprob...
99
100
  		pr_err("incorrect value in post_handler2
  ");
12da3b888   Masami Hiramatsu   kprobes: add test...
101
102
103
104
105
106
107
108
109
110
111
112
113
114
  	}
  	posth_val = preh_val + div_factor;
  }
  
  static struct kprobe kp2 = {
  	.symbol_name = "kprobe_target2",
  	.pre_handler = kp_pre_handler2,
  	.post_handler = kp_post_handler2
  };
  
  static int test_kprobes(void)
  {
  	int ret;
  	struct kprobe *kps[2] = {&kp, &kp2};
fd02e6f7a   Masami Hiramatsu   kprobes: Fix self...
115
116
117
  	/* addr and flags should be cleard for reusing kprobe. */
  	kp.addr = NULL;
  	kp.flags = 0;
12da3b888   Masami Hiramatsu   kprobes: add test...
118
119
  	ret = register_kprobes(kps, 2);
  	if (ret < 0) {
4878b14b4   Fabian Frederick   kernel/test_kprob...
120
121
  		pr_err("register_kprobes returned %d
  ", ret);
12da3b888   Masami Hiramatsu   kprobes: add test...
122
123
124
125
126
127
128
129
  		return ret;
  	}
  
  	preh_val = 0;
  	posth_val = 0;
  	ret = target(rand1);
  
  	if (preh_val == 0) {
4878b14b4   Fabian Frederick   kernel/test_kprob...
130
131
  		pr_err("kprobe pre_handler not called
  ");
12da3b888   Masami Hiramatsu   kprobes: add test...
132
133
134
135
  		handler_errors++;
  	}
  
  	if (posth_val == 0) {
4878b14b4   Fabian Frederick   kernel/test_kprob...
136
137
  		pr_err("kprobe post_handler not called
  ");
12da3b888   Masami Hiramatsu   kprobes: add test...
138
139
140
141
142
143
144
145
  		handler_errors++;
  	}
  
  	preh_val = 0;
  	posth_val = 0;
  	ret = target2(rand1);
  
  	if (preh_val == 0) {
4878b14b4   Fabian Frederick   kernel/test_kprob...
146
147
  		pr_err("kprobe pre_handler2 not called
  ");
12da3b888   Masami Hiramatsu   kprobes: add test...
148
149
150
151
  		handler_errors++;
  	}
  
  	if (posth_val == 0) {
4878b14b4   Fabian Frederick   kernel/test_kprob...
152
153
  		pr_err("kprobe post_handler2 not called
  ");
12da3b888   Masami Hiramatsu   kprobes: add test...
154
155
156
157
158
159
160
  		handler_errors++;
  	}
  
  	unregister_kprobes(kps, 2);
  	return 0;
  
  }
8c1c93564   Ananth N Mavinakayanahalli   x86: kprobes: add...
161
162
163
164
  static u32 j_kprobe_target(u32 value)
  {
  	if (value != rand1) {
  		handler_errors++;
4878b14b4   Fabian Frederick   kernel/test_kprob...
165
166
  		pr_err("incorrect value in jprobe handler
  ");
8c1c93564   Ananth N Mavinakayanahalli   x86: kprobes: add...
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
  	}
  
  	jph_val = rand1;
  	jprobe_return();
  	return 0;
  }
  
  static struct jprobe jp = {
  	.entry		= j_kprobe_target,
  	.kp.symbol_name = "kprobe_target"
  };
  
  static int test_jprobe(void)
  {
  	int ret;
  
  	ret = register_jprobe(&jp);
  	if (ret < 0) {
4878b14b4   Fabian Frederick   kernel/test_kprob...
185
186
  		pr_err("register_jprobe returned %d
  ", ret);
8c1c93564   Ananth N Mavinakayanahalli   x86: kprobes: add...
187
188
  		return ret;
  	}
8e1144050   Masami Hiramatsu   kprobes: indirect...
189
  	ret = target(rand1);
8c1c93564   Ananth N Mavinakayanahalli   x86: kprobes: add...
190
191
  	unregister_jprobe(&jp);
  	if (jph_val == 0) {
4878b14b4   Fabian Frederick   kernel/test_kprob...
192
193
  		pr_err("jprobe handler not called
  ");
8c1c93564   Ananth N Mavinakayanahalli   x86: kprobes: add...
194
195
196
197
198
  		handler_errors++;
  	}
  
  	return 0;
  }
12da3b888   Masami Hiramatsu   kprobes: add test...
199
200
201
202
203
204
205
206
207
  static struct jprobe jp2 = {
  	.entry          = j_kprobe_target,
  	.kp.symbol_name = "kprobe_target2"
  };
  
  static int test_jprobes(void)
  {
  	int ret;
  	struct jprobe *jps[2] = {&jp, &jp2};
fd02e6f7a   Masami Hiramatsu   kprobes: Fix self...
208
209
210
  	/* addr and flags should be cleard for reusing kprobe. */
  	jp.kp.addr = NULL;
  	jp.kp.flags = 0;
12da3b888   Masami Hiramatsu   kprobes: add test...
211
212
  	ret = register_jprobes(jps, 2);
  	if (ret < 0) {
4878b14b4   Fabian Frederick   kernel/test_kprob...
213
214
  		pr_err("register_jprobes returned %d
  ", ret);
12da3b888   Masami Hiramatsu   kprobes: add test...
215
216
217
218
219
220
  		return ret;
  	}
  
  	jph_val = 0;
  	ret = target(rand1);
  	if (jph_val == 0) {
4878b14b4   Fabian Frederick   kernel/test_kprob...
221
222
  		pr_err("jprobe handler not called
  ");
12da3b888   Masami Hiramatsu   kprobes: add test...
223
224
225
226
227
228
  		handler_errors++;
  	}
  
  	jph_val = 0;
  	ret = target2(rand1);
  	if (jph_val == 0) {
4878b14b4   Fabian Frederick   kernel/test_kprob...
229
230
  		pr_err("jprobe handler2 not called
  ");
12da3b888   Masami Hiramatsu   kprobes: add test...
231
232
233
234
235
236
  		handler_errors++;
  	}
  	unregister_jprobes(jps, 2);
  
  	return 0;
  }
8c1c93564   Ananth N Mavinakayanahalli   x86: kprobes: add...
237
238
  #ifdef CONFIG_KRETPROBES
  static u32 krph_val;
f47cd9b55   Abhishek Sagar   kprobes: kretprob...
239
240
241
242
243
  static int entry_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
  {
  	krph_val = (rand1 / div_factor);
  	return 0;
  }
8c1c93564   Ananth N Mavinakayanahalli   x86: kprobes: add...
244
245
246
247
248
249
  static int return_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
  {
  	unsigned long ret = regs_return_value(regs);
  
  	if (ret != (rand1 / div_factor)) {
  		handler_errors++;
4878b14b4   Fabian Frederick   kernel/test_kprob...
250
251
  		pr_err("incorrect value in kretprobe handler
  ");
8c1c93564   Ananth N Mavinakayanahalli   x86: kprobes: add...
252
  	}
f47cd9b55   Abhishek Sagar   kprobes: kretprob...
253
254
  	if (krph_val == 0) {
  		handler_errors++;
4878b14b4   Fabian Frederick   kernel/test_kprob...
255
256
  		pr_err("call to kretprobe entry handler failed
  ");
f47cd9b55   Abhishek Sagar   kprobes: kretprob...
257
  	}
8c1c93564   Ananth N Mavinakayanahalli   x86: kprobes: add...
258

f47cd9b55   Abhishek Sagar   kprobes: kretprob...
259
  	krph_val = rand1;
8c1c93564   Ananth N Mavinakayanahalli   x86: kprobes: add...
260
261
262
263
264
  	return 0;
  }
  
  static struct kretprobe rp = {
  	.handler	= return_handler,
f47cd9b55   Abhishek Sagar   kprobes: kretprob...
265
  	.entry_handler  = entry_handler,
8c1c93564   Ananth N Mavinakayanahalli   x86: kprobes: add...
266
267
268
269
270
271
272
273
274
  	.kp.symbol_name = "kprobe_target"
  };
  
  static int test_kretprobe(void)
  {
  	int ret;
  
  	ret = register_kretprobe(&rp);
  	if (ret < 0) {
4878b14b4   Fabian Frederick   kernel/test_kprob...
275
276
  		pr_err("register_kretprobe returned %d
  ", ret);
8c1c93564   Ananth N Mavinakayanahalli   x86: kprobes: add...
277
278
  		return ret;
  	}
8e1144050   Masami Hiramatsu   kprobes: indirect...
279
  	ret = target(rand1);
8c1c93564   Ananth N Mavinakayanahalli   x86: kprobes: add...
280
  	unregister_kretprobe(&rp);
f47cd9b55   Abhishek Sagar   kprobes: kretprob...
281
  	if (krph_val != rand1) {
4878b14b4   Fabian Frederick   kernel/test_kprob...
282
283
  		pr_err("kretprobe handler not called
  ");
8c1c93564   Ananth N Mavinakayanahalli   x86: kprobes: add...
284
285
286
287
288
  		handler_errors++;
  	}
  
  	return 0;
  }
12da3b888   Masami Hiramatsu   kprobes: add test...
289
290
291
292
293
294
295
  
  static int return_handler2(struct kretprobe_instance *ri, struct pt_regs *regs)
  {
  	unsigned long ret = regs_return_value(regs);
  
  	if (ret != (rand1 / div_factor) + 1) {
  		handler_errors++;
4878b14b4   Fabian Frederick   kernel/test_kprob...
296
297
  		pr_err("incorrect value in kretprobe handler2
  ");
12da3b888   Masami Hiramatsu   kprobes: add test...
298
299
300
  	}
  	if (krph_val == 0) {
  		handler_errors++;
4878b14b4   Fabian Frederick   kernel/test_kprob...
301
302
  		pr_err("call to kretprobe entry handler failed
  ");
12da3b888   Masami Hiramatsu   kprobes: add test...
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
  	}
  
  	krph_val = rand1;
  	return 0;
  }
  
  static struct kretprobe rp2 = {
  	.handler	= return_handler2,
  	.entry_handler  = entry_handler,
  	.kp.symbol_name = "kprobe_target2"
  };
  
  static int test_kretprobes(void)
  {
  	int ret;
  	struct kretprobe *rps[2] = {&rp, &rp2};
fd02e6f7a   Masami Hiramatsu   kprobes: Fix self...
319
320
321
  	/* addr and flags should be cleard for reusing kprobe. */
  	rp.kp.addr = NULL;
  	rp.kp.flags = 0;
12da3b888   Masami Hiramatsu   kprobes: add test...
322
323
  	ret = register_kretprobes(rps, 2);
  	if (ret < 0) {
4878b14b4   Fabian Frederick   kernel/test_kprob...
324
325
  		pr_err("register_kretprobe returned %d
  ", ret);
12da3b888   Masami Hiramatsu   kprobes: add test...
326
327
328
329
330
331
  		return ret;
  	}
  
  	krph_val = 0;
  	ret = target(rand1);
  	if (krph_val != rand1) {
4878b14b4   Fabian Frederick   kernel/test_kprob...
332
333
  		pr_err("kretprobe handler not called
  ");
12da3b888   Masami Hiramatsu   kprobes: add test...
334
335
336
337
338
339
  		handler_errors++;
  	}
  
  	krph_val = 0;
  	ret = target2(rand1);
  	if (krph_val != rand1) {
4878b14b4   Fabian Frederick   kernel/test_kprob...
340
341
  		pr_err("kretprobe handler2 not called
  ");
12da3b888   Masami Hiramatsu   kprobes: add test...
342
343
344
345
346
  		handler_errors++;
  	}
  	unregister_kretprobes(rps, 2);
  	return 0;
  }
8c1c93564   Ananth N Mavinakayanahalli   x86: kprobes: add...
347
348
349
350
351
  #endif /* CONFIG_KRETPROBES */
  
  int init_test_probes(void)
  {
  	int ret;
8e1144050   Masami Hiramatsu   kprobes: indirect...
352
  	target = kprobe_target;
12da3b888   Masami Hiramatsu   kprobes: add test...
353
  	target2 = kprobe_target2;
8e1144050   Masami Hiramatsu   kprobes: indirect...
354

8c1c93564   Ananth N Mavinakayanahalli   x86: kprobes: add...
355
  	do {
6d65df332   Akinobu Mita   kernel/: rename r...
356
  		rand1 = prandom_u32();
8c1c93564   Ananth N Mavinakayanahalli   x86: kprobes: add...
357
  	} while (rand1 <= div_factor);
4878b14b4   Fabian Frederick   kernel/test_kprob...
358
359
  	pr_info("started
  ");
8c1c93564   Ananth N Mavinakayanahalli   x86: kprobes: add...
360
361
362
363
364
365
  	num_tests++;
  	ret = test_kprobe();
  	if (ret < 0)
  		errors++;
  
  	num_tests++;
12da3b888   Masami Hiramatsu   kprobes: add test...
366
367
368
369
370
  	ret = test_kprobes();
  	if (ret < 0)
  		errors++;
  
  	num_tests++;
8c1c93564   Ananth N Mavinakayanahalli   x86: kprobes: add...
371
372
373
  	ret = test_jprobe();
  	if (ret < 0)
  		errors++;
12da3b888   Masami Hiramatsu   kprobes: add test...
374
375
376
377
  	num_tests++;
  	ret = test_jprobes();
  	if (ret < 0)
  		errors++;
8c1c93564   Ananth N Mavinakayanahalli   x86: kprobes: add...
378
379
380
381
382
  #ifdef CONFIG_KRETPROBES
  	num_tests++;
  	ret = test_kretprobe();
  	if (ret < 0)
  		errors++;
12da3b888   Masami Hiramatsu   kprobes: add test...
383
384
385
386
387
  
  	num_tests++;
  	ret = test_kretprobes();
  	if (ret < 0)
  		errors++;
8c1c93564   Ananth N Mavinakayanahalli   x86: kprobes: add...
388
389
390
  #endif /* CONFIG_KRETPROBES */
  
  	if (errors)
4878b14b4   Fabian Frederick   kernel/test_kprob...
391
392
  		pr_err("BUG: %d out of %d tests failed
  ", errors, num_tests);
8c1c93564   Ananth N Mavinakayanahalli   x86: kprobes: add...
393
  	else if (handler_errors)
4878b14b4   Fabian Frederick   kernel/test_kprob...
394
395
  		pr_err("BUG: %d error(s) running handlers
  ", handler_errors);
8c1c93564   Ananth N Mavinakayanahalli   x86: kprobes: add...
396
  	else
4878b14b4   Fabian Frederick   kernel/test_kprob...
397
398
  		pr_info("passed successfully
  ");
8c1c93564   Ananth N Mavinakayanahalli   x86: kprobes: add...
399
400
401
  
  	return 0;
  }