~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/lib/test_kprobes.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0-or-later
  2 /*
  3  * test_kprobes.c - simple sanity test for k*probes
  4  *
  5  * Copyright IBM Corp. 2008
  6  */
  7 
  8 #include <linux/kernel.h>
  9 #include <linux/kprobes.h>
 10 #include <linux/random.h>
 11 #include <kunit/test.h>
 12 
 13 #define div_factor 3
 14 
 15 static u32 rand1, preh_val, posth_val;
 16 static u32 (*target)(u32 value);
 17 static u32 (*recursed_target)(u32 value);
 18 static u32 (*target2)(u32 value);
 19 static struct kunit *current_test;
 20 
 21 static unsigned long (*internal_target)(void);
 22 static unsigned long (*stacktrace_target)(void);
 23 static unsigned long (*stacktrace_driver)(void);
 24 static unsigned long target_return_address[2];
 25 
 26 static noinline u32 kprobe_target(u32 value)
 27 {
 28         return (value / div_factor);
 29 }
 30 
 31 static noinline u32 kprobe_recursed_target(u32 value)
 32 {
 33         return (value / div_factor);
 34 }
 35 
 36 static int kp_pre_handler(struct kprobe *p, struct pt_regs *regs)
 37 {
 38         KUNIT_EXPECT_FALSE(current_test, preemptible());
 39 
 40         preh_val = recursed_target(rand1);
 41         return 0;
 42 }
 43 
 44 static void kp_post_handler(struct kprobe *p, struct pt_regs *regs,
 45                 unsigned long flags)
 46 {
 47         u32 expval = recursed_target(rand1);
 48 
 49         KUNIT_EXPECT_FALSE(current_test, preemptible());
 50         KUNIT_EXPECT_EQ(current_test, preh_val, expval);
 51 
 52         posth_val = preh_val + div_factor;
 53 }
 54 
 55 static struct kprobe kp = {
 56         .symbol_name = "kprobe_target",
 57         .pre_handler = kp_pre_handler,
 58         .post_handler = kp_post_handler
 59 };
 60 
 61 static void test_kprobe(struct kunit *test)
 62 {
 63         current_test = test;
 64         KUNIT_EXPECT_EQ(test, 0, register_kprobe(&kp));
 65         target(rand1);
 66         unregister_kprobe(&kp);
 67         KUNIT_EXPECT_NE(test, 0, preh_val);
 68         KUNIT_EXPECT_NE(test, 0, posth_val);
 69 }
 70 
 71 static noinline u32 kprobe_target2(u32 value)
 72 {
 73         return (value / div_factor) + 1;
 74 }
 75 
 76 static noinline unsigned long kprobe_stacktrace_internal_target(void)
 77 {
 78         if (!target_return_address[0])
 79                 target_return_address[0] = (unsigned long)__builtin_return_address(0);
 80         return target_return_address[0];
 81 }
 82 
 83 static noinline unsigned long kprobe_stacktrace_target(void)
 84 {
 85         if (!target_return_address[1])
 86                 target_return_address[1] = (unsigned long)__builtin_return_address(0);
 87 
 88         if (internal_target)
 89                 internal_target();
 90 
 91         return target_return_address[1];
 92 }
 93 
 94 static noinline unsigned long kprobe_stacktrace_driver(void)
 95 {
 96         if (stacktrace_target)
 97                 stacktrace_target();
 98 
 99         /* This is for preventing inlining the function */
100         return (unsigned long)__builtin_return_address(0);
101 }
102 
103 static int kp_pre_handler2(struct kprobe *p, struct pt_regs *regs)
104 {
105         preh_val = (rand1 / div_factor) + 1;
106         return 0;
107 }
108 
109 static void kp_post_handler2(struct kprobe *p, struct pt_regs *regs,
110                 unsigned long flags)
111 {
112         KUNIT_EXPECT_EQ(current_test, preh_val, (rand1 / div_factor) + 1);
113         posth_val = preh_val + div_factor;
114 }
115 
116 static struct kprobe kp2 = {
117         .symbol_name = "kprobe_target2",
118         .pre_handler = kp_pre_handler2,
119         .post_handler = kp_post_handler2
120 };
121 
122 static void test_kprobes(struct kunit *test)
123 {
124         struct kprobe *kps[2] = {&kp, &kp2};
125 
126         current_test = test;
127 
128         /* addr and flags should be cleard for reusing kprobe. */
129         kp.addr = NULL;
130         kp.flags = 0;
131 
132         KUNIT_EXPECT_EQ(test, 0, register_kprobes(kps, 2));
133         preh_val = 0;
134         posth_val = 0;
135         target(rand1);
136 
137         KUNIT_EXPECT_NE(test, 0, preh_val);
138         KUNIT_EXPECT_NE(test, 0, posth_val);
139 
140         preh_val = 0;
141         posth_val = 0;
142         target2(rand1);
143 
144         KUNIT_EXPECT_NE(test, 0, preh_val);
145         KUNIT_EXPECT_NE(test, 0, posth_val);
146         unregister_kprobes(kps, 2);
147 }
148 
149 static struct kprobe kp_missed = {
150         .symbol_name = "kprobe_recursed_target",
151         .pre_handler = kp_pre_handler,
152         .post_handler = kp_post_handler,
153 };
154 
155 static void test_kprobe_missed(struct kunit *test)
156 {
157         current_test = test;
158         preh_val = 0;
159         posth_val = 0;
160 
161         KUNIT_EXPECT_EQ(test, 0, register_kprobe(&kp_missed));
162 
163         recursed_target(rand1);
164 
165         KUNIT_EXPECT_EQ(test, 2, kp_missed.nmissed);
166         KUNIT_EXPECT_NE(test, 0, preh_val);
167         KUNIT_EXPECT_NE(test, 0, posth_val);
168 
169         unregister_kprobe(&kp_missed);
170 }
171 
172 #ifdef CONFIG_KRETPROBES
173 static u32 krph_val;
174 
175 static int entry_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
176 {
177         KUNIT_EXPECT_FALSE(current_test, preemptible());
178         krph_val = (rand1 / div_factor);
179         return 0;
180 }
181 
182 static int return_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
183 {
184         unsigned long ret = regs_return_value(regs);
185 
186         KUNIT_EXPECT_FALSE(current_test, preemptible());
187         KUNIT_EXPECT_EQ(current_test, ret, rand1 / div_factor);
188         KUNIT_EXPECT_NE(current_test, krph_val, 0);
189         krph_val = rand1;
190         return 0;
191 }
192 
193 static struct kretprobe rp = {
194         .handler        = return_handler,
195         .entry_handler  = entry_handler,
196         .kp.symbol_name = "kprobe_target"
197 };
198 
199 static void test_kretprobe(struct kunit *test)
200 {
201         current_test = test;
202         KUNIT_EXPECT_EQ(test, 0, register_kretprobe(&rp));
203         target(rand1);
204         unregister_kretprobe(&rp);
205         KUNIT_EXPECT_EQ(test, krph_val, rand1);
206 }
207 
208 static int return_handler2(struct kretprobe_instance *ri, struct pt_regs *regs)
209 {
210         unsigned long ret = regs_return_value(regs);
211 
212         KUNIT_EXPECT_EQ(current_test, ret, (rand1 / div_factor) + 1);
213         KUNIT_EXPECT_NE(current_test, krph_val, 0);
214         krph_val = rand1;
215         return 0;
216 }
217 
218 static struct kretprobe rp2 = {
219         .handler        = return_handler2,
220         .entry_handler  = entry_handler,
221         .kp.symbol_name = "kprobe_target2"
222 };
223 
224 static void test_kretprobes(struct kunit *test)
225 {
226         struct kretprobe *rps[2] = {&rp, &rp2};
227 
228         current_test = test;
229         /* addr and flags should be cleard for reusing kprobe. */
230         rp.kp.addr = NULL;
231         rp.kp.flags = 0;
232         KUNIT_EXPECT_EQ(test, 0, register_kretprobes(rps, 2));
233 
234         krph_val = 0;
235         target(rand1);
236         KUNIT_EXPECT_EQ(test, krph_val, rand1);
237 
238         krph_val = 0;
239         target2(rand1);
240         KUNIT_EXPECT_EQ(test, krph_val, rand1);
241         unregister_kretprobes(rps, 2);
242 }
243 
244 #ifdef CONFIG_ARCH_CORRECT_STACKTRACE_ON_KRETPROBE
245 #define STACK_BUF_SIZE 16
246 static unsigned long stack_buf[STACK_BUF_SIZE];
247 
248 static int stacktrace_return_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
249 {
250         unsigned long retval = regs_return_value(regs);
251         int i, ret;
252 
253         KUNIT_EXPECT_FALSE(current_test, preemptible());
254         KUNIT_EXPECT_EQ(current_test, retval, target_return_address[1]);
255 
256         /*
257          * Test stacktrace inside the kretprobe handler, this will involves
258          * kretprobe trampoline, but must include correct return address
259          * of the target function.
260          */
261         ret = stack_trace_save(stack_buf, STACK_BUF_SIZE, 0);
262         KUNIT_EXPECT_NE(current_test, ret, 0);
263 
264         for (i = 0; i < ret; i++) {
265                 if (stack_buf[i] == target_return_address[1])
266                         break;
267         }
268         KUNIT_EXPECT_NE(current_test, i, ret);
269 
270 #if !IS_MODULE(CONFIG_KPROBES_SANITY_TEST)
271         /*
272          * Test stacktrace from pt_regs at the return address. Thus the stack
273          * trace must start from the target return address.
274          */
275         ret = stack_trace_save_regs(regs, stack_buf, STACK_BUF_SIZE, 0);
276         KUNIT_EXPECT_NE(current_test, ret, 0);
277         KUNIT_EXPECT_EQ(current_test, stack_buf[0], target_return_address[1]);
278 #endif
279 
280         return 0;
281 }
282 
283 static struct kretprobe rp3 = {
284         .handler        = stacktrace_return_handler,
285         .kp.symbol_name = "kprobe_stacktrace_target"
286 };
287 
288 static void test_stacktrace_on_kretprobe(struct kunit *test)
289 {
290         unsigned long myretaddr = (unsigned long)__builtin_return_address(0);
291 
292         current_test = test;
293         rp3.kp.addr = NULL;
294         rp3.kp.flags = 0;
295 
296         /*
297          * Run the stacktrace_driver() to record correct return address in
298          * stacktrace_target() and ensure stacktrace_driver() call is not
299          * inlined by checking the return address of stacktrace_driver()
300          * and the return address of this function is different.
301          */
302         KUNIT_ASSERT_NE(test, myretaddr, stacktrace_driver());
303 
304         KUNIT_ASSERT_EQ(test, 0, register_kretprobe(&rp3));
305         KUNIT_ASSERT_NE(test, myretaddr, stacktrace_driver());
306         unregister_kretprobe(&rp3);
307 }
308 
309 static int stacktrace_internal_return_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
310 {
311         unsigned long retval = regs_return_value(regs);
312         int i, ret;
313 
314         KUNIT_EXPECT_FALSE(current_test, preemptible());
315         KUNIT_EXPECT_EQ(current_test, retval, target_return_address[0]);
316 
317         /*
318          * Test stacktrace inside the kretprobe handler for nested case.
319          * The unwinder will find the kretprobe_trampoline address on the
320          * return address, and kretprobe must solve that.
321          */
322         ret = stack_trace_save(stack_buf, STACK_BUF_SIZE, 0);
323         KUNIT_EXPECT_NE(current_test, ret, 0);
324 
325         for (i = 0; i < ret - 1; i++) {
326                 if (stack_buf[i] == target_return_address[0]) {
327                         KUNIT_EXPECT_EQ(current_test, stack_buf[i + 1], target_return_address[1]);
328                         break;
329                 }
330         }
331         KUNIT_EXPECT_NE(current_test, i, ret);
332 
333 #if !IS_MODULE(CONFIG_KPROBES_SANITY_TEST)
334         /* Ditto for the regs version. */
335         ret = stack_trace_save_regs(regs, stack_buf, STACK_BUF_SIZE, 0);
336         KUNIT_EXPECT_NE(current_test, ret, 0);
337         KUNIT_EXPECT_EQ(current_test, stack_buf[0], target_return_address[0]);
338         KUNIT_EXPECT_EQ(current_test, stack_buf[1], target_return_address[1]);
339 #endif
340 
341         return 0;
342 }
343 
344 static struct kretprobe rp4 = {
345         .handler        = stacktrace_internal_return_handler,
346         .kp.symbol_name = "kprobe_stacktrace_internal_target"
347 };
348 
349 static void test_stacktrace_on_nested_kretprobe(struct kunit *test)
350 {
351         unsigned long myretaddr = (unsigned long)__builtin_return_address(0);
352         struct kretprobe *rps[2] = {&rp3, &rp4};
353 
354         current_test = test;
355         rp3.kp.addr = NULL;
356         rp3.kp.flags = 0;
357 
358         //KUNIT_ASSERT_NE(test, myretaddr, stacktrace_driver());
359 
360         KUNIT_ASSERT_EQ(test, 0, register_kretprobes(rps, 2));
361         KUNIT_ASSERT_NE(test, myretaddr, stacktrace_driver());
362         unregister_kretprobes(rps, 2);
363 }
364 #endif /* CONFIG_ARCH_CORRECT_STACKTRACE_ON_KRETPROBE */
365 
366 #endif /* CONFIG_KRETPROBES */
367 
368 static int kprobes_test_init(struct kunit *test)
369 {
370         target = kprobe_target;
371         target2 = kprobe_target2;
372         recursed_target = kprobe_recursed_target;
373         stacktrace_target = kprobe_stacktrace_target;
374         internal_target = kprobe_stacktrace_internal_target;
375         stacktrace_driver = kprobe_stacktrace_driver;
376         rand1 = get_random_u32_above(div_factor);
377         return 0;
378 }
379 
380 static struct kunit_case kprobes_testcases[] = {
381         KUNIT_CASE(test_kprobe),
382         KUNIT_CASE(test_kprobes),
383         KUNIT_CASE(test_kprobe_missed),
384 #ifdef CONFIG_KRETPROBES
385         KUNIT_CASE(test_kretprobe),
386         KUNIT_CASE(test_kretprobes),
387 #ifdef CONFIG_ARCH_CORRECT_STACKTRACE_ON_KRETPROBE
388         KUNIT_CASE(test_stacktrace_on_kretprobe),
389         KUNIT_CASE(test_stacktrace_on_nested_kretprobe),
390 #endif
391 #endif
392         {}
393 };
394 
395 static struct kunit_suite kprobes_test_suite = {
396         .name = "kprobes_test",
397         .init = kprobes_test_init,
398         .test_cases = kprobes_testcases,
399 };
400 
401 kunit_test_suites(&kprobes_test_suite);
402 
403 MODULE_DESCRIPTION("simple sanity test for k*probes");
404 MODULE_LICENSE("GPL");
405 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php