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        kp.addr = 0; /* addr should be cleard for reusing kprobe. */
 119        ret = register_kprobes(kps, 2);
 120        if (ret < 0) {
 121                printk(KERN_ERR "Kprobe smoke test failed: "
 122                                "register_kprobes returned %d\n", ret);
 123                return ret;
 124        }
 125
 126        preh_val = 0;
 127        posth_val = 0;
 128        ret = target(rand1);
 129
 130        if (preh_val == 0) {
 131                printk(KERN_ERR "Kprobe smoke test failed: "
 132                                "kprobe pre_handler not called\n");
 133                handler_errors++;
 134        }
 135
 136        if (posth_val == 0) {
 137                printk(KERN_ERR "Kprobe smoke test failed: "
 138                                "kprobe post_handler not called\n");
 139                handler_errors++;
 140        }
 141
 142        preh_val = 0;
 143        posth_val = 0;
 144        ret = target2(rand1);
 145
 146        if (preh_val == 0) {
 147                printk(KERN_ERR "Kprobe smoke test failed: "
 148                                "kprobe pre_handler2 not called\n");
 149                handler_errors++;
 150        }
 151
 152        if (posth_val == 0) {
 153                printk(KERN_ERR "Kprobe smoke test failed: "
 154                                "kprobe post_handler2 not called\n");
 155                handler_errors++;
 156        }
 157
 158        unregister_kprobes(kps, 2);
 159        return 0;
 160
 161}
 162
 163static u32 j_kprobe_target(u32 value)
 164{
 165        if (value != rand1) {
 166                handler_errors++;
 167                printk(KERN_ERR "Kprobe smoke test failed: "
 168                                "incorrect value in jprobe handler\n");
 169        }
 170
 171        jph_val = rand1;
 172        jprobe_return();
 173        return 0;
 174}
 175
 176static struct jprobe jp = {
 177        .entry          = j_kprobe_target,
 178        .kp.symbol_name = "kprobe_target"
 179};
 180
 181static int test_jprobe(void)
 182{
 183        int ret;
 184
 185        ret = register_jprobe(&jp);
 186        if (ret < 0) {
 187                printk(KERN_ERR "Kprobe smoke test failed: "
 188                                "register_jprobe returned %d\n", ret);
 189                return ret;
 190        }
 191
 192        ret = target(rand1);
 193        unregister_jprobe(&jp);
 194        if (jph_val == 0) {
 195                printk(KERN_ERR "Kprobe smoke test failed: "
 196                                "jprobe handler not called\n");
 197                handler_errors++;
 198        }
 199
 200        return 0;
 201}
 202
 203static struct jprobe jp2 = {
 204        .entry          = j_kprobe_target,
 205        .kp.symbol_name = "kprobe_target2"
 206};
 207
 208static int test_jprobes(void)
 209{
 210        int ret;
 211        struct jprobe *jps[2] = {&jp, &jp2};
 212
 213        jp.kp.addr = 0; /* addr should be cleard for reusing kprobe. */
 214        ret = register_jprobes(jps, 2);
 215        if (ret < 0) {
 216                printk(KERN_ERR "Kprobe smoke test failed: "
 217                                "register_jprobes returned %d\n", ret);
 218                return ret;
 219        }
 220
 221        jph_val = 0;
 222        ret = target(rand1);
 223        if (jph_val == 0) {
 224                printk(KERN_ERR "Kprobe smoke test failed: "
 225                                "jprobe handler not called\n");
 226                handler_errors++;
 227        }
 228
 229        jph_val = 0;
 230        ret = target2(rand1);
 231        if (jph_val == 0) {
 232                printk(KERN_ERR "Kprobe smoke test failed: "
 233                                "jprobe handler2 not called\n");
 234                handler_errors++;
 235        }
 236        unregister_jprobes(jps, 2);
 237
 238        return 0;
 239}
 240#ifdef CONFIG_KRETPROBES
 241static u32 krph_val;
 242
 243static int entry_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
 244{
 245        krph_val = (rand1 / div_factor);
 246        return 0;
 247}
 248
 249static int return_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
 250{
 251        unsigned long ret = regs_return_value(regs);
 252
 253        if (ret != (rand1 / div_factor)) {
 254                handler_errors++;
 255                printk(KERN_ERR "Kprobe smoke test failed: "
 256                                "incorrect value in kretprobe handler\n");
 257        }
 258        if (krph_val == 0) {
 259                handler_errors++;
 260                printk(KERN_ERR "Kprobe smoke test failed: "
 261                                "call to kretprobe entry handler failed\n");
 262        }
 263
 264        krph_val = rand1;
 265        return 0;
 266}
 267
 268static struct kretprobe rp = {
 269        .handler        = return_handler,
 270        .entry_handler  = entry_handler,
 271        .kp.symbol_name = "kprobe_target"
 272};
 273
 274static int test_kretprobe(void)
 275{
 276        int ret;
 277
 278        ret = register_kretprobe(&rp);
 279        if (ret < 0) {
 280                printk(KERN_ERR "Kprobe smoke test failed: "
 281                                "register_kretprobe returned %d\n", ret);
 282                return ret;
 283        }
 284
 285        ret = target(rand1);
 286        unregister_kretprobe(&rp);
 287        if (krph_val != rand1) {
 288                printk(KERN_ERR "Kprobe smoke test failed: "
 289                                "kretprobe handler not called\n");
 290                handler_errors++;
 291        }
 292
 293        return 0;
 294}
 295
 296static int return_handler2(struct kretprobe_instance *ri, struct pt_regs *regs)
 297{
 298        unsigned long ret = regs_return_value(regs);
 299
 300        if (ret != (rand1 / div_factor) + 1) {
 301                handler_errors++;
 302                printk(KERN_ERR "Kprobe smoke test failed: "
 303                                "incorrect value in kretprobe handler2\n");
 304        }
 305        if (krph_val == 0) {
 306                handler_errors++;
 307                printk(KERN_ERR "Kprobe smoke test failed: "
 308                                "call to kretprobe entry handler failed\n");
 309        }
 310
 311        krph_val = rand1;
 312        return 0;
 313}
 314
 315static struct kretprobe rp2 = {
 316        .handler        = return_handler2,
 317        .entry_handler  = entry_handler,
 318        .kp.symbol_name = "kprobe_target2"
 319};
 320
 321static int test_kretprobes(void)
 322{
 323        int ret;
 324        struct kretprobe *rps[2] = {&rp, &rp2};
 325
 326        rp.kp.addr = 0; /* addr should be cleard for reusing kprobe. */
 327        ret = register_kretprobes(rps, 2);
 328        if (ret < 0) {
 329                printk(KERN_ERR "Kprobe smoke test failed: "
 330                                "register_kretprobe returned %d\n", ret);
 331                return ret;
 332        }
 333
 334        krph_val = 0;
 335        ret = target(rand1);
 336        if (krph_val != rand1) {
 337                printk(KERN_ERR "Kprobe smoke test failed: "
 338                                "kretprobe handler not called\n");
 339                handler_errors++;
 340        }
 341
 342        krph_val = 0;
 343        ret = target2(rand1);
 344        if (krph_val != rand1) {
 345                printk(KERN_ERR "Kprobe smoke test failed: "
 346                                "kretprobe handler2 not called\n");
 347                handler_errors++;
 348        }
 349        unregister_kretprobes(rps, 2);
 350        return 0;
 351}
 352#endif /* CONFIG_KRETPROBES */
 353
 354int init_test_probes(void)
 355{
 356        int ret;
 357
 358        target = kprobe_target;
 359        target2 = kprobe_target2;
 360
 361        do {
 362                rand1 = random32();
 363        } while (rand1 <= div_factor);
 364
 365        printk(KERN_INFO "Kprobe smoke test started\n");
 366        num_tests++;
 367        ret = test_kprobe();
 368        if (ret < 0)
 369                errors++;
 370
 371        num_tests++;
 372        ret = test_kprobes();
 373        if (ret < 0)
 374                errors++;
 375
 376        num_tests++;
 377        ret = test_jprobe();
 378        if (ret < 0)
 379                errors++;
 380
 381        num_tests++;
 382        ret = test_jprobes();
 383        if (ret < 0)
 384                errors++;
 385
 386#ifdef CONFIG_KRETPROBES
 387        num_tests++;
 388        ret = test_kretprobe();
 389        if (ret < 0)
 390                errors++;
 391
 392        num_tests++;
 393        ret = test_kretprobes();
 394        if (ret < 0)
 395                errors++;
 396#endif /* CONFIG_KRETPROBES */
 397
 398        if (errors)
 399                printk(KERN_ERR "BUG: Kprobe smoke test: %d out of "
 400                                "%d tests failed\n", errors, num_tests);
 401        else if (handler_errors)
 402                printk(KERN_ERR "BUG: Kprobe smoke test: %d error(s) "
 403                                "running handlers\n", handler_errors);
 404        else
 405                printk(KERN_INFO "Kprobe smoke test passed successfully\n");
 406
 407        return 0;
 408}
 409