blob: 9c0127ead6abe6986de7a374bd7e332a3584df17 [file] [log] [blame]
Ananth N Mavinakayanahalli8c1c9352008-01-30 13:32:53 +01001/*
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
23static u32 rand1, preh_val, posth_val, jph_val;
24static int errors, handler_errors, num_tests;
Masami Hiramatsu8e114402009-01-06 14:41:47 -080025static u32 (*target)(u32 value);
Ananth N Mavinakayanahalli8c1c9352008-01-30 13:32:53 +010026
27static noinline u32 kprobe_target(u32 value)
28{
Ananth N Mavinakayanahalli8c1c9352008-01-30 13:32:53 +010029 return (value / div_factor);
30}
31
32static int kp_pre_handler(struct kprobe *p, struct pt_regs *regs)
33{
34 preh_val = (rand1 / div_factor);
35 return 0;
36}
37
38static void kp_post_handler(struct kprobe *p, struct pt_regs *regs,
39 unsigned long flags)
40{
41 if (preh_val != (rand1 / div_factor)) {
42 handler_errors++;
43 printk(KERN_ERR "Kprobe smoke test failed: "
44 "incorrect value in post_handler\n");
45 }
46 posth_val = preh_val + div_factor;
47}
48
49static struct kprobe kp = {
50 .symbol_name = "kprobe_target",
51 .pre_handler = kp_pre_handler,
52 .post_handler = kp_post_handler
53};
54
55static int test_kprobe(void)
56{
57 int ret;
58
59 ret = register_kprobe(&kp);
60 if (ret < 0) {
61 printk(KERN_ERR "Kprobe smoke test failed: "
62 "register_kprobe returned %d\n", ret);
63 return ret;
64 }
65
Masami Hiramatsu8e114402009-01-06 14:41:47 -080066 ret = target(rand1);
Ananth N Mavinakayanahalli8c1c9352008-01-30 13:32:53 +010067 unregister_kprobe(&kp);
68
69 if (preh_val == 0) {
70 printk(KERN_ERR "Kprobe smoke test failed: "
71 "kprobe pre_handler not called\n");
72 handler_errors++;
73 }
74
75 if (posth_val == 0) {
76 printk(KERN_ERR "Kprobe smoke test failed: "
77 "kprobe post_handler not called\n");
78 handler_errors++;
79 }
80
81 return 0;
82}
83
84static u32 j_kprobe_target(u32 value)
85{
86 if (value != rand1) {
87 handler_errors++;
88 printk(KERN_ERR "Kprobe smoke test failed: "
89 "incorrect value in jprobe handler\n");
90 }
91
92 jph_val = rand1;
93 jprobe_return();
94 return 0;
95}
96
97static struct jprobe jp = {
98 .entry = j_kprobe_target,
99 .kp.symbol_name = "kprobe_target"
100};
101
102static int test_jprobe(void)
103{
104 int ret;
105
106 ret = register_jprobe(&jp);
107 if (ret < 0) {
108 printk(KERN_ERR "Kprobe smoke test failed: "
109 "register_jprobe returned %d\n", ret);
110 return ret;
111 }
112
Masami Hiramatsu8e114402009-01-06 14:41:47 -0800113 ret = target(rand1);
Ananth N Mavinakayanahalli8c1c9352008-01-30 13:32:53 +0100114 unregister_jprobe(&jp);
115 if (jph_val == 0) {
116 printk(KERN_ERR "Kprobe smoke test failed: "
117 "jprobe handler not called\n");
118 handler_errors++;
119 }
120
121 return 0;
122}
123
124#ifdef CONFIG_KRETPROBES
125static u32 krph_val;
126
Abhishek Sagarf47cd9b2008-02-06 01:38:22 -0800127static int entry_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
128{
129 krph_val = (rand1 / div_factor);
130 return 0;
131}
132
Ananth N Mavinakayanahalli8c1c9352008-01-30 13:32:53 +0100133static int return_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
134{
135 unsigned long ret = regs_return_value(regs);
136
137 if (ret != (rand1 / div_factor)) {
138 handler_errors++;
139 printk(KERN_ERR "Kprobe smoke test failed: "
140 "incorrect value in kretprobe handler\n");
141 }
Abhishek Sagarf47cd9b2008-02-06 01:38:22 -0800142 if (krph_val == 0) {
143 handler_errors++;
144 printk(KERN_ERR "Kprobe smoke test failed: "
145 "call to kretprobe entry handler failed\n");
146 }
Ananth N Mavinakayanahalli8c1c9352008-01-30 13:32:53 +0100147
Abhishek Sagarf47cd9b2008-02-06 01:38:22 -0800148 krph_val = rand1;
Ananth N Mavinakayanahalli8c1c9352008-01-30 13:32:53 +0100149 return 0;
150}
151
152static struct kretprobe rp = {
153 .handler = return_handler,
Abhishek Sagarf47cd9b2008-02-06 01:38:22 -0800154 .entry_handler = entry_handler,
Ananth N Mavinakayanahalli8c1c9352008-01-30 13:32:53 +0100155 .kp.symbol_name = "kprobe_target"
156};
157
158static int test_kretprobe(void)
159{
160 int ret;
161
162 ret = register_kretprobe(&rp);
163 if (ret < 0) {
164 printk(KERN_ERR "Kprobe smoke test failed: "
165 "register_kretprobe returned %d\n", ret);
166 return ret;
167 }
168
Masami Hiramatsu8e114402009-01-06 14:41:47 -0800169 ret = target(rand1);
Ananth N Mavinakayanahalli8c1c9352008-01-30 13:32:53 +0100170 unregister_kretprobe(&rp);
Abhishek Sagarf47cd9b2008-02-06 01:38:22 -0800171 if (krph_val != rand1) {
Ananth N Mavinakayanahalli8c1c9352008-01-30 13:32:53 +0100172 printk(KERN_ERR "Kprobe smoke test failed: "
173 "kretprobe handler not called\n");
174 handler_errors++;
175 }
176
177 return 0;
178}
179#endif /* CONFIG_KRETPROBES */
180
181int init_test_probes(void)
182{
183 int ret;
184
Masami Hiramatsu8e114402009-01-06 14:41:47 -0800185 target = kprobe_target;
186
Ananth N Mavinakayanahalli8c1c9352008-01-30 13:32:53 +0100187 do {
188 rand1 = random32();
189 } while (rand1 <= div_factor);
190
191 printk(KERN_INFO "Kprobe smoke test started\n");
192 num_tests++;
193 ret = test_kprobe();
194 if (ret < 0)
195 errors++;
196
197 num_tests++;
198 ret = test_jprobe();
199 if (ret < 0)
200 errors++;
201
202#ifdef CONFIG_KRETPROBES
203 num_tests++;
204 ret = test_kretprobe();
205 if (ret < 0)
206 errors++;
207#endif /* CONFIG_KRETPROBES */
208
209 if (errors)
210 printk(KERN_ERR "BUG: Kprobe smoke test: %d out of "
211 "%d tests failed\n", errors, num_tests);
212 else if (handler_errors)
213 printk(KERN_ERR "BUG: Kprobe smoke test: %d error(s) "
214 "running handlers\n", handler_errors);
215 else
216 printk(KERN_INFO "Kprobe smoke test passed successfully\n");
217
218 return 0;
219}