lkdtm: rename globals for clarity
[cascardo/linux.git] / drivers / misc / lkdtm_core.c
1 /*
2  * Linux Kernel Dump Test Module for testing kernel crashes conditions:
3  * induces system failures at predefined crashpoints and under predefined
4  * operational conditions in order to evaluate the reliability of kernel
5  * sanity checking and crash dumps obtained using different dumping
6  * solutions.
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21  *
22  * Copyright (C) IBM Corporation, 2006
23  *
24  * Author: Ankita Garg <ankita@in.ibm.com>
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 #define pr_fmt(fmt) "lkdtm: " fmt
34
35 #include <linux/kernel.h>
36 #include <linux/fs.h>
37 #include <linux/module.h>
38 #include <linux/buffer_head.h>
39 #include <linux/kprobes.h>
40 #include <linux/list.h>
41 #include <linux/init.h>
42 #include <linux/interrupt.h>
43 #include <linux/hrtimer.h>
44 #include <linux/slab.h>
45 #include <scsi/scsi_cmnd.h>
46 #include <linux/debugfs.h>
47
48 #ifdef CONFIG_IDE
49 #include <linux/ide.h>
50 #endif
51
52 #include "lkdtm.h"
53
54 enum cname {
55         CN_INVALID,
56         CN_INT_HARDWARE_ENTRY,
57         CN_INT_HW_IRQ_EN,
58         CN_INT_TASKLET_ENTRY,
59         CN_FS_DEVRW,
60         CN_MEM_SWAPOUT,
61         CN_TIMERADD,
62         CN_SCSI_DISPATCH_CMD,
63         CN_IDE_CORE_CP,
64         CN_DIRECT,
65 };
66
67 enum ctype {
68         CT_NONE,
69         CT_PANIC,
70         CT_BUG,
71         CT_WARNING,
72         CT_EXCEPTION,
73         CT_LOOP,
74         CT_OVERFLOW,
75         CT_CORRUPT_STACK,
76         CT_UNALIGNED_LOAD_STORE_WRITE,
77         CT_OVERWRITE_ALLOCATION,
78         CT_WRITE_AFTER_FREE,
79         CT_READ_AFTER_FREE,
80         CT_WRITE_BUDDY_AFTER_FREE,
81         CT_READ_BUDDY_AFTER_FREE,
82         CT_SOFTLOCKUP,
83         CT_HARDLOCKUP,
84         CT_SPINLOCKUP,
85         CT_HUNG_TASK,
86         CT_EXEC_DATA,
87         CT_EXEC_STACK,
88         CT_EXEC_KMALLOC,
89         CT_EXEC_VMALLOC,
90         CT_EXEC_RODATA,
91         CT_EXEC_USERSPACE,
92         CT_ACCESS_USERSPACE,
93         CT_WRITE_RO,
94         CT_WRITE_RO_AFTER_INIT,
95         CT_WRITE_KERN,
96         CT_ATOMIC_UNDERFLOW,
97         CT_ATOMIC_OVERFLOW,
98         CT_USERCOPY_HEAP_SIZE_TO,
99         CT_USERCOPY_HEAP_SIZE_FROM,
100         CT_USERCOPY_HEAP_FLAG_TO,
101         CT_USERCOPY_HEAP_FLAG_FROM,
102         CT_USERCOPY_STACK_FRAME_TO,
103         CT_USERCOPY_STACK_FRAME_FROM,
104         CT_USERCOPY_STACK_BEYOND,
105         CT_USERCOPY_KERNEL,
106 };
107
108 static char* cp_name[] = {
109         "INVALID",
110         "INT_HARDWARE_ENTRY",
111         "INT_HW_IRQ_EN",
112         "INT_TASKLET_ENTRY",
113         "FS_DEVRW",
114         "MEM_SWAPOUT",
115         "TIMERADD",
116         "SCSI_DISPATCH_CMD",
117         "IDE_CORE_CP",
118         "DIRECT",
119 };
120
121 static char* cp_type[] = {
122         "NONE",
123         "PANIC",
124         "BUG",
125         "WARNING",
126         "EXCEPTION",
127         "LOOP",
128         "OVERFLOW",
129         "CORRUPT_STACK",
130         "UNALIGNED_LOAD_STORE_WRITE",
131         "OVERWRITE_ALLOCATION",
132         "WRITE_AFTER_FREE",
133         "READ_AFTER_FREE",
134         "WRITE_BUDDY_AFTER_FREE",
135         "READ_BUDDY_AFTER_FREE",
136         "SOFTLOCKUP",
137         "HARDLOCKUP",
138         "SPINLOCKUP",
139         "HUNG_TASK",
140         "EXEC_DATA",
141         "EXEC_STACK",
142         "EXEC_KMALLOC",
143         "EXEC_VMALLOC",
144         "EXEC_RODATA",
145         "EXEC_USERSPACE",
146         "ACCESS_USERSPACE",
147         "WRITE_RO",
148         "WRITE_RO_AFTER_INIT",
149         "WRITE_KERN",
150         "ATOMIC_UNDERFLOW",
151         "ATOMIC_OVERFLOW",
152         "USERCOPY_HEAP_SIZE_TO",
153         "USERCOPY_HEAP_SIZE_FROM",
154         "USERCOPY_HEAP_FLAG_TO",
155         "USERCOPY_HEAP_FLAG_FROM",
156         "USERCOPY_STACK_FRAME_TO",
157         "USERCOPY_STACK_FRAME_FROM",
158         "USERCOPY_STACK_BEYOND",
159         "USERCOPY_KERNEL",
160 };
161
162 static struct jprobe lkdtm_jprobe;
163
164 static int lkdtm_parse_commandline(void);
165 static void lkdtm_handler(void);
166
167 #define DEFAULT_COUNT 10
168 static char* cpoint_name;
169 static char* cpoint_type;
170 static int cpoint_count = DEFAULT_COUNT;
171 static int recur_count = -1;
172 static int crash_count = DEFAULT_COUNT;
173 static DEFINE_SPINLOCK(crash_count_lock);
174
175 static enum cname lkdtm_crashpoint = CN_INVALID;
176 static enum ctype lkdtm_crashtype = CT_NONE;
177
178 module_param(recur_count, int, 0644);
179 MODULE_PARM_DESC(recur_count, " Recursion level for the stack overflow test");
180 module_param(cpoint_name, charp, 0444);
181 MODULE_PARM_DESC(cpoint_name, " Crash Point, where kernel is to be crashed");
182 module_param(cpoint_type, charp, 0444);
183 MODULE_PARM_DESC(cpoint_type, " Crash Point Type, action to be taken on "\
184                                 "hitting the crash point");
185 module_param(cpoint_count, int, 0644);
186 MODULE_PARM_DESC(cpoint_count, " Crash Point Count, number of times the "\
187                                 "crash point is to be hit to trigger action");
188
189 static unsigned int jp_do_irq(unsigned int irq)
190 {
191         lkdtm_handler();
192         jprobe_return();
193         return 0;
194 }
195
196 static irqreturn_t jp_handle_irq_event(unsigned int irq,
197                                        struct irqaction *action)
198 {
199         lkdtm_handler();
200         jprobe_return();
201         return 0;
202 }
203
204 static void jp_tasklet_action(struct softirq_action *a)
205 {
206         lkdtm_handler();
207         jprobe_return();
208 }
209
210 static void jp_ll_rw_block(int rw, int nr, struct buffer_head *bhs[])
211 {
212         lkdtm_handler();
213         jprobe_return();
214 }
215
216 struct scan_control;
217
218 static unsigned long jp_shrink_inactive_list(unsigned long max_scan,
219                                              struct zone *zone,
220                                              struct scan_control *sc)
221 {
222         lkdtm_handler();
223         jprobe_return();
224         return 0;
225 }
226
227 static int jp_hrtimer_start(struct hrtimer *timer, ktime_t tim,
228                             const enum hrtimer_mode mode)
229 {
230         lkdtm_handler();
231         jprobe_return();
232         return 0;
233 }
234
235 static int jp_scsi_dispatch_cmd(struct scsi_cmnd *cmd)
236 {
237         lkdtm_handler();
238         jprobe_return();
239         return 0;
240 }
241
242 #ifdef CONFIG_IDE
243 static int jp_generic_ide_ioctl(ide_drive_t *drive, struct file *file,
244                         struct block_device *bdev, unsigned int cmd,
245                         unsigned long arg)
246 {
247         lkdtm_handler();
248         jprobe_return();
249         return 0;
250 }
251 #endif
252
253 /* Return the crashpoint number or NONE if the name is invalid */
254 static enum ctype parse_cp_type(const char *what, size_t count)
255 {
256         int i;
257
258         for (i = 0; i < ARRAY_SIZE(cp_type); i++) {
259                 if (!strcmp(what, cp_type[i]))
260                         return i;
261         }
262
263         return CT_NONE;
264 }
265
266 static const char *cp_type_to_str(enum ctype type)
267 {
268         if (type == CT_NONE || type < 0 || type > ARRAY_SIZE(cp_type))
269                 return "NONE";
270
271         return cp_type[type];
272 }
273
274 static const char *cp_name_to_str(enum cname name)
275 {
276         if (name == CN_INVALID || name < 0 || name > ARRAY_SIZE(cp_name))
277                 return "INVALID";
278
279         return cp_name[name];
280 }
281
282
283 static int lkdtm_parse_commandline(void)
284 {
285         int i;
286         unsigned long flags;
287
288         if (cpoint_count < 1 || recur_count < 1)
289                 return -EINVAL;
290
291         spin_lock_irqsave(&crash_count_lock, flags);
292         crash_count = cpoint_count;
293         spin_unlock_irqrestore(&crash_count_lock, flags);
294
295         /* No special parameters */
296         if (!cpoint_type && !cpoint_name)
297                 return 0;
298
299         /* Neither or both of these need to be set */
300         if (!cpoint_type || !cpoint_name)
301                 return -EINVAL;
302
303         lkdtm_crashtype = parse_cp_type(cpoint_type, strlen(cpoint_type));
304         if (lkdtm_crashtype == CT_NONE)
305                 return -EINVAL;
306
307         /* Refuse INVALID as a selectable crashpoint name. */
308         if (!strcmp(cpoint_name, "INVALID"))
309                 return -EINVAL;
310
311         for (i = 0; i < ARRAY_SIZE(cp_name); i++) {
312                 if (!strcmp(cpoint_name, cp_name[i])) {
313                         lkdtm_crashpoint = i;
314                         return 0;
315                 }
316         }
317
318         /* Could not find a valid crash point */
319         return -EINVAL;
320 }
321
322 static void lkdtm_do_action(enum ctype which)
323 {
324         switch (which) {
325         case CT_PANIC:
326                 lkdtm_PANIC();
327                 break;
328         case CT_BUG:
329                 lkdtm_BUG();
330                 break;
331         case CT_WARNING:
332                 lkdtm_WARNING();
333                 break;
334         case CT_EXCEPTION:
335                 lkdtm_EXCEPTION();
336                 break;
337         case CT_LOOP:
338                 lkdtm_LOOP();
339                 break;
340         case CT_OVERFLOW:
341                 lkdtm_OVERFLOW();
342                 break;
343         case CT_CORRUPT_STACK:
344                 lkdtm_CORRUPT_STACK();
345                 break;
346         case CT_UNALIGNED_LOAD_STORE_WRITE:
347                 lkdtm_UNALIGNED_LOAD_STORE_WRITE();
348                 break;
349         case CT_OVERWRITE_ALLOCATION:
350                 lkdtm_OVERWRITE_ALLOCATION();
351                 break;
352         case CT_WRITE_AFTER_FREE:
353                 lkdtm_WRITE_AFTER_FREE();
354                 break;
355         case CT_READ_AFTER_FREE:
356                 lkdtm_READ_AFTER_FREE();
357                 break;
358         case CT_WRITE_BUDDY_AFTER_FREE:
359                 lkdtm_WRITE_BUDDY_AFTER_FREE();
360                 break;
361         case CT_READ_BUDDY_AFTER_FREE:
362                 lkdtm_READ_BUDDY_AFTER_FREE();
363                 break;
364         case CT_SOFTLOCKUP:
365                 lkdtm_SOFTLOCKUP();
366                 break;
367         case CT_HARDLOCKUP:
368                 lkdtm_HARDLOCKUP();
369                 break;
370         case CT_SPINLOCKUP:
371                 lkdtm_SPINLOCKUP();
372                 break;
373         case CT_HUNG_TASK:
374                 lkdtm_HUNG_TASK();
375                 break;
376         case CT_EXEC_DATA:
377                 lkdtm_EXEC_DATA();
378                 break;
379         case CT_EXEC_STACK:
380                 lkdtm_EXEC_STACK();
381                 break;
382         case CT_EXEC_KMALLOC:
383                 lkdtm_EXEC_KMALLOC();
384                 break;
385         case CT_EXEC_VMALLOC:
386                 lkdtm_EXEC_VMALLOC();
387                 break;
388         case CT_EXEC_RODATA:
389                 lkdtm_EXEC_RODATA();
390                 break;
391         case CT_EXEC_USERSPACE:
392                 lkdtm_EXEC_USERSPACE();
393                 break;
394         case CT_ACCESS_USERSPACE:
395                 lkdtm_ACCESS_USERSPACE();
396                 break;
397         case CT_WRITE_RO:
398                 lkdtm_WRITE_RO();
399                 break;
400         case CT_WRITE_RO_AFTER_INIT:
401                 lkdtm_WRITE_RO_AFTER_INIT();
402                 break;
403         case CT_WRITE_KERN:
404                 lkdtm_WRITE_KERN();
405                 break;
406         case CT_ATOMIC_UNDERFLOW:
407                 lkdtm_ATOMIC_UNDERFLOW();
408                 break;
409         case CT_ATOMIC_OVERFLOW:
410                 lkdtm_ATOMIC_OVERFLOW();
411                 break;
412         case CT_USERCOPY_HEAP_SIZE_TO:
413                 lkdtm_USERCOPY_HEAP_SIZE_TO();
414                 break;
415         case CT_USERCOPY_HEAP_SIZE_FROM:
416                 lkdtm_USERCOPY_HEAP_SIZE_FROM();
417                 break;
418         case CT_USERCOPY_HEAP_FLAG_TO:
419                 lkdtm_USERCOPY_HEAP_FLAG_TO();
420                 break;
421         case CT_USERCOPY_HEAP_FLAG_FROM:
422                 lkdtm_USERCOPY_HEAP_FLAG_FROM();
423                 break;
424         case CT_USERCOPY_STACK_FRAME_TO:
425                 lkdtm_USERCOPY_STACK_FRAME_TO();
426                 break;
427         case CT_USERCOPY_STACK_FRAME_FROM:
428                 lkdtm_USERCOPY_STACK_FRAME_FROM();
429                 break;
430         case CT_USERCOPY_STACK_BEYOND:
431                 lkdtm_USERCOPY_STACK_BEYOND();
432                 break;
433         case CT_USERCOPY_KERNEL:
434                 lkdtm_USERCOPY_KERNEL();
435                 break;
436         case CT_NONE:
437         default:
438                 break;
439         }
440
441 }
442
443 static void lkdtm_handler(void)
444 {
445         unsigned long flags;
446         bool do_it = false;
447
448         spin_lock_irqsave(&crash_count_lock, flags);
449         crash_count--;
450         pr_info("Crash point %s of type %s hit, trigger in %d rounds\n",
451                 cp_name_to_str(lkdtm_crashpoint),
452                 cp_type_to_str(lkdtm_crashtype), crash_count);
453
454         if (crash_count == 0) {
455                 do_it = true;
456                 crash_count = cpoint_count;
457         }
458         spin_unlock_irqrestore(&crash_count_lock, flags);
459
460         if (do_it)
461                 lkdtm_do_action(lkdtm_crashtype);
462 }
463
464 static int lkdtm_register_cpoint(enum cname which)
465 {
466         int ret;
467
468         lkdtm_crashpoint = CN_INVALID;
469         if (lkdtm_jprobe.entry != NULL)
470                 unregister_jprobe(&lkdtm_jprobe);
471
472         switch (which) {
473         case CN_DIRECT:
474                 lkdtm_do_action(lkdtm_crashtype);
475                 return 0;
476         case CN_INT_HARDWARE_ENTRY:
477                 lkdtm_jprobe.kp.symbol_name = "do_IRQ";
478                 lkdtm_jprobe.entry = (kprobe_opcode_t*) jp_do_irq;
479                 break;
480         case CN_INT_HW_IRQ_EN:
481                 lkdtm_jprobe.kp.symbol_name = "handle_IRQ_event";
482                 lkdtm_jprobe.entry = (kprobe_opcode_t*) jp_handle_irq_event;
483                 break;
484         case CN_INT_TASKLET_ENTRY:
485                 lkdtm_jprobe.kp.symbol_name = "tasklet_action";
486                 lkdtm_jprobe.entry = (kprobe_opcode_t*) jp_tasklet_action;
487                 break;
488         case CN_FS_DEVRW:
489                 lkdtm_jprobe.kp.symbol_name = "ll_rw_block";
490                 lkdtm_jprobe.entry = (kprobe_opcode_t*) jp_ll_rw_block;
491                 break;
492         case CN_MEM_SWAPOUT:
493                 lkdtm_jprobe.kp.symbol_name = "shrink_inactive_list";
494                 lkdtm_jprobe.entry = (kprobe_opcode_t*) jp_shrink_inactive_list;
495                 break;
496         case CN_TIMERADD:
497                 lkdtm_jprobe.kp.symbol_name = "hrtimer_start";
498                 lkdtm_jprobe.entry = (kprobe_opcode_t*) jp_hrtimer_start;
499                 break;
500         case CN_SCSI_DISPATCH_CMD:
501                 lkdtm_jprobe.kp.symbol_name = "scsi_dispatch_cmd";
502                 lkdtm_jprobe.entry = (kprobe_opcode_t*) jp_scsi_dispatch_cmd;
503                 break;
504         case CN_IDE_CORE_CP:
505 #ifdef CONFIG_IDE
506                 lkdtm_jprobe.kp.symbol_name = "generic_ide_ioctl";
507                 lkdtm_jprobe.entry = (kprobe_opcode_t*) jp_generic_ide_ioctl;
508 #else
509                 pr_info("Crash point not available\n");
510                 return -EINVAL;
511 #endif
512                 break;
513         default:
514                 pr_info("Invalid Crash Point\n");
515                 return -EINVAL;
516         }
517
518         lkdtm_crashpoint = which;
519         if ((ret = register_jprobe(&lkdtm_jprobe)) < 0) {
520                 pr_info("Couldn't register jprobe\n");
521                 lkdtm_crashpoint = CN_INVALID;
522         }
523
524         return ret;
525 }
526
527 static ssize_t do_register_entry(enum cname which, struct file *f,
528                 const char __user *user_buf, size_t count, loff_t *off)
529 {
530         char *buf;
531         int err;
532
533         if (count >= PAGE_SIZE)
534                 return -EINVAL;
535
536         buf = (char *)__get_free_page(GFP_KERNEL);
537         if (!buf)
538                 return -ENOMEM;
539         if (copy_from_user(buf, user_buf, count)) {
540                 free_page((unsigned long) buf);
541                 return -EFAULT;
542         }
543         /* NULL-terminate and remove enter */
544         buf[count] = '\0';
545         strim(buf);
546
547         lkdtm_crashtype = parse_cp_type(buf, count);
548         free_page((unsigned long) buf);
549
550         if (lkdtm_crashtype == CT_NONE)
551                 return -EINVAL;
552
553         err = lkdtm_register_cpoint(which);
554         if (err < 0)
555                 return err;
556
557         *off += count;
558
559         return count;
560 }
561
562 /* Generic read callback that just prints out the available crash types */
563 static ssize_t lkdtm_debugfs_read(struct file *f, char __user *user_buf,
564                 size_t count, loff_t *off)
565 {
566         char *buf;
567         int i, n, out;
568
569         buf = (char *)__get_free_page(GFP_KERNEL);
570         if (buf == NULL)
571                 return -ENOMEM;
572
573         n = snprintf(buf, PAGE_SIZE, "Available crash types:\n");
574         for (i = 0; i < ARRAY_SIZE(cp_type); i++)
575                 n += snprintf(buf + n, PAGE_SIZE - n, "%s\n", cp_type[i]);
576         buf[n] = '\0';
577
578         out = simple_read_from_buffer(user_buf, count, off,
579                                       buf, n);
580         free_page((unsigned long) buf);
581
582         return out;
583 }
584
585 static int lkdtm_debugfs_open(struct inode *inode, struct file *file)
586 {
587         return 0;
588 }
589
590
591 static ssize_t int_hardware_entry(struct file *f, const char __user *buf,
592                 size_t count, loff_t *off)
593 {
594         return do_register_entry(CN_INT_HARDWARE_ENTRY, f, buf, count, off);
595 }
596
597 static ssize_t int_hw_irq_en(struct file *f, const char __user *buf,
598                 size_t count, loff_t *off)
599 {
600         return do_register_entry(CN_INT_HW_IRQ_EN, f, buf, count, off);
601 }
602
603 static ssize_t int_tasklet_entry(struct file *f, const char __user *buf,
604                 size_t count, loff_t *off)
605 {
606         return do_register_entry(CN_INT_TASKLET_ENTRY, f, buf, count, off);
607 }
608
609 static ssize_t fs_devrw_entry(struct file *f, const char __user *buf,
610                 size_t count, loff_t *off)
611 {
612         return do_register_entry(CN_FS_DEVRW, f, buf, count, off);
613 }
614
615 static ssize_t mem_swapout_entry(struct file *f, const char __user *buf,
616                 size_t count, loff_t *off)
617 {
618         return do_register_entry(CN_MEM_SWAPOUT, f, buf, count, off);
619 }
620
621 static ssize_t timeradd_entry(struct file *f, const char __user *buf,
622                 size_t count, loff_t *off)
623 {
624         return do_register_entry(CN_TIMERADD, f, buf, count, off);
625 }
626
627 static ssize_t scsi_dispatch_cmd_entry(struct file *f,
628                 const char __user *buf, size_t count, loff_t *off)
629 {
630         return do_register_entry(CN_SCSI_DISPATCH_CMD, f, buf, count, off);
631 }
632
633 static ssize_t ide_core_cp_entry(struct file *f, const char __user *buf,
634                 size_t count, loff_t *off)
635 {
636         return do_register_entry(CN_IDE_CORE_CP, f, buf, count, off);
637 }
638
639 /* Special entry to just crash directly. Available without KPROBEs */
640 static ssize_t direct_entry(struct file *f, const char __user *user_buf,
641                 size_t count, loff_t *off)
642 {
643         enum ctype type;
644         char *buf;
645
646         if (count >= PAGE_SIZE)
647                 return -EINVAL;
648         if (count < 1)
649                 return -EINVAL;
650
651         buf = (char *)__get_free_page(GFP_KERNEL);
652         if (!buf)
653                 return -ENOMEM;
654         if (copy_from_user(buf, user_buf, count)) {
655                 free_page((unsigned long) buf);
656                 return -EFAULT;
657         }
658         /* NULL-terminate and remove enter */
659         buf[count] = '\0';
660         strim(buf);
661
662         type = parse_cp_type(buf, count);
663         free_page((unsigned long) buf);
664         if (type == CT_NONE)
665                 return -EINVAL;
666
667         pr_info("Performing direct entry %s\n", cp_type_to_str(type));
668         lkdtm_do_action(type);
669         *off += count;
670
671         return count;
672 }
673
674 struct crash_entry {
675         const char *name;
676         const struct file_operations fops;
677 };
678
679 static const struct crash_entry crash_entries[] = {
680         {"DIRECT", {.read = lkdtm_debugfs_read,
681                         .llseek = generic_file_llseek,
682                         .open = lkdtm_debugfs_open,
683                         .write = direct_entry} },
684         {"INT_HARDWARE_ENTRY", {.read = lkdtm_debugfs_read,
685                         .llseek = generic_file_llseek,
686                         .open = lkdtm_debugfs_open,
687                         .write = int_hardware_entry} },
688         {"INT_HW_IRQ_EN", {.read = lkdtm_debugfs_read,
689                         .llseek = generic_file_llseek,
690                         .open = lkdtm_debugfs_open,
691                         .write = int_hw_irq_en} },
692         {"INT_TASKLET_ENTRY", {.read = lkdtm_debugfs_read,
693                         .llseek = generic_file_llseek,
694                         .open = lkdtm_debugfs_open,
695                         .write = int_tasklet_entry} },
696         {"FS_DEVRW", {.read = lkdtm_debugfs_read,
697                         .llseek = generic_file_llseek,
698                         .open = lkdtm_debugfs_open,
699                         .write = fs_devrw_entry} },
700         {"MEM_SWAPOUT", {.read = lkdtm_debugfs_read,
701                         .llseek = generic_file_llseek,
702                         .open = lkdtm_debugfs_open,
703                         .write = mem_swapout_entry} },
704         {"TIMERADD", {.read = lkdtm_debugfs_read,
705                         .llseek = generic_file_llseek,
706                         .open = lkdtm_debugfs_open,
707                         .write = timeradd_entry} },
708         {"SCSI_DISPATCH_CMD", {.read = lkdtm_debugfs_read,
709                         .llseek = generic_file_llseek,
710                         .open = lkdtm_debugfs_open,
711                         .write = scsi_dispatch_cmd_entry} },
712         {"IDE_CORE_CP", {.read = lkdtm_debugfs_read,
713                         .llseek = generic_file_llseek,
714                         .open = lkdtm_debugfs_open,
715                         .write = ide_core_cp_entry} },
716 };
717
718 static struct dentry *lkdtm_debugfs_root;
719
720 static int __init lkdtm_module_init(void)
721 {
722         int ret = -EINVAL;
723         int n_debugfs_entries = 1; /* Assume only the direct entry */
724         int i;
725
726         /* Handle test-specific initialization. */
727         lkdtm_bugs_init(&recur_count);
728         lkdtm_perms_init();
729         lkdtm_usercopy_init();
730
731         /* Register debugfs interface */
732         lkdtm_debugfs_root = debugfs_create_dir("provoke-crash", NULL);
733         if (!lkdtm_debugfs_root) {
734                 pr_err("creating root dir failed\n");
735                 return -ENODEV;
736         }
737
738 #ifdef CONFIG_KPROBES
739         n_debugfs_entries = ARRAY_SIZE(crash_entries);
740 #endif
741
742         for (i = 0; i < n_debugfs_entries; i++) {
743                 const struct crash_entry *cur = &crash_entries[i];
744                 struct dentry *de;
745
746                 de = debugfs_create_file(cur->name, 0644, lkdtm_debugfs_root,
747                                 NULL, &cur->fops);
748                 if (de == NULL) {
749                         pr_err("could not create %s\n", cur->name);
750                         goto out_err;
751                 }
752         }
753
754         if (lkdtm_parse_commandline() == -EINVAL) {
755                 pr_info("Invalid command\n");
756                 goto out_err;
757         }
758
759         if (lkdtm_crashpoint != CN_INVALID && lkdtm_crashtype != CT_NONE) {
760                 ret = lkdtm_register_cpoint(lkdtm_crashpoint);
761                 if (ret < 0) {
762                         pr_info("Invalid crash point %d\n", lkdtm_crashpoint);
763                         goto out_err;
764                 }
765                 pr_info("Crash point %s of type %s registered\n",
766                         cpoint_name, cpoint_type);
767         } else {
768                 pr_info("No crash points registered, enable through debugfs\n");
769         }
770
771         return 0;
772
773 out_err:
774         debugfs_remove_recursive(lkdtm_debugfs_root);
775         return ret;
776 }
777
778 static void __exit lkdtm_module_exit(void)
779 {
780         debugfs_remove_recursive(lkdtm_debugfs_root);
781
782         /* Handle test-specific clean-up. */
783         lkdtm_usercopy_exit();
784
785         unregister_jprobe(&lkdtm_jprobe);
786         pr_info("Crash point unregistered\n");
787 }
788
789 module_init(lkdtm_module_init);
790 module_exit(lkdtm_module_exit);
791
792 MODULE_LICENSE("GPL");
793 MODULE_DESCRIPTION("Kprobe module for testing crash dumps");