Blame view

kernel/test_kprobes.c 6.36 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
  #include <linux/kernel.h>
  #include <linux/kprobes.h>
  #include <linux/random.h>
  
  #define div_factor 3
2c7d662e2   Masami Hiramatsu   kprobes: Disable ...
22
  static u32 rand1, preh_val, posth_val;
8c1c93564   Ananth N Mavinakayanahalli   x86: kprobes: add...
23
  static int errors, handler_errors, num_tests;
8e1144050   Masami Hiramatsu   kprobes: indirect...
24
  static u32 (*target)(u32 value);
12da3b888   Masami Hiramatsu   kprobes: add test...
25
  static u32 (*target2)(u32 value);
8c1c93564   Ananth N Mavinakayanahalli   x86: kprobes: add...
26
27
28
  
  static noinline u32 kprobe_target(u32 value)
  {
8c1c93564   Ananth N Mavinakayanahalli   x86: kprobes: add...
29
30
31
32
33
  	return (value / div_factor);
  }
  
  static int kp_pre_handler(struct kprobe *p, struct pt_regs *regs)
  {
3539d0915   Masami Hiramatsu   kprobes: Improve ...
34
35
36
37
38
  	if (preemptible()) {
  		handler_errors++;
  		pr_err("pre-handler is preemptible
  ");
  	}
8c1c93564   Ananth N Mavinakayanahalli   x86: kprobes: add...
39
40
41
42
43
44
45
  	preh_val = (rand1 / div_factor);
  	return 0;
  }
  
  static void kp_post_handler(struct kprobe *p, struct pt_regs *regs,
  		unsigned long flags)
  {
3539d0915   Masami Hiramatsu   kprobes: Improve ...
46
47
48
49
50
  	if (preemptible()) {
  		handler_errors++;
  		pr_err("post-handler is preemptible
  ");
  	}
8c1c93564   Ananth N Mavinakayanahalli   x86: kprobes: add...
51
52
  	if (preh_val != (rand1 / div_factor)) {
  		handler_errors++;
4878b14b4   Fabian Frederick   kernel/test_kprob...
53
54
  		pr_err("incorrect value in post_handler
  ");
8c1c93564   Ananth N Mavinakayanahalli   x86: kprobes: add...
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
  	}
  	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...
71
72
  		pr_err("register_kprobe returned %d
  ", ret);
8c1c93564   Ananth N Mavinakayanahalli   x86: kprobes: add...
73
74
  		return ret;
  	}
8e1144050   Masami Hiramatsu   kprobes: indirect...
75
  	ret = target(rand1);
8c1c93564   Ananth N Mavinakayanahalli   x86: kprobes: add...
76
77
78
  	unregister_kprobe(&kp);
  
  	if (preh_val == 0) {
4878b14b4   Fabian Frederick   kernel/test_kprob...
79
80
  		pr_err("kprobe pre_handler not called
  ");
8c1c93564   Ananth N Mavinakayanahalli   x86: kprobes: add...
81
82
83
84
  		handler_errors++;
  	}
  
  	if (posth_val == 0) {
4878b14b4   Fabian Frederick   kernel/test_kprob...
85
86
  		pr_err("kprobe post_handler not called
  ");
8c1c93564   Ananth N Mavinakayanahalli   x86: kprobes: add...
87
88
89
90
91
  		handler_errors++;
  	}
  
  	return 0;
  }
12da3b888   Masami Hiramatsu   kprobes: add test...
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
  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...
108
109
  		pr_err("incorrect value in post_handler2
  ");
12da3b888   Masami Hiramatsu   kprobes: add test...
110
111
112
113
114
115
116
117
118
119
120
121
122
123
  	}
  	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...
124
125
126
  	/* addr and flags should be cleard for reusing kprobe. */
  	kp.addr = NULL;
  	kp.flags = 0;
12da3b888   Masami Hiramatsu   kprobes: add test...
127
128
  	ret = register_kprobes(kps, 2);
  	if (ret < 0) {
4878b14b4   Fabian Frederick   kernel/test_kprob...
129
130
  		pr_err("register_kprobes returned %d
  ", ret);
12da3b888   Masami Hiramatsu   kprobes: add test...
131
132
133
134
135
136
137
138
  		return ret;
  	}
  
  	preh_val = 0;
  	posth_val = 0;
  	ret = target(rand1);
  
  	if (preh_val == 0) {
4878b14b4   Fabian Frederick   kernel/test_kprob...
139
140
  		pr_err("kprobe pre_handler not called
  ");
12da3b888   Masami Hiramatsu   kprobes: add test...
141
142
143
144
  		handler_errors++;
  	}
  
  	if (posth_val == 0) {
4878b14b4   Fabian Frederick   kernel/test_kprob...
145
146
  		pr_err("kprobe post_handler not called
  ");
12da3b888   Masami Hiramatsu   kprobes: add test...
147
148
149
150
151
152
153
154
  		handler_errors++;
  	}
  
  	preh_val = 0;
  	posth_val = 0;
  	ret = target2(rand1);
  
  	if (preh_val == 0) {
4878b14b4   Fabian Frederick   kernel/test_kprob...
155
156
  		pr_err("kprobe pre_handler2 not called
  ");
12da3b888   Masami Hiramatsu   kprobes: add test...
157
158
159
160
  		handler_errors++;
  	}
  
  	if (posth_val == 0) {
4878b14b4   Fabian Frederick   kernel/test_kprob...
161
162
  		pr_err("kprobe post_handler2 not called
  ");
12da3b888   Masami Hiramatsu   kprobes: add test...
163
164
165
166
167
168
169
  		handler_errors++;
  	}
  
  	unregister_kprobes(kps, 2);
  	return 0;
  
  }
8c1c93564   Ananth N Mavinakayanahalli   x86: kprobes: add...
170
171
  #ifdef CONFIG_KRETPROBES
  static u32 krph_val;
f47cd9b55   Abhishek Sagar   kprobes: kretprob...
172
173
  static int entry_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
  {
3539d0915   Masami Hiramatsu   kprobes: Improve ...
174
175
176
177
178
  	if (preemptible()) {
  		handler_errors++;
  		pr_err("kretprobe entry handler is preemptible
  ");
  	}
f47cd9b55   Abhishek Sagar   kprobes: kretprob...
179
180
181
  	krph_val = (rand1 / div_factor);
  	return 0;
  }
8c1c93564   Ananth N Mavinakayanahalli   x86: kprobes: add...
182
183
184
  static int return_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
  {
  	unsigned long ret = regs_return_value(regs);
3539d0915   Masami Hiramatsu   kprobes: Improve ...
185
186
187
188
189
  	if (preemptible()) {
  		handler_errors++;
  		pr_err("kretprobe return handler is preemptible
  ");
  	}
8c1c93564   Ananth N Mavinakayanahalli   x86: kprobes: add...
190
191
  	if (ret != (rand1 / div_factor)) {
  		handler_errors++;
4878b14b4   Fabian Frederick   kernel/test_kprob...
192
193
  		pr_err("incorrect value in kretprobe handler
  ");
8c1c93564   Ananth N Mavinakayanahalli   x86: kprobes: add...
194
  	}
f47cd9b55   Abhishek Sagar   kprobes: kretprob...
195
196
  	if (krph_val == 0) {
  		handler_errors++;
4878b14b4   Fabian Frederick   kernel/test_kprob...
197
198
  		pr_err("call to kretprobe entry handler failed
  ");
f47cd9b55   Abhishek Sagar   kprobes: kretprob...
199
  	}
8c1c93564   Ananth N Mavinakayanahalli   x86: kprobes: add...
200

f47cd9b55   Abhishek Sagar   kprobes: kretprob...
201
  	krph_val = rand1;
8c1c93564   Ananth N Mavinakayanahalli   x86: kprobes: add...
202
203
204
205
206
  	return 0;
  }
  
  static struct kretprobe rp = {
  	.handler	= return_handler,
f47cd9b55   Abhishek Sagar   kprobes: kretprob...
207
  	.entry_handler  = entry_handler,
8c1c93564   Ananth N Mavinakayanahalli   x86: kprobes: add...
208
209
210
211
212
213
214
215
216
  	.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...
217
218
  		pr_err("register_kretprobe returned %d
  ", ret);
8c1c93564   Ananth N Mavinakayanahalli   x86: kprobes: add...
219
220
  		return ret;
  	}
8e1144050   Masami Hiramatsu   kprobes: indirect...
221
  	ret = target(rand1);
8c1c93564   Ananth N Mavinakayanahalli   x86: kprobes: add...
222
  	unregister_kretprobe(&rp);
f47cd9b55   Abhishek Sagar   kprobes: kretprob...
223
  	if (krph_val != rand1) {
4878b14b4   Fabian Frederick   kernel/test_kprob...
224
225
  		pr_err("kretprobe handler not called
  ");
8c1c93564   Ananth N Mavinakayanahalli   x86: kprobes: add...
226
227
228
229
230
  		handler_errors++;
  	}
  
  	return 0;
  }
12da3b888   Masami Hiramatsu   kprobes: add test...
231
232
233
234
235
236
237
  
  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...
238
239
  		pr_err("incorrect value in kretprobe handler2
  ");
12da3b888   Masami Hiramatsu   kprobes: add test...
240
241
242
  	}
  	if (krph_val == 0) {
  		handler_errors++;
4878b14b4   Fabian Frederick   kernel/test_kprob...
243
244
  		pr_err("call to kretprobe entry handler failed
  ");
12da3b888   Masami Hiramatsu   kprobes: add test...
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
  	}
  
  	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...
261
262
263
  	/* addr and flags should be cleard for reusing kprobe. */
  	rp.kp.addr = NULL;
  	rp.kp.flags = 0;
12da3b888   Masami Hiramatsu   kprobes: add test...
264
265
  	ret = register_kretprobes(rps, 2);
  	if (ret < 0) {
4878b14b4   Fabian Frederick   kernel/test_kprob...
266
267
  		pr_err("register_kretprobe returned %d
  ", ret);
12da3b888   Masami Hiramatsu   kprobes: add test...
268
269
270
271
272
273
  		return ret;
  	}
  
  	krph_val = 0;
  	ret = target(rand1);
  	if (krph_val != rand1) {
4878b14b4   Fabian Frederick   kernel/test_kprob...
274
275
  		pr_err("kretprobe handler not called
  ");
12da3b888   Masami Hiramatsu   kprobes: add test...
276
277
278
279
280
281
  		handler_errors++;
  	}
  
  	krph_val = 0;
  	ret = target2(rand1);
  	if (krph_val != rand1) {
4878b14b4   Fabian Frederick   kernel/test_kprob...
282
283
  		pr_err("kretprobe handler2 not called
  ");
12da3b888   Masami Hiramatsu   kprobes: add test...
284
285
286
287
288
  		handler_errors++;
  	}
  	unregister_kretprobes(rps, 2);
  	return 0;
  }
8c1c93564   Ananth N Mavinakayanahalli   x86: kprobes: add...
289
290
291
292
293
  #endif /* CONFIG_KRETPROBES */
  
  int init_test_probes(void)
  {
  	int ret;
8e1144050   Masami Hiramatsu   kprobes: indirect...
294
  	target = kprobe_target;
12da3b888   Masami Hiramatsu   kprobes: add test...
295
  	target2 = kprobe_target2;
8e1144050   Masami Hiramatsu   kprobes: indirect...
296

8c1c93564   Ananth N Mavinakayanahalli   x86: kprobes: add...
297
  	do {
6d65df332   Akinobu Mita   kernel/: rename r...
298
  		rand1 = prandom_u32();
8c1c93564   Ananth N Mavinakayanahalli   x86: kprobes: add...
299
  	} while (rand1 <= div_factor);
4878b14b4   Fabian Frederick   kernel/test_kprob...
300
301
  	pr_info("started
  ");
8c1c93564   Ananth N Mavinakayanahalli   x86: kprobes: add...
302
303
304
305
306
307
  	num_tests++;
  	ret = test_kprobe();
  	if (ret < 0)
  		errors++;
  
  	num_tests++;
12da3b888   Masami Hiramatsu   kprobes: add test...
308
309
310
  	ret = test_kprobes();
  	if (ret < 0)
  		errors++;
8c1c93564   Ananth N Mavinakayanahalli   x86: kprobes: add...
311
312
313
314
315
  #ifdef CONFIG_KRETPROBES
  	num_tests++;
  	ret = test_kretprobe();
  	if (ret < 0)
  		errors++;
12da3b888   Masami Hiramatsu   kprobes: add test...
316
317
318
319
320
  
  	num_tests++;
  	ret = test_kretprobes();
  	if (ret < 0)
  		errors++;
8c1c93564   Ananth N Mavinakayanahalli   x86: kprobes: add...
321
322
323
  #endif /* CONFIG_KRETPROBES */
  
  	if (errors)
4878b14b4   Fabian Frederick   kernel/test_kprob...
324
325
  		pr_err("BUG: %d out of %d tests failed
  ", errors, num_tests);
8c1c93564   Ananth N Mavinakayanahalli   x86: kprobes: add...
326
  	else if (handler_errors)
4878b14b4   Fabian Frederick   kernel/test_kprob...
327
328
  		pr_err("BUG: %d error(s) running handlers
  ", handler_errors);
8c1c93564   Ananth N Mavinakayanahalli   x86: kprobes: add...
329
  	else
4878b14b4   Fabian Frederick   kernel/test_kprob...
330
331
  		pr_info("passed successfully
  ");
8c1c93564   Ananth N Mavinakayanahalli   x86: kprobes: add...
332
333
334
  
  	return 0;
  }