lkdtm.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754
  1. /*
  2. * Kprobe module for testing crash dumps
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 2 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  17. *
  18. * Copyright (C) IBM Corporation, 2006
  19. *
  20. * Author: Ankita Garg <ankita@in.ibm.com>
  21. *
  22. * This module induces system failures at predefined crashpoints to
  23. * evaluate the reliability of crash dumps obtained using different dumping
  24. * solutions.
  25. *
  26. * It is adapted from the Linux Kernel Dump Test Tool by
  27. * Fernando Luis Vazquez Cao <http://lkdtt.sourceforge.net>
  28. *
  29. * Debugfs support added by Simon Kagstrom <simon.kagstrom@netinsight.net>
  30. *
  31. * See Documentation/fault-injection/provoke-crashes.txt for instructions
  32. */
  33. #include <linux/kernel.h>
  34. #include <linux/fs.h>
  35. #include <linux/module.h>
  36. #include <linux/buffer_head.h>
  37. #include <linux/kprobes.h>
  38. #include <linux/list.h>
  39. #include <linux/init.h>
  40. #include <linux/interrupt.h>
  41. #include <linux/hrtimer.h>
  42. #include <linux/slab.h>
  43. #include <scsi/scsi_cmnd.h>
  44. #include <linux/debugfs.h>
  45. #include <linux/vmalloc.h>
  46. #ifdef CONFIG_IDE
  47. #include <linux/ide.h>
  48. #endif
  49. #define DEFAULT_COUNT 10
  50. #define REC_NUM_DEFAULT 10
  51. #define EXEC_SIZE 64
  52. enum cname {
  53. CN_INVALID,
  54. CN_INT_HARDWARE_ENTRY,
  55. CN_INT_HW_IRQ_EN,
  56. CN_INT_TASKLET_ENTRY,
  57. CN_FS_DEVRW,
  58. CN_MEM_SWAPOUT,
  59. CN_TIMERADD,
  60. CN_SCSI_DISPATCH_CMD,
  61. CN_IDE_CORE_CP,
  62. CN_DIRECT,
  63. };
  64. enum ctype {
  65. CT_NONE,
  66. CT_PANIC,
  67. CT_BUG,
  68. CT_WARNING,
  69. CT_EXCEPTION,
  70. CT_LOOP,
  71. CT_OVERFLOW,
  72. CT_CORRUPT_STACK,
  73. CT_UNALIGNED_LOAD_STORE_WRITE,
  74. CT_OVERWRITE_ALLOCATION,
  75. CT_WRITE_AFTER_FREE,
  76. CT_SOFTLOCKUP,
  77. CT_HARDLOCKUP,
  78. CT_SPINLOCKUP,
  79. CT_HUNG_TASK,
  80. CT_EXEC_DATA,
  81. CT_EXEC_STACK,
  82. CT_EXEC_KMALLOC,
  83. CT_EXEC_VMALLOC,
  84. };
  85. static char* cp_name[] = {
  86. "INT_HARDWARE_ENTRY",
  87. "INT_HW_IRQ_EN",
  88. "INT_TASKLET_ENTRY",
  89. "FS_DEVRW",
  90. "MEM_SWAPOUT",
  91. "TIMERADD",
  92. "SCSI_DISPATCH_CMD",
  93. "IDE_CORE_CP",
  94. "DIRECT",
  95. };
  96. static char* cp_type[] = {
  97. "PANIC",
  98. "BUG",
  99. "WARNING",
  100. "EXCEPTION",
  101. "LOOP",
  102. "OVERFLOW",
  103. "CORRUPT_STACK",
  104. "UNALIGNED_LOAD_STORE_WRITE",
  105. "OVERWRITE_ALLOCATION",
  106. "WRITE_AFTER_FREE",
  107. "SOFTLOCKUP",
  108. "HARDLOCKUP",
  109. "SPINLOCKUP",
  110. "HUNG_TASK",
  111. "EXEC_DATA",
  112. "EXEC_STACK",
  113. "EXEC_KMALLOC",
  114. "EXEC_VMALLOC",
  115. };
  116. static struct jprobe lkdtm;
  117. static int lkdtm_parse_commandline(void);
  118. static void lkdtm_handler(void);
  119. static char* cpoint_name;
  120. static char* cpoint_type;
  121. static int cpoint_count = DEFAULT_COUNT;
  122. static int recur_count = REC_NUM_DEFAULT;
  123. static enum cname cpoint = CN_INVALID;
  124. static enum ctype cptype = CT_NONE;
  125. static int count = DEFAULT_COUNT;
  126. static DEFINE_SPINLOCK(count_lock);
  127. static DEFINE_SPINLOCK(lock_me_up);
  128. static u8 data_area[EXEC_SIZE];
  129. module_param(recur_count, int, 0644);
  130. MODULE_PARM_DESC(recur_count, " Recursion level for the stack overflow test, "\
  131. "default is 10");
  132. module_param(cpoint_name, charp, 0444);
  133. MODULE_PARM_DESC(cpoint_name, " Crash Point, where kernel is to be crashed");
  134. module_param(cpoint_type, charp, 0444);
  135. MODULE_PARM_DESC(cpoint_type, " Crash Point Type, action to be taken on "\
  136. "hitting the crash point");
  137. module_param(cpoint_count, int, 0644);
  138. MODULE_PARM_DESC(cpoint_count, " Crash Point Count, number of times the "\
  139. "crash point is to be hit to trigger action");
  140. static unsigned int jp_do_irq(unsigned int irq)
  141. {
  142. lkdtm_handler();
  143. jprobe_return();
  144. return 0;
  145. }
  146. static irqreturn_t jp_handle_irq_event(unsigned int irq,
  147. struct irqaction *action)
  148. {
  149. lkdtm_handler();
  150. jprobe_return();
  151. return 0;
  152. }
  153. static void jp_tasklet_action(struct softirq_action *a)
  154. {
  155. lkdtm_handler();
  156. jprobe_return();
  157. }
  158. static void jp_ll_rw_block(int rw, int nr, struct buffer_head *bhs[])
  159. {
  160. lkdtm_handler();
  161. jprobe_return();
  162. }
  163. struct scan_control;
  164. static unsigned long jp_shrink_inactive_list(unsigned long max_scan,
  165. struct zone *zone,
  166. struct scan_control *sc)
  167. {
  168. lkdtm_handler();
  169. jprobe_return();
  170. return 0;
  171. }
  172. static int jp_hrtimer_start(struct hrtimer *timer, ktime_t tim,
  173. const enum hrtimer_mode mode)
  174. {
  175. lkdtm_handler();
  176. jprobe_return();
  177. return 0;
  178. }
  179. static int jp_scsi_dispatch_cmd(struct scsi_cmnd *cmd)
  180. {
  181. lkdtm_handler();
  182. jprobe_return();
  183. return 0;
  184. }
  185. #ifdef CONFIG_IDE
  186. int jp_generic_ide_ioctl(ide_drive_t *drive, struct file *file,
  187. struct block_device *bdev, unsigned int cmd,
  188. unsigned long arg)
  189. {
  190. lkdtm_handler();
  191. jprobe_return();
  192. return 0;
  193. }
  194. #endif
  195. /* Return the crashpoint number or NONE if the name is invalid */
  196. static enum ctype parse_cp_type(const char *what, size_t count)
  197. {
  198. int i;
  199. for (i = 0; i < ARRAY_SIZE(cp_type); i++) {
  200. if (!strcmp(what, cp_type[i]))
  201. return i + 1;
  202. }
  203. return CT_NONE;
  204. }
  205. static const char *cp_type_to_str(enum ctype type)
  206. {
  207. if (type == CT_NONE || type < 0 || type > ARRAY_SIZE(cp_type))
  208. return "None";
  209. return cp_type[type - 1];
  210. }
  211. static const char *cp_name_to_str(enum cname name)
  212. {
  213. if (name == CN_INVALID || name < 0 || name > ARRAY_SIZE(cp_name))
  214. return "INVALID";
  215. return cp_name[name - 1];
  216. }
  217. static int lkdtm_parse_commandline(void)
  218. {
  219. int i;
  220. unsigned long flags;
  221. if (cpoint_count < 1 || recur_count < 1)
  222. return -EINVAL;
  223. spin_lock_irqsave(&count_lock, flags);
  224. count = cpoint_count;
  225. spin_unlock_irqrestore(&count_lock, flags);
  226. /* No special parameters */
  227. if (!cpoint_type && !cpoint_name)
  228. return 0;
  229. /* Neither or both of these need to be set */
  230. if (!cpoint_type || !cpoint_name)
  231. return -EINVAL;
  232. cptype = parse_cp_type(cpoint_type, strlen(cpoint_type));
  233. if (cptype == CT_NONE)
  234. return -EINVAL;
  235. for (i = 0; i < ARRAY_SIZE(cp_name); i++) {
  236. if (!strcmp(cpoint_name, cp_name[i])) {
  237. cpoint = i + 1;
  238. return 0;
  239. }
  240. }
  241. /* Could not find a valid crash point */
  242. return -EINVAL;
  243. }
  244. static int recursive_loop(int a)
  245. {
  246. char buf[1024];
  247. memset(buf,0xFF,1024);
  248. recur_count--;
  249. if (!recur_count)
  250. return 0;
  251. else
  252. return recursive_loop(a);
  253. }
  254. static void do_nothing(void)
  255. {
  256. return;
  257. }
  258. static void execute_location(void *dst)
  259. {
  260. void (*func)(void) = dst;
  261. memcpy(dst, do_nothing, EXEC_SIZE);
  262. func();
  263. }
  264. static void lkdtm_do_action(enum ctype which)
  265. {
  266. switch (which) {
  267. case CT_PANIC:
  268. panic("dumptest");
  269. break;
  270. case CT_BUG:
  271. BUG();
  272. break;
  273. case CT_WARNING:
  274. WARN_ON(1);
  275. break;
  276. case CT_EXCEPTION:
  277. *((int *) 0) = 0;
  278. break;
  279. case CT_LOOP:
  280. for (;;)
  281. ;
  282. break;
  283. case CT_OVERFLOW:
  284. (void) recursive_loop(0);
  285. break;
  286. case CT_CORRUPT_STACK: {
  287. /* Make sure the compiler creates and uses an 8 char array. */
  288. volatile char data[8];
  289. memset((void *)data, 0, 64);
  290. break;
  291. }
  292. case CT_UNALIGNED_LOAD_STORE_WRITE: {
  293. static u8 data[5] __attribute__((aligned(4))) = {1, 2,
  294. 3, 4, 5};
  295. u32 *p;
  296. u32 val = 0x12345678;
  297. p = (u32 *)(data + 1);
  298. if (*p == 0)
  299. val = 0x87654321;
  300. *p = val;
  301. break;
  302. }
  303. case CT_OVERWRITE_ALLOCATION: {
  304. size_t len = 1020;
  305. u32 *data = kmalloc(len, GFP_KERNEL);
  306. data[1024 / sizeof(u32)] = 0x12345678;
  307. kfree(data);
  308. break;
  309. }
  310. case CT_WRITE_AFTER_FREE: {
  311. size_t len = 1024;
  312. u32 *data = kmalloc(len, GFP_KERNEL);
  313. kfree(data);
  314. schedule();
  315. memset(data, 0x78, len);
  316. break;
  317. }
  318. case CT_SOFTLOCKUP:
  319. preempt_disable();
  320. for (;;)
  321. cpu_relax();
  322. break;
  323. case CT_HARDLOCKUP:
  324. local_irq_disable();
  325. for (;;)
  326. cpu_relax();
  327. break;
  328. case CT_SPINLOCKUP:
  329. /* Must be called twice to trigger. */
  330. spin_lock(&lock_me_up);
  331. break;
  332. case CT_HUNG_TASK:
  333. set_current_state(TASK_UNINTERRUPTIBLE);
  334. schedule();
  335. break;
  336. case CT_EXEC_DATA:
  337. execute_location(data_area);
  338. break;
  339. case CT_EXEC_STACK: {
  340. u8 stack_area[EXEC_SIZE];
  341. execute_location(stack_area);
  342. break;
  343. }
  344. case CT_EXEC_KMALLOC: {
  345. u32 *kmalloc_area = kmalloc(EXEC_SIZE, GFP_KERNEL);
  346. execute_location(kmalloc_area);
  347. kfree(kmalloc_area);
  348. break;
  349. }
  350. case CT_EXEC_VMALLOC: {
  351. u32 *vmalloc_area = vmalloc(EXEC_SIZE);
  352. execute_location(vmalloc_area);
  353. vfree(vmalloc_area);
  354. break;
  355. }
  356. case CT_NONE:
  357. default:
  358. break;
  359. }
  360. }
  361. static void lkdtm_handler(void)
  362. {
  363. unsigned long flags;
  364. bool do_it = false;
  365. spin_lock_irqsave(&count_lock, flags);
  366. count--;
  367. printk(KERN_INFO "lkdtm: Crash point %s of type %s hit, trigger in %d rounds\n",
  368. cp_name_to_str(cpoint), cp_type_to_str(cptype), count);
  369. if (count == 0) {
  370. do_it = true;
  371. count = cpoint_count;
  372. }
  373. spin_unlock_irqrestore(&count_lock, flags);
  374. if (do_it)
  375. lkdtm_do_action(cptype);
  376. }
  377. static int lkdtm_register_cpoint(enum cname which)
  378. {
  379. int ret;
  380. cpoint = CN_INVALID;
  381. if (lkdtm.entry != NULL)
  382. unregister_jprobe(&lkdtm);
  383. switch (which) {
  384. case CN_DIRECT:
  385. lkdtm_do_action(cptype);
  386. return 0;
  387. case CN_INT_HARDWARE_ENTRY:
  388. lkdtm.kp.symbol_name = "do_IRQ";
  389. lkdtm.entry = (kprobe_opcode_t*) jp_do_irq;
  390. break;
  391. case CN_INT_HW_IRQ_EN:
  392. lkdtm.kp.symbol_name = "handle_IRQ_event";
  393. lkdtm.entry = (kprobe_opcode_t*) jp_handle_irq_event;
  394. break;
  395. case CN_INT_TASKLET_ENTRY:
  396. lkdtm.kp.symbol_name = "tasklet_action";
  397. lkdtm.entry = (kprobe_opcode_t*) jp_tasklet_action;
  398. break;
  399. case CN_FS_DEVRW:
  400. lkdtm.kp.symbol_name = "ll_rw_block";
  401. lkdtm.entry = (kprobe_opcode_t*) jp_ll_rw_block;
  402. break;
  403. case CN_MEM_SWAPOUT:
  404. lkdtm.kp.symbol_name = "shrink_inactive_list";
  405. lkdtm.entry = (kprobe_opcode_t*) jp_shrink_inactive_list;
  406. break;
  407. case CN_TIMERADD:
  408. lkdtm.kp.symbol_name = "hrtimer_start";
  409. lkdtm.entry = (kprobe_opcode_t*) jp_hrtimer_start;
  410. break;
  411. case CN_SCSI_DISPATCH_CMD:
  412. lkdtm.kp.symbol_name = "scsi_dispatch_cmd";
  413. lkdtm.entry = (kprobe_opcode_t*) jp_scsi_dispatch_cmd;
  414. break;
  415. case CN_IDE_CORE_CP:
  416. #ifdef CONFIG_IDE
  417. lkdtm.kp.symbol_name = "generic_ide_ioctl";
  418. lkdtm.entry = (kprobe_opcode_t*) jp_generic_ide_ioctl;
  419. #else
  420. printk(KERN_INFO "lkdtm: Crash point not available\n");
  421. return -EINVAL;
  422. #endif
  423. break;
  424. default:
  425. printk(KERN_INFO "lkdtm: Invalid Crash Point\n");
  426. return -EINVAL;
  427. }
  428. cpoint = which;
  429. if ((ret = register_jprobe(&lkdtm)) < 0) {
  430. printk(KERN_INFO "lkdtm: Couldn't register jprobe\n");
  431. cpoint = CN_INVALID;
  432. }
  433. return ret;
  434. }
  435. static ssize_t do_register_entry(enum cname which, struct file *f,
  436. const char __user *user_buf, size_t count, loff_t *off)
  437. {
  438. char *buf;
  439. int err;
  440. if (count >= PAGE_SIZE)
  441. return -EINVAL;
  442. buf = (char *)__get_free_page(GFP_KERNEL);
  443. if (!buf)
  444. return -ENOMEM;
  445. if (copy_from_user(buf, user_buf, count)) {
  446. free_page((unsigned long) buf);
  447. return -EFAULT;
  448. }
  449. /* NULL-terminate and remove enter */
  450. buf[count] = '\0';
  451. strim(buf);
  452. cptype = parse_cp_type(buf, count);
  453. free_page((unsigned long) buf);
  454. if (cptype == CT_NONE)
  455. return -EINVAL;
  456. err = lkdtm_register_cpoint(which);
  457. if (err < 0)
  458. return err;
  459. *off += count;
  460. return count;
  461. }
  462. /* Generic read callback that just prints out the available crash types */
  463. static ssize_t lkdtm_debugfs_read(struct file *f, char __user *user_buf,
  464. size_t count, loff_t *off)
  465. {
  466. char *buf;
  467. int i, n, out;
  468. buf = (char *)__get_free_page(GFP_KERNEL);
  469. if (buf == NULL)
  470. return -ENOMEM;
  471. n = snprintf(buf, PAGE_SIZE, "Available crash types:\n");
  472. for (i = 0; i < ARRAY_SIZE(cp_type); i++)
  473. n += snprintf(buf + n, PAGE_SIZE - n, "%s\n", cp_type[i]);
  474. buf[n] = '\0';
  475. out = simple_read_from_buffer(user_buf, count, off,
  476. buf, n);
  477. free_page((unsigned long) buf);
  478. return out;
  479. }
  480. static int lkdtm_debugfs_open(struct inode *inode, struct file *file)
  481. {
  482. return 0;
  483. }
  484. static ssize_t int_hardware_entry(struct file *f, const char __user *buf,
  485. size_t count, loff_t *off)
  486. {
  487. return do_register_entry(CN_INT_HARDWARE_ENTRY, f, buf, count, off);
  488. }
  489. static ssize_t int_hw_irq_en(struct file *f, const char __user *buf,
  490. size_t count, loff_t *off)
  491. {
  492. return do_register_entry(CN_INT_HW_IRQ_EN, f, buf, count, off);
  493. }
  494. static ssize_t int_tasklet_entry(struct file *f, const char __user *buf,
  495. size_t count, loff_t *off)
  496. {
  497. return do_register_entry(CN_INT_TASKLET_ENTRY, f, buf, count, off);
  498. }
  499. static ssize_t fs_devrw_entry(struct file *f, const char __user *buf,
  500. size_t count, loff_t *off)
  501. {
  502. return do_register_entry(CN_FS_DEVRW, f, buf, count, off);
  503. }
  504. static ssize_t mem_swapout_entry(struct file *f, const char __user *buf,
  505. size_t count, loff_t *off)
  506. {
  507. return do_register_entry(CN_MEM_SWAPOUT, f, buf, count, off);
  508. }
  509. static ssize_t timeradd_entry(struct file *f, const char __user *buf,
  510. size_t count, loff_t *off)
  511. {
  512. return do_register_entry(CN_TIMERADD, f, buf, count, off);
  513. }
  514. static ssize_t scsi_dispatch_cmd_entry(struct file *f,
  515. const char __user *buf, size_t count, loff_t *off)
  516. {
  517. return do_register_entry(CN_SCSI_DISPATCH_CMD, f, buf, count, off);
  518. }
  519. static ssize_t ide_core_cp_entry(struct file *f, const char __user *buf,
  520. size_t count, loff_t *off)
  521. {
  522. return do_register_entry(CN_IDE_CORE_CP, f, buf, count, off);
  523. }
  524. /* Special entry to just crash directly. Available without KPROBEs */
  525. static ssize_t direct_entry(struct file *f, const char __user *user_buf,
  526. size_t count, loff_t *off)
  527. {
  528. enum ctype type;
  529. char *buf;
  530. if (count >= PAGE_SIZE)
  531. return -EINVAL;
  532. if (count < 1)
  533. return -EINVAL;
  534. buf = (char *)__get_free_page(GFP_KERNEL);
  535. if (!buf)
  536. return -ENOMEM;
  537. if (copy_from_user(buf, user_buf, count)) {
  538. free_page((unsigned long) buf);
  539. return -EFAULT;
  540. }
  541. /* NULL-terminate and remove enter */
  542. buf[count] = '\0';
  543. strim(buf);
  544. type = parse_cp_type(buf, count);
  545. free_page((unsigned long) buf);
  546. if (type == CT_NONE)
  547. return -EINVAL;
  548. printk(KERN_INFO "lkdtm: Performing direct entry %s\n",
  549. cp_type_to_str(type));
  550. lkdtm_do_action(type);
  551. *off += count;
  552. return count;
  553. }
  554. struct crash_entry {
  555. const char *name;
  556. const struct file_operations fops;
  557. };
  558. static const struct crash_entry crash_entries[] = {
  559. {"DIRECT", {.read = lkdtm_debugfs_read,
  560. .llseek = generic_file_llseek,
  561. .open = lkdtm_debugfs_open,
  562. .write = direct_entry} },
  563. {"INT_HARDWARE_ENTRY", {.read = lkdtm_debugfs_read,
  564. .llseek = generic_file_llseek,
  565. .open = lkdtm_debugfs_open,
  566. .write = int_hardware_entry} },
  567. {"INT_HW_IRQ_EN", {.read = lkdtm_debugfs_read,
  568. .llseek = generic_file_llseek,
  569. .open = lkdtm_debugfs_open,
  570. .write = int_hw_irq_en} },
  571. {"INT_TASKLET_ENTRY", {.read = lkdtm_debugfs_read,
  572. .llseek = generic_file_llseek,
  573. .open = lkdtm_debugfs_open,
  574. .write = int_tasklet_entry} },
  575. {"FS_DEVRW", {.read = lkdtm_debugfs_read,
  576. .llseek = generic_file_llseek,
  577. .open = lkdtm_debugfs_open,
  578. .write = fs_devrw_entry} },
  579. {"MEM_SWAPOUT", {.read = lkdtm_debugfs_read,
  580. .llseek = generic_file_llseek,
  581. .open = lkdtm_debugfs_open,
  582. .write = mem_swapout_entry} },
  583. {"TIMERADD", {.read = lkdtm_debugfs_read,
  584. .llseek = generic_file_llseek,
  585. .open = lkdtm_debugfs_open,
  586. .write = timeradd_entry} },
  587. {"SCSI_DISPATCH_CMD", {.read = lkdtm_debugfs_read,
  588. .llseek = generic_file_llseek,
  589. .open = lkdtm_debugfs_open,
  590. .write = scsi_dispatch_cmd_entry} },
  591. {"IDE_CORE_CP", {.read = lkdtm_debugfs_read,
  592. .llseek = generic_file_llseek,
  593. .open = lkdtm_debugfs_open,
  594. .write = ide_core_cp_entry} },
  595. };
  596. static struct dentry *lkdtm_debugfs_root;
  597. static int __init lkdtm_module_init(void)
  598. {
  599. int ret = -EINVAL;
  600. int n_debugfs_entries = 1; /* Assume only the direct entry */
  601. int i;
  602. /* Register debugfs interface */
  603. lkdtm_debugfs_root = debugfs_create_dir("provoke-crash", NULL);
  604. if (!lkdtm_debugfs_root) {
  605. printk(KERN_ERR "lkdtm: creating root dir failed\n");
  606. return -ENODEV;
  607. }
  608. #ifdef CONFIG_KPROBES
  609. n_debugfs_entries = ARRAY_SIZE(crash_entries);
  610. #endif
  611. for (i = 0; i < n_debugfs_entries; i++) {
  612. const struct crash_entry *cur = &crash_entries[i];
  613. struct dentry *de;
  614. de = debugfs_create_file(cur->name, 0644, lkdtm_debugfs_root,
  615. NULL, &cur->fops);
  616. if (de == NULL) {
  617. printk(KERN_ERR "lkdtm: could not create %s\n",
  618. cur->name);
  619. goto out_err;
  620. }
  621. }
  622. if (lkdtm_parse_commandline() == -EINVAL) {
  623. printk(KERN_INFO "lkdtm: Invalid command\n");
  624. goto out_err;
  625. }
  626. if (cpoint != CN_INVALID && cptype != CT_NONE) {
  627. ret = lkdtm_register_cpoint(cpoint);
  628. if (ret < 0) {
  629. printk(KERN_INFO "lkdtm: Invalid crash point %d\n",
  630. cpoint);
  631. goto out_err;
  632. }
  633. printk(KERN_INFO "lkdtm: Crash point %s of type %s registered\n",
  634. cpoint_name, cpoint_type);
  635. } else {
  636. printk(KERN_INFO "lkdtm: No crash points registered, enable through debugfs\n");
  637. }
  638. return 0;
  639. out_err:
  640. debugfs_remove_recursive(lkdtm_debugfs_root);
  641. return ret;
  642. }
  643. static void __exit lkdtm_module_exit(void)
  644. {
  645. debugfs_remove_recursive(lkdtm_debugfs_root);
  646. unregister_jprobe(&lkdtm);
  647. printk(KERN_INFO "lkdtm: Crash point unregistered\n");
  648. }
  649. module_init(lkdtm_module_init);
  650. module_exit(lkdtm_module_exit);
  651. MODULE_LICENSE("GPL");