linux/kernel/test_kprobes.c
<<
>>
Prefs
   1/*
   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;
  25static u32 (*target)(u32 value);
  26static u32 (*target2)(u32 value);
  27
  28static noinline u32 kprobe_target(u32 value)
  29{
  30        return (value / div_factor);
  31}
  32
  33static int kp_pre_handler(struct kprobe *p, struct pt_regs *regs)
  34{
  35        preh_val = (rand1 / div_factor);
  36        return 0;
  37}
  38
  39static void kp_post_handler(struct kprobe *p, struct pt_regs *regs,
  40                unsigned long flags)
  41{
  42        if (preh_val != (rand1 / div_factor)) {
  43                handler_errors++;
  44                printk(KERN_ERR "Kprobe smoke test failed: "
  45                                "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                printk(KERN_ERR "Kprobe smoke test failed: "
  63                                "register_kprobe returned %d\n", ret);
  64                return ret;
  65        }
  66
  67        ret = target(rand1);
  68        unregister_kprobe(&kp);
  69
  70        if (preh_val == 0) {
  71                printk(KERN_ERR "Kprobe smoke test failed: "
  72                                "kprobe pre_handler not called\n");
  73                handler_errors++;
  74        }
  75
  76        if (posth_val == 0) {
  77                printk(KERN_ERR "Kprobe smoke test failed: "
  78                                "kprobe post_handler not called\n");
  79                handler_errors++;
  80        }
  81
  82        return 0;
  83}
  84
  85static noinline u32 kprobe_target2(u32 value)
  86{
  87        return (value / div_factor) + 1;
  88}
  89
  90static int kp_pre_handler2(struct kprobe *p, struct pt_regs *regs)
  91{
  92        preh_val = (rand1 / div_factor) + 1;
  93        return 0;
  94}
  95
  96static void kp_post_handler2(struct kprobe *p, struct pt_regs *regs,
  97                unsigned long flags)
  98{
  99        if (preh_val != (rand1 / div_factor) + 1) {
 100                handler_errors++;
 101                printk(KERN_ERR "Kprobe smoke test failed: "
 102                                "incorrect value in post_handler2\n");
 103        }
 104        posth_val = preh_val + div_factor;
 105}
 106
 107static struct kprobe kp2 = {
 108        .symbol_name = "kprobe_target2",
 109        .pre_handler = kp_pre_handler2,
 110        .post_handler = kp_post_handler2
 111};
 112
 113static int test_kprobes(void)
 114{
 115        int ret;
 116        struct kprobe *kps[2] = {&kp, &kp2};
 117
 118        /* addr and flags should be cleard for reusing kprobe. */
 119        kp.addr = NULL;
 120        kp.flags = 0;
 121        ret = register_kprobes(kps, 2);
 122        if (ret < 0) {
 123                printk(KERN_ERR "Kprobe smoke test failed: "
 124                                "register_kprobes returned %d\n", ret);
 125                return ret;
 126        }
 127
 128        preh_val = 0;
 129        posth_val = 0;
 130        ret = target(rand1);
 131
 132        if (preh_val == 0) {
 133                printk(KERN_ERR "Kprobe smoke test failed: "
 134                                "kprobe pre_handler not called\n");
 135                handler_errors++;
 136        }
 137
 138        if (posth_val == 0) {
 139                printk(KERN_ERR "Kprobe smoke test failed: "
 140                                "kprobe post_handler not called\n");
 141                handler_errors++;
 142        }
 143
 144        preh_val = 0;
 145        posth_val = 0;
 146        ret = target2(rand1);
 147
 148        if (preh_val == 0) {
 149                printk(KERN_ERR "Kprobe smoke test failed: "
 150                                "kprobe pre_handler2 not called\n");
 151                handler_errors++;
 152        }
 153
 154        if (posth_val == 0) {
 155                printk(KERN_ERR "Kprobe smoke test failed: "
 156                                "kprobe post_handler2 not called\n");
 157                handler_errors++;
 158        }
 159
 160        unregister_kprobes(kps, 2);
 161        return 0;
 162
 163}
 164
 165static u32 j_kprobe_target(u32 value)
 166{
 167        if (value != rand1) {
 168                handler_errors++;
 169                printk(KERN_ERR "Kprobe smoke test failed: "
 170                                "incorrect value in jprobe handler\n");
 171        }
 172
 173        jph_val = rand1;
 174        jprobe_return();
 175        return 0;
 176}
 177
 178static struct jprobe jp = {
 179        .entry          = j_kprobe_target,
 180        .kp.symbol_name = "kprobe_target"
 181};
 182
 183static int test_jprobe(void)
 184{
 185        int ret;
 186
 187        ret = register_jprobe(&jp);
 188        if (ret < 0) {
 189                printk(KERN_ERR "Kprobe smoke test failed: "
 190                                "register_jprobe returned %d\n", ret);
 191                return ret;
 192        }
 193
 194        ret = target(rand1);
 195        unregister_jprobe(&jp);
 196        if (jph_val == 0) {
 197                printk(KERN_ERR "Kprobe smoke test failed: "
 198                                "jprobe handler not called\n");
 199                handler_errors++;
 200        }
 201
 202        return 0;
 203}
 204
 205static struct jprobe jp2 = {
 206        .entry          = j_kprobe_target,
 207        .kp.symbol_name = "kprobe_target2"
 208};
 209
 210static int test_jprobes(void)
 211{
 212        int ret;
 213        struct jprobe *jps[2] = {&jp, &jp2};
 214
 215        /* addr and flags should be cleard for reusing kprobe. */
 216        jp.kp.addr = NULL;
 217        jp.kp.flags = 0;
 218        ret = register_jprobes(jps, 2);
 219        if (ret < 0) {
 220                printk(KERN_ERR "Kprobe smoke test failed: "
 221                                "register_jprobes returned %d\n", ret);
 222                return ret;
 223        }
 224
 225        jph_val = 0;
 226        ret = target(rand1);
 227        if (jph_val == 0) {
 228                printk(KERN_ERR "Kprobe smoke test failed: "
 229                                "jprobe handler not called\n");
 230                handler_errors++;
 231        }
 232
 233        jph_val = 0;
 234        ret = target2(rand1);
 235        if (jph_val == 0) {
 236                printk(KERN_ERR "Kprobe smoke test failed: "
 237                                "jprobe handler2 not called\n");
 238                handler_errors++;
 239        }
 240        unregister_jprobes(jps, 2);
 241
 242        return 0;
 243}
 244#ifdef CONFIG_KRETPROBES
 245static u32 krph_val;
 246
 247static int entry_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
 248{
 249        krph_val = (rand1 / div_factor);
 250        return 0;
 251}
 252
 253static int return_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
 254{
 255        unsigned long ret = regs_return_value(regs);
 256
 257        if (ret != (rand1 / div_factor)) {
 258                handler_errors++;
 259                printk(KERN_ERR "Kprobe smoke test failed: "
 260                                "incorrect value in kretprobe handler\n");
 261        }
 262        if (krph_val == 0) {
 263                handler_errors++;
 264                printk(KERN_ERR "Kprobe smoke test failed: "
 265                                "call to kretprobe entry handler failed\n");
 266        }
 267
 268        krph_val = rand1;
 269        return 0;
 270}
 271
 272static struct kretprobe rp = {
 273        .handler        = return_handler,
 274        .entry_handler  = entry_handler,
 275        .kp.symbol_name = "kprobe_target"
 276};
 277
 278static int test_kretprobe(void)
 279{
 280        int ret;
 281
 282        ret = register_kretprobe(&rp);
 283        if (ret < 0) {
 284                printk(KERN_ERR "Kprobe smoke test failed: "
 285                                "register_kretprobe returned %d\n", ret);
 286                return ret;
 287        }
 288
 289        ret = target(rand1);
 290        unregister_kretprobe(&rp);
 291        if (krph_val != rand1) {
 292                printk(KERN_ERR "Kprobe smoke test failed: "
 293                                "kretprobe handler not called\n");
 294                handler_errors++;
 295        }
 296
 297        return 0;
 298}
 299
 300static int return_handler2(struct kretprobe_instance *ri, struct pt_regs *regs)
 301{
 302        unsigned long ret = regs_return_value(regs);
 303
 304        if (ret != (rand1 / div_factor) + 1) {
 305                handler_errors++;
 306                printk(KERN_ERR "Kprobe smoke test failed: "
 307                                "incorrect value in kretprobe handler2\n");
 308        }
 309        if (krph_val == 0) {
 310                handler_errors++;
 311                printk(KERN_ERR "Kprobe smoke test failed: "
 312                                "call to kretprobe entry handler failed\n");
 313        }
 314
 315        krph_val = rand1;
 316        return 0;
 317}
 318
 319static struct kretprobe rp2 = {
 320        .handler        = return_handler2,
 321        .entry_handler  = entry_handler,
 322        .kp.symbol_name = "kprobe_target2"
 323};
 324
 325static int test_kretprobes(void)
 326{
 327        int ret;
 328        struct kretprobe *rps[2] = {&rp, &rp2};
 329
 330        /* addr and flags should be cleard for reusing kprobe. */
 331        rp.kp.addr = NULL;
 332        rp.kp.flags = 0;
 333        ret = register_kretprobes(rps, 2);
 334        if (ret < 0) {
 335                printk(KERN_ERR "Kprobe smoke test failed: "
 336                                "register_kretprobe returned %d\n", ret);
 337                return ret;
 338        }
 339
 340        krph_val = 0;
 341        ret = target(rand1);
 342        if (krph_val != rand1) {
 343                printk(KERN_ERR "Kprobe smoke test failed: "
 344                                "kretprobe handler not called\n");
 345                handler_errors++;
 346        }
 347
 348        krph_val = 0;
 349        ret = target2(rand1);
 350        if (krph_val != rand1) {
 351                printk(KERN_ERR "Kprobe smoke test failed: "
 352                                "kretprobe handler2 not called\n");
 353                handler_errors++;
 354        }
 355        unregister_kretprobes(rps, 2);
 356        return 0;
 357}
 358#endif /* CONFIG_KRETPROBES */
 359
 360int init_test_probes(void)
 361{
 362        int ret;
 363
 364        target = kprobe_target;
 365        target2 = kprobe_target2;
 366
 367        do {
 368                rand1 = random32();
 369        } while (rand1 <= div_factor);
 370
 371        printk(KERN_INFO "Kprobe smoke test started\n");
 372        num_tests++;
 373        ret = test_kprobe();
 374        if (ret < 0)
 375                errors++;
 376
 377        num_tests++;
 378        ret = test_kprobes();
 379        if (ret < 0)
 380                errors++;
 381
 382        num_tests++;
 383        ret = test_jprobe();
 384        if (ret < 0)
 385                errors++;
 386
 387        num_tests++;
 388        ret = test_jprobes();
 389        if (ret < 0)
 390                errors++;
 391
 392#ifdef CONFIG_KRETPROBES
 393        num_tests++;
 394        ret = test_kretprobe();
 395        if (ret < 0)
 396                errors++;
 397
 398        num_tests++;
 399        ret = test_kretprobes();
 400        if (ret < 0)
 401                errors++;
 402#endif /* CONFIG_KRETPROBES */
 403
 404        if (errors)
 405                printk(KERN_ERR "BUG: Kprobe smoke test: %d out of "
 406                                "%d tests failed\n", errors, num_tests);
 407        else if (handler_errors)
 408                printk(KERN_ERR "BUG: Kprobe smoke test: %d error(s) "
 409                                "running handlers\n", handler_errors);
 410        else
 411                printk(KERN_INFO "Kprobe smoke test passed successfully\n");
 412
 413        return 0;
 414}
 415
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.