test_kprobes.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  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 noinline u32 kprobe_target(u32 value)
  23. {
  24. /*
  25. * gcc ignores noinline on some architectures unless we stuff
  26. * sufficient lard into the function. The get_kprobe() here is
  27. * just for that.
  28. *
  29. * NOTE: We aren't concerned about the correctness of get_kprobe()
  30. * here; hence, this call is neither under !preempt nor with the
  31. * kprobe_mutex held. This is fine(tm)
  32. */
  33. if (get_kprobe((void *)0xdeadbeef))
  34. printk(KERN_INFO "Kprobe smoke test: probe on 0xdeadbeef!\n");
  35. return (value / div_factor);
  36. }
  37. static int kp_pre_handler(struct kprobe *p, struct pt_regs *regs)
  38. {
  39. preh_val = (rand1 / div_factor);
  40. return 0;
  41. }
  42. static void kp_post_handler(struct kprobe *p, struct pt_regs *regs,
  43. unsigned long flags)
  44. {
  45. if (preh_val != (rand1 / div_factor)) {
  46. handler_errors++;
  47. printk(KERN_ERR "Kprobe smoke test failed: "
  48. "incorrect value in post_handler\n");
  49. }
  50. posth_val = preh_val + div_factor;
  51. }
  52. static struct kprobe kp = {
  53. .symbol_name = "kprobe_target",
  54. .pre_handler = kp_pre_handler,
  55. .post_handler = kp_post_handler
  56. };
  57. static int test_kprobe(void)
  58. {
  59. int ret;
  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. ret = kprobe_target(rand1);
  67. unregister_kprobe(&kp);
  68. if (preh_val == 0) {
  69. printk(KERN_ERR "Kprobe smoke test failed: "
  70. "kprobe pre_handler not called\n");
  71. handler_errors++;
  72. }
  73. if (posth_val == 0) {
  74. printk(KERN_ERR "Kprobe smoke test failed: "
  75. "kprobe post_handler not called\n");
  76. handler_errors++;
  77. }
  78. return 0;
  79. }
  80. static u32 j_kprobe_target(u32 value)
  81. {
  82. if (value != rand1) {
  83. handler_errors++;
  84. printk(KERN_ERR "Kprobe smoke test failed: "
  85. "incorrect value in jprobe handler\n");
  86. }
  87. jph_val = rand1;
  88. jprobe_return();
  89. return 0;
  90. }
  91. static struct jprobe jp = {
  92. .entry = j_kprobe_target,
  93. .kp.symbol_name = "kprobe_target"
  94. };
  95. static int test_jprobe(void)
  96. {
  97. int ret;
  98. ret = register_jprobe(&jp);
  99. if (ret < 0) {
  100. printk(KERN_ERR "Kprobe smoke test failed: "
  101. "register_jprobe returned %d\n", ret);
  102. return ret;
  103. }
  104. ret = kprobe_target(rand1);
  105. unregister_jprobe(&jp);
  106. if (jph_val == 0) {
  107. printk(KERN_ERR "Kprobe smoke test failed: "
  108. "jprobe handler not called\n");
  109. handler_errors++;
  110. }
  111. return 0;
  112. }
  113. #ifdef CONFIG_KRETPROBES
  114. static u32 krph_val;
  115. static int entry_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
  116. {
  117. krph_val = (rand1 / div_factor);
  118. return 0;
  119. }
  120. static int return_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
  121. {
  122. unsigned long ret = regs_return_value(regs);
  123. if (ret != (rand1 / div_factor)) {
  124. handler_errors++;
  125. printk(KERN_ERR "Kprobe smoke test failed: "
  126. "incorrect value in kretprobe handler\n");
  127. }
  128. if (krph_val == 0) {
  129. handler_errors++;
  130. printk(KERN_ERR "Kprobe smoke test failed: "
  131. "call to kretprobe entry handler failed\n");
  132. }
  133. krph_val = rand1;
  134. return 0;
  135. }
  136. static struct kretprobe rp = {
  137. .handler = return_handler,
  138. .entry_handler = entry_handler,
  139. .kp.symbol_name = "kprobe_target"
  140. };
  141. static int test_kretprobe(void)
  142. {
  143. int ret;
  144. ret = register_kretprobe(&rp);
  145. if (ret < 0) {
  146. printk(KERN_ERR "Kprobe smoke test failed: "
  147. "register_kretprobe returned %d\n", ret);
  148. return ret;
  149. }
  150. ret = kprobe_target(rand1);
  151. unregister_kretprobe(&rp);
  152. if (krph_val != rand1) {
  153. printk(KERN_ERR "Kprobe smoke test failed: "
  154. "kretprobe handler not called\n");
  155. handler_errors++;
  156. }
  157. return 0;
  158. }
  159. #endif /* CONFIG_KRETPROBES */
  160. int init_test_probes(void)
  161. {
  162. int ret;
  163. do {
  164. rand1 = random32();
  165. } while (rand1 <= div_factor);
  166. printk(KERN_INFO "Kprobe smoke test started\n");
  167. num_tests++;
  168. ret = test_kprobe();
  169. if (ret < 0)
  170. errors++;
  171. num_tests++;
  172. ret = test_jprobe();
  173. if (ret < 0)
  174. errors++;
  175. #ifdef CONFIG_KRETPROBES
  176. num_tests++;
  177. ret = test_kretprobe();
  178. if (ret < 0)
  179. errors++;
  180. #endif /* CONFIG_KRETPROBES */
  181. if (errors)
  182. printk(KERN_ERR "BUG: Kprobe smoke test: %d out of "
  183. "%d tests failed\n", errors, num_tests);
  184. else if (handler_errors)
  185. printk(KERN_ERR "BUG: Kprobe smoke test: %d error(s) "
  186. "running handlers\n", handler_errors);
  187. else
  188. printk(KERN_INFO "Kprobe smoke test passed successfully\n");
  189. return 0;
  190. }