test_kprobes.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  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. #include <linux/kernel.h>
  17. #include <linux/kprobes.h>
  18. #include <linux/random.h>
  19. #define div_factor 3
  20. static u32 rand1, preh_val, posth_val, jph_val;
  21. static int errors, handler_errors, num_tests;
  22. static u32 (*target)(u32 value);
  23. static noinline u32 kprobe_target(u32 value)
  24. {
  25. return (value / div_factor);
  26. }
  27. static int kp_pre_handler(struct kprobe *p, struct pt_regs *regs)
  28. {
  29. preh_val = (rand1 / div_factor);
  30. return 0;
  31. }
  32. static void kp_post_handler(struct kprobe *p, struct pt_regs *regs,
  33. unsigned long flags)
  34. {
  35. if (preh_val != (rand1 / div_factor)) {
  36. handler_errors++;
  37. printk(KERN_ERR "Kprobe smoke test failed: "
  38. "incorrect value in post_handler\n");
  39. }
  40. posth_val = preh_val + div_factor;
  41. }
  42. static struct kprobe kp = {
  43. .symbol_name = "kprobe_target",
  44. .pre_handler = kp_pre_handler,
  45. .post_handler = kp_post_handler
  46. };
  47. static int test_kprobe(void)
  48. {
  49. int ret;
  50. ret = register_kprobe(&kp);
  51. if (ret < 0) {
  52. printk(KERN_ERR "Kprobe smoke test failed: "
  53. "register_kprobe returned %d\n", ret);
  54. return ret;
  55. }
  56. ret = target(rand1);
  57. unregister_kprobe(&kp);
  58. if (preh_val == 0) {
  59. printk(KERN_ERR "Kprobe smoke test failed: "
  60. "kprobe pre_handler not called\n");
  61. handler_errors++;
  62. }
  63. if (posth_val == 0) {
  64. printk(KERN_ERR "Kprobe smoke test failed: "
  65. "kprobe post_handler not called\n");
  66. handler_errors++;
  67. }
  68. return 0;
  69. }
  70. static u32 j_kprobe_target(u32 value)
  71. {
  72. if (value != rand1) {
  73. handler_errors++;
  74. printk(KERN_ERR "Kprobe smoke test failed: "
  75. "incorrect value in jprobe handler\n");
  76. }
  77. jph_val = rand1;
  78. jprobe_return();
  79. return 0;
  80. }
  81. static struct jprobe jp = {
  82. .entry = j_kprobe_target,
  83. .kp.symbol_name = "kprobe_target"
  84. };
  85. static int test_jprobe(void)
  86. {
  87. int ret;
  88. ret = register_jprobe(&jp);
  89. if (ret < 0) {
  90. printk(KERN_ERR "Kprobe smoke test failed: "
  91. "register_jprobe returned %d\n", ret);
  92. return ret;
  93. }
  94. ret = target(rand1);
  95. unregister_jprobe(&jp);
  96. if (jph_val == 0) {
  97. printk(KERN_ERR "Kprobe smoke test failed: "
  98. "jprobe handler not called\n");
  99. handler_errors++;
  100. }
  101. return 0;
  102. }
  103. #ifdef CONFIG_KRETPROBES
  104. static u32 krph_val;
  105. static int entry_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
  106. {
  107. krph_val = (rand1 / div_factor);
  108. return 0;
  109. }
  110. static int return_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
  111. {
  112. unsigned long ret = regs_return_value(regs);
  113. if (ret != (rand1 / div_factor)) {
  114. handler_errors++;
  115. printk(KERN_ERR "Kprobe smoke test failed: "
  116. "incorrect value in kretprobe handler\n");
  117. }
  118. if (krph_val == 0) {
  119. handler_errors++;
  120. printk(KERN_ERR "Kprobe smoke test failed: "
  121. "call to kretprobe entry handler failed\n");
  122. }
  123. krph_val = rand1;
  124. return 0;
  125. }
  126. static struct kretprobe rp = {
  127. .handler = return_handler,
  128. .entry_handler = entry_handler,
  129. .kp.symbol_name = "kprobe_target"
  130. };
  131. static int test_kretprobe(void)
  132. {
  133. int ret;
  134. ret = register_kretprobe(&rp);
  135. if (ret < 0) {
  136. printk(KERN_ERR "Kprobe smoke test failed: "
  137. "register_kretprobe returned %d\n", ret);
  138. return ret;
  139. }
  140. ret = target(rand1);
  141. unregister_kretprobe(&rp);
  142. if (krph_val != rand1) {
  143. printk(KERN_ERR "Kprobe smoke test failed: "
  144. "kretprobe handler not called\n");
  145. handler_errors++;
  146. }
  147. return 0;
  148. }
  149. #endif /* CONFIG_KRETPROBES */
  150. int init_test_probes(void)
  151. {
  152. int ret;
  153. target = kprobe_target;
  154. do {
  155. rand1 = random32();
  156. } while (rand1 <= div_factor);
  157. printk(KERN_INFO "Kprobe smoke test started\n");
  158. num_tests++;
  159. ret = test_kprobe();
  160. if (ret < 0)
  161. errors++;
  162. num_tests++;
  163. ret = test_jprobe();
  164. if (ret < 0)
  165. errors++;
  166. #ifdef CONFIG_KRETPROBES
  167. num_tests++;
  168. ret = test_kretprobe();
  169. if (ret < 0)
  170. errors++;
  171. #endif /* CONFIG_KRETPROBES */
  172. if (errors)
  173. printk(KERN_ERR "BUG: Kprobe smoke test: %d out of "
  174. "%d tests failed\n", errors, num_tests);
  175. else if (handler_errors)
  176. printk(KERN_ERR "BUG: Kprobe smoke test: %d error(s) "
  177. "running handlers\n", handler_errors);
  178. else
  179. printk(KERN_INFO "Kprobe smoke test passed successfully\n");
  180. return 0;
  181. }