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