Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v5.3-rc6 313 lines 6.1 kB view raw
1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * test_kprobes.c - simple sanity test for *probes 4 * 5 * Copyright IBM Corp. 2008 6 */ 7 8#define pr_fmt(fmt) "Kprobe smoke test: " fmt 9 10#include <linux/kernel.h> 11#include <linux/kprobes.h> 12#include <linux/random.h> 13 14#define div_factor 3 15 16static u32 rand1, preh_val, posth_val; 17static int errors, handler_errors, num_tests; 18static u32 (*target)(u32 value); 19static u32 (*target2)(u32 value); 20 21static noinline u32 kprobe_target(u32 value) 22{ 23 return (value / div_factor); 24} 25 26static int kp_pre_handler(struct kprobe *p, struct pt_regs *regs) 27{ 28 if (preemptible()) { 29 handler_errors++; 30 pr_err("pre-handler is preemptible\n"); 31 } 32 preh_val = (rand1 / div_factor); 33 return 0; 34} 35 36static void kp_post_handler(struct kprobe *p, struct pt_regs *regs, 37 unsigned long flags) 38{ 39 if (preemptible()) { 40 handler_errors++; 41 pr_err("post-handler is preemptible\n"); 42 } 43 if (preh_val != (rand1 / div_factor)) { 44 handler_errors++; 45 pr_err("incorrect value in post_handler\n"); 46 } 47 posth_val = preh_val + div_factor; 48} 49 50static struct kprobe kp = { 51 .symbol_name = "kprobe_target", 52 .pre_handler = kp_pre_handler, 53 .post_handler = kp_post_handler 54}; 55 56static int test_kprobe(void) 57{ 58 int ret; 59 60 ret = register_kprobe(&kp); 61 if (ret < 0) { 62 pr_err("register_kprobe returned %d\n", ret); 63 return ret; 64 } 65 66 ret = target(rand1); 67 unregister_kprobe(&kp); 68 69 if (preh_val == 0) { 70 pr_err("kprobe pre_handler not called\n"); 71 handler_errors++; 72 } 73 74 if (posth_val == 0) { 75 pr_err("kprobe post_handler not called\n"); 76 handler_errors++; 77 } 78 79 return 0; 80} 81 82static noinline u32 kprobe_target2(u32 value) 83{ 84 return (value / div_factor) + 1; 85} 86 87static int kp_pre_handler2(struct kprobe *p, struct pt_regs *regs) 88{ 89 preh_val = (rand1 / div_factor) + 1; 90 return 0; 91} 92 93static void kp_post_handler2(struct kprobe *p, struct pt_regs *regs, 94 unsigned long flags) 95{ 96 if (preh_val != (rand1 / div_factor) + 1) { 97 handler_errors++; 98 pr_err("incorrect value in post_handler2\n"); 99 } 100 posth_val = preh_val + div_factor; 101} 102 103static struct kprobe kp2 = { 104 .symbol_name = "kprobe_target2", 105 .pre_handler = kp_pre_handler2, 106 .post_handler = kp_post_handler2 107}; 108 109static int test_kprobes(void) 110{ 111 int ret; 112 struct kprobe *kps[2] = {&kp, &kp2}; 113 114 /* addr and flags should be cleard for reusing kprobe. */ 115 kp.addr = NULL; 116 kp.flags = 0; 117 ret = register_kprobes(kps, 2); 118 if (ret < 0) { 119 pr_err("register_kprobes returned %d\n", ret); 120 return ret; 121 } 122 123 preh_val = 0; 124 posth_val = 0; 125 ret = target(rand1); 126 127 if (preh_val == 0) { 128 pr_err("kprobe pre_handler not called\n"); 129 handler_errors++; 130 } 131 132 if (posth_val == 0) { 133 pr_err("kprobe post_handler not called\n"); 134 handler_errors++; 135 } 136 137 preh_val = 0; 138 posth_val = 0; 139 ret = target2(rand1); 140 141 if (preh_val == 0) { 142 pr_err("kprobe pre_handler2 not called\n"); 143 handler_errors++; 144 } 145 146 if (posth_val == 0) { 147 pr_err("kprobe post_handler2 not called\n"); 148 handler_errors++; 149 } 150 151 unregister_kprobes(kps, 2); 152 return 0; 153 154} 155 156#ifdef CONFIG_KRETPROBES 157static u32 krph_val; 158 159static int entry_handler(struct kretprobe_instance *ri, struct pt_regs *regs) 160{ 161 if (preemptible()) { 162 handler_errors++; 163 pr_err("kretprobe entry handler is preemptible\n"); 164 } 165 krph_val = (rand1 / div_factor); 166 return 0; 167} 168 169static int return_handler(struct kretprobe_instance *ri, struct pt_regs *regs) 170{ 171 unsigned long ret = regs_return_value(regs); 172 173 if (preemptible()) { 174 handler_errors++; 175 pr_err("kretprobe return handler is preemptible\n"); 176 } 177 if (ret != (rand1 / div_factor)) { 178 handler_errors++; 179 pr_err("incorrect value in kretprobe handler\n"); 180 } 181 if (krph_val == 0) { 182 handler_errors++; 183 pr_err("call to kretprobe entry handler failed\n"); 184 } 185 186 krph_val = rand1; 187 return 0; 188} 189 190static struct kretprobe rp = { 191 .handler = return_handler, 192 .entry_handler = entry_handler, 193 .kp.symbol_name = "kprobe_target" 194}; 195 196static int test_kretprobe(void) 197{ 198 int ret; 199 200 ret = register_kretprobe(&rp); 201 if (ret < 0) { 202 pr_err("register_kretprobe returned %d\n", ret); 203 return ret; 204 } 205 206 ret = target(rand1); 207 unregister_kretprobe(&rp); 208 if (krph_val != rand1) { 209 pr_err("kretprobe handler not called\n"); 210 handler_errors++; 211 } 212 213 return 0; 214} 215 216static int return_handler2(struct kretprobe_instance *ri, struct pt_regs *regs) 217{ 218 unsigned long ret = regs_return_value(regs); 219 220 if (ret != (rand1 / div_factor) + 1) { 221 handler_errors++; 222 pr_err("incorrect value in kretprobe handler2\n"); 223 } 224 if (krph_val == 0) { 225 handler_errors++; 226 pr_err("call to kretprobe entry handler failed\n"); 227 } 228 229 krph_val = rand1; 230 return 0; 231} 232 233static struct kretprobe rp2 = { 234 .handler = return_handler2, 235 .entry_handler = entry_handler, 236 .kp.symbol_name = "kprobe_target2" 237}; 238 239static int test_kretprobes(void) 240{ 241 int ret; 242 struct kretprobe *rps[2] = {&rp, &rp2}; 243 244 /* addr and flags should be cleard for reusing kprobe. */ 245 rp.kp.addr = NULL; 246 rp.kp.flags = 0; 247 ret = register_kretprobes(rps, 2); 248 if (ret < 0) { 249 pr_err("register_kretprobe returned %d\n", ret); 250 return ret; 251 } 252 253 krph_val = 0; 254 ret = target(rand1); 255 if (krph_val != rand1) { 256 pr_err("kretprobe handler not called\n"); 257 handler_errors++; 258 } 259 260 krph_val = 0; 261 ret = target2(rand1); 262 if (krph_val != rand1) { 263 pr_err("kretprobe handler2 not called\n"); 264 handler_errors++; 265 } 266 unregister_kretprobes(rps, 2); 267 return 0; 268} 269#endif /* CONFIG_KRETPROBES */ 270 271int init_test_probes(void) 272{ 273 int ret; 274 275 target = kprobe_target; 276 target2 = kprobe_target2; 277 278 do { 279 rand1 = prandom_u32(); 280 } while (rand1 <= div_factor); 281 282 pr_info("started\n"); 283 num_tests++; 284 ret = test_kprobe(); 285 if (ret < 0) 286 errors++; 287 288 num_tests++; 289 ret = test_kprobes(); 290 if (ret < 0) 291 errors++; 292 293#ifdef CONFIG_KRETPROBES 294 num_tests++; 295 ret = test_kretprobe(); 296 if (ret < 0) 297 errors++; 298 299 num_tests++; 300 ret = test_kretprobes(); 301 if (ret < 0) 302 errors++; 303#endif /* CONFIG_KRETPROBES */ 304 305 if (errors) 306 pr_err("BUG: %d out of %d tests failed\n", errors, num_tests); 307 else if (handler_errors) 308 pr_err("BUG: %d error(s) running handlers\n", handler_errors); 309 else 310 pr_info("passed successfully\n"); 311 312 return 0; 313}