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#define pr_fmt(fmt) KBUILD_MODNAME ": " 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#include <linux/vmalloc.h> 48#include <linux/mman.h> 49#include <asm/cacheflush.h> 50 51#ifdef CONFIG_IDE 52#include <linux/ide.h> 53#endif 54 55/* 56 * Make sure our attempts to over run the kernel stack doesn't trigger 57 * a compiler warning when CONFIG_FRAME_WARN is set. Then make sure we 58 * recurse past the end of THREAD_SIZE by default. 59 */ 60#if defined(CONFIG_FRAME_WARN) && (CONFIG_FRAME_WARN > 0) 61#define REC_STACK_SIZE (CONFIG_FRAME_WARN / 2) 62#else 63#define REC_STACK_SIZE (THREAD_SIZE / 8) 64#endif 65#define REC_NUM_DEFAULT ((THREAD_SIZE / REC_STACK_SIZE) * 2) 66 67#define DEFAULT_COUNT 10 68#define EXEC_SIZE 64 69 70enum cname { 71 CN_INVALID, 72 CN_INT_HARDWARE_ENTRY, 73 CN_INT_HW_IRQ_EN, 74 CN_INT_TASKLET_ENTRY, 75 CN_FS_DEVRW, 76 CN_MEM_SWAPOUT, 77 CN_TIMERADD, 78 CN_SCSI_DISPATCH_CMD, 79 CN_IDE_CORE_CP, 80 CN_DIRECT, 81}; 82 83enum ctype { 84 CT_NONE, 85 CT_PANIC, 86 CT_BUG, 87 CT_WARNING, 88 CT_EXCEPTION, 89 CT_LOOP, 90 CT_OVERFLOW, 91 CT_CORRUPT_STACK, 92 CT_UNALIGNED_LOAD_STORE_WRITE, 93 CT_OVERWRITE_ALLOCATION, 94 CT_WRITE_AFTER_FREE, 95 CT_SOFTLOCKUP, 96 CT_HARDLOCKUP, 97 CT_SPINLOCKUP, 98 CT_HUNG_TASK, 99 CT_EXEC_DATA, 100 CT_EXEC_STACK, 101 CT_EXEC_KMALLOC, 102 CT_EXEC_VMALLOC, 103 CT_EXEC_USERSPACE, 104 CT_ACCESS_USERSPACE, 105 CT_WRITE_RO, 106 CT_WRITE_KERN, 107}; 108 109static char* cp_name[] = { 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 121static char* cp_type[] = { 122 "PANIC", 123 "BUG", 124 "WARNING", 125 "EXCEPTION", 126 "LOOP", 127 "OVERFLOW", 128 "CORRUPT_STACK", 129 "UNALIGNED_LOAD_STORE_WRITE", 130 "OVERWRITE_ALLOCATION", 131 "WRITE_AFTER_FREE", 132 "SOFTLOCKUP", 133 "HARDLOCKUP", 134 "SPINLOCKUP", 135 "HUNG_TASK", 136 "EXEC_DATA", 137 "EXEC_STACK", 138 "EXEC_KMALLOC", 139 "EXEC_VMALLOC", 140 "EXEC_USERSPACE", 141 "ACCESS_USERSPACE", 142 "WRITE_RO", 143 "WRITE_KERN", 144}; 145 146static struct jprobe lkdtm; 147 148static int lkdtm_parse_commandline(void); 149static void lkdtm_handler(void); 150 151static char* cpoint_name; 152static char* cpoint_type; 153static int cpoint_count = DEFAULT_COUNT; 154static int recur_count = REC_NUM_DEFAULT; 155 156static enum cname cpoint = CN_INVALID; 157static enum ctype cptype = CT_NONE; 158static int count = DEFAULT_COUNT; 159static DEFINE_SPINLOCK(count_lock); 160static DEFINE_SPINLOCK(lock_me_up); 161 162static u8 data_area[EXEC_SIZE]; 163 164static const unsigned long rodata = 0xAA55AA55; 165 166module_param(recur_count, int, 0644); 167MODULE_PARM_DESC(recur_count, " Recursion level for the stack overflow test"); 168module_param(cpoint_name, charp, 0444); 169MODULE_PARM_DESC(cpoint_name, " Crash Point, where kernel is to be crashed"); 170module_param(cpoint_type, charp, 0444); 171MODULE_PARM_DESC(cpoint_type, " Crash Point Type, action to be taken on "\ 172 "hitting the crash point"); 173module_param(cpoint_count, int, 0644); 174MODULE_PARM_DESC(cpoint_count, " Crash Point Count, number of times the "\ 175 "crash point is to be hit to trigger action"); 176 177static unsigned int jp_do_irq(unsigned int irq) 178{ 179 lkdtm_handler(); 180 jprobe_return(); 181 return 0; 182} 183 184static irqreturn_t jp_handle_irq_event(unsigned int irq, 185 struct irqaction *action) 186{ 187 lkdtm_handler(); 188 jprobe_return(); 189 return 0; 190} 191 192static void jp_tasklet_action(struct softirq_action *a) 193{ 194 lkdtm_handler(); 195 jprobe_return(); 196} 197 198static void jp_ll_rw_block(int rw, int nr, struct buffer_head *bhs[]) 199{ 200 lkdtm_handler(); 201 jprobe_return(); 202} 203 204struct scan_control; 205 206static unsigned long jp_shrink_inactive_list(unsigned long max_scan, 207 struct zone *zone, 208 struct scan_control *sc) 209{ 210 lkdtm_handler(); 211 jprobe_return(); 212 return 0; 213} 214 215static int jp_hrtimer_start(struct hrtimer *timer, ktime_t tim, 216 const enum hrtimer_mode mode) 217{ 218 lkdtm_handler(); 219 jprobe_return(); 220 return 0; 221} 222 223static int jp_scsi_dispatch_cmd(struct scsi_cmnd *cmd) 224{ 225 lkdtm_handler(); 226 jprobe_return(); 227 return 0; 228} 229 230#ifdef CONFIG_IDE 231static int jp_generic_ide_ioctl(ide_drive_t *drive, struct file *file, 232 struct block_device *bdev, unsigned int cmd, 233 unsigned long arg) 234{ 235 lkdtm_handler(); 236 jprobe_return(); 237 return 0; 238} 239#endif 240 241/* Return the crashpoint number or NONE if the name is invalid */ 242static enum ctype parse_cp_type(const char *what, size_t count) 243{ 244 int i; 245 246 for (i = 0; i < ARRAY_SIZE(cp_type); i++) { 247 if (!strcmp(what, cp_type[i])) 248 return i + 1; 249 } 250 251 return CT_NONE; 252} 253 254static const char *cp_type_to_str(enum ctype type) 255{ 256 if (type == CT_NONE || type < 0 || type > ARRAY_SIZE(cp_type)) 257 return "None"; 258 259 return cp_type[type - 1]; 260} 261 262static const char *cp_name_to_str(enum cname name) 263{ 264 if (name == CN_INVALID || name < 0 || name > ARRAY_SIZE(cp_name)) 265 return "INVALID"; 266 267 return cp_name[name - 1]; 268} 269 270 271static int lkdtm_parse_commandline(void) 272{ 273 int i; 274 unsigned long flags; 275 276 if (cpoint_count < 1 || recur_count < 1) 277 return -EINVAL; 278 279 spin_lock_irqsave(&count_lock, flags); 280 count = cpoint_count; 281 spin_unlock_irqrestore(&count_lock, flags); 282 283 /* No special parameters */ 284 if (!cpoint_type && !cpoint_name) 285 return 0; 286 287 /* Neither or both of these need to be set */ 288 if (!cpoint_type || !cpoint_name) 289 return -EINVAL; 290 291 cptype = parse_cp_type(cpoint_type, strlen(cpoint_type)); 292 if (cptype == CT_NONE) 293 return -EINVAL; 294 295 for (i = 0; i < ARRAY_SIZE(cp_name); i++) { 296 if (!strcmp(cpoint_name, cp_name[i])) { 297 cpoint = i + 1; 298 return 0; 299 } 300 } 301 302 /* Could not find a valid crash point */ 303 return -EINVAL; 304} 305 306static int recursive_loop(int remaining) 307{ 308 char buf[REC_STACK_SIZE]; 309 310 /* Make sure compiler does not optimize this away. */ 311 memset(buf, (remaining & 0xff) | 0x1, REC_STACK_SIZE); 312 if (!remaining) 313 return 0; 314 else 315 return recursive_loop(remaining - 1); 316} 317 318static void do_nothing(void) 319{ 320 return; 321} 322 323/* Must immediately follow do_nothing for size calculuations to work out. */ 324static void do_overwritten(void) 325{ 326 pr_info("do_overwritten wasn't overwritten!\n"); 327 return; 328} 329 330static noinline void corrupt_stack(void) 331{ 332 /* Use default char array length that triggers stack protection. */ 333 char data[8]; 334 335 memset((void *)data, 0, 64); 336} 337 338static void execute_location(void *dst) 339{ 340 void (*func)(void) = dst; 341 342 pr_info("attempting ok execution at %p\n", do_nothing); 343 do_nothing(); 344 345 memcpy(dst, do_nothing, EXEC_SIZE); 346 flush_icache_range((unsigned long)dst, (unsigned long)dst + EXEC_SIZE); 347 pr_info("attempting bad execution at %p\n", func); 348 func(); 349} 350 351static void execute_user_location(void *dst) 352{ 353 /* Intentionally crossing kernel/user memory boundary. */ 354 void (*func)(void) = dst; 355 356 pr_info("attempting ok execution at %p\n", do_nothing); 357 do_nothing(); 358 359 if (copy_to_user((void __user *)dst, do_nothing, EXEC_SIZE)) 360 return; 361 flush_icache_range((unsigned long)dst, (unsigned long)dst + EXEC_SIZE); 362 pr_info("attempting bad execution at %p\n", func); 363 func(); 364} 365 366static void lkdtm_do_action(enum ctype which) 367{ 368 switch (which) { 369 case CT_PANIC: 370 panic("dumptest"); 371 break; 372 case CT_BUG: 373 BUG(); 374 break; 375 case CT_WARNING: 376 WARN_ON(1); 377 break; 378 case CT_EXCEPTION: 379 *((int *) 0) = 0; 380 break; 381 case CT_LOOP: 382 for (;;) 383 ; 384 break; 385 case CT_OVERFLOW: 386 (void) recursive_loop(recur_count); 387 break; 388 case CT_CORRUPT_STACK: 389 corrupt_stack(); 390 break; 391 case CT_UNALIGNED_LOAD_STORE_WRITE: { 392 static u8 data[5] __attribute__((aligned(4))) = {1, 2, 393 3, 4, 5}; 394 u32 *p; 395 u32 val = 0x12345678; 396 397 p = (u32 *)(data + 1); 398 if (*p == 0) 399 val = 0x87654321; 400 *p = val; 401 break; 402 } 403 case CT_OVERWRITE_ALLOCATION: { 404 size_t len = 1020; 405 u32 *data = kmalloc(len, GFP_KERNEL); 406 407 data[1024 / sizeof(u32)] = 0x12345678; 408 kfree(data); 409 break; 410 } 411 case CT_WRITE_AFTER_FREE: { 412 size_t len = 1024; 413 u32 *data = kmalloc(len, GFP_KERNEL); 414 415 kfree(data); 416 schedule(); 417 memset(data, 0x78, len); 418 break; 419 } 420 case CT_SOFTLOCKUP: 421 preempt_disable(); 422 for (;;) 423 cpu_relax(); 424 break; 425 case CT_HARDLOCKUP: 426 local_irq_disable(); 427 for (;;) 428 cpu_relax(); 429 break; 430 case CT_SPINLOCKUP: 431 /* Must be called twice to trigger. */ 432 spin_lock(&lock_me_up); 433 /* Let sparse know we intended to exit holding the lock. */ 434 __release(&lock_me_up); 435 break; 436 case CT_HUNG_TASK: 437 set_current_state(TASK_UNINTERRUPTIBLE); 438 schedule(); 439 break; 440 case CT_EXEC_DATA: 441 execute_location(data_area); 442 break; 443 case CT_EXEC_STACK: { 444 u8 stack_area[EXEC_SIZE]; 445 execute_location(stack_area); 446 break; 447 } 448 case CT_EXEC_KMALLOC: { 449 u32 *kmalloc_area = kmalloc(EXEC_SIZE, GFP_KERNEL); 450 execute_location(kmalloc_area); 451 kfree(kmalloc_area); 452 break; 453 } 454 case CT_EXEC_VMALLOC: { 455 u32 *vmalloc_area = vmalloc(EXEC_SIZE); 456 execute_location(vmalloc_area); 457 vfree(vmalloc_area); 458 break; 459 } 460 case CT_EXEC_USERSPACE: { 461 unsigned long user_addr; 462 463 user_addr = vm_mmap(NULL, 0, PAGE_SIZE, 464 PROT_READ | PROT_WRITE | PROT_EXEC, 465 MAP_ANONYMOUS | MAP_PRIVATE, 0); 466 if (user_addr >= TASK_SIZE) { 467 pr_warn("Failed to allocate user memory\n"); 468 return; 469 } 470 execute_user_location((void *)user_addr); 471 vm_munmap(user_addr, PAGE_SIZE); 472 break; 473 } 474 case CT_ACCESS_USERSPACE: { 475 unsigned long user_addr, tmp; 476 unsigned long *ptr; 477 478 user_addr = vm_mmap(NULL, 0, PAGE_SIZE, 479 PROT_READ | PROT_WRITE | PROT_EXEC, 480 MAP_ANONYMOUS | MAP_PRIVATE, 0); 481 if (user_addr >= TASK_SIZE) { 482 pr_warn("Failed to allocate user memory\n"); 483 return; 484 } 485 486 ptr = (unsigned long *)user_addr; 487 488 pr_info("attempting bad read at %p\n", ptr); 489 tmp = *ptr; 490 tmp += 0xc0dec0de; 491 492 pr_info("attempting bad write at %p\n", ptr); 493 *ptr = tmp; 494 495 vm_munmap(user_addr, PAGE_SIZE); 496 497 break; 498 } 499 case CT_WRITE_RO: { 500 unsigned long *ptr; 501 502 ptr = (unsigned long *)&rodata; 503 504 pr_info("attempting bad write at %p\n", ptr); 505 *ptr ^= 0xabcd1234; 506 507 break; 508 } 509 case CT_WRITE_KERN: { 510 size_t size; 511 unsigned char *ptr; 512 513 size = (unsigned long)do_overwritten - 514 (unsigned long)do_nothing; 515 ptr = (unsigned char *)do_overwritten; 516 517 pr_info("attempting bad %zu byte write at %p\n", size, ptr); 518 memcpy(ptr, (unsigned char *)do_nothing, size); 519 flush_icache_range((unsigned long)ptr, 520 (unsigned long)(ptr + size)); 521 522 do_overwritten(); 523 break; 524 } 525 case CT_NONE: 526 default: 527 break; 528 } 529 530} 531 532static void lkdtm_handler(void) 533{ 534 unsigned long flags; 535 bool do_it = false; 536 537 spin_lock_irqsave(&count_lock, flags); 538 count--; 539 pr_info("Crash point %s of type %s hit, trigger in %d rounds\n", 540 cp_name_to_str(cpoint), cp_type_to_str(cptype), count); 541 542 if (count == 0) { 543 do_it = true; 544 count = cpoint_count; 545 } 546 spin_unlock_irqrestore(&count_lock, flags); 547 548 if (do_it) 549 lkdtm_do_action(cptype); 550} 551 552static int lkdtm_register_cpoint(enum cname which) 553{ 554 int ret; 555 556 cpoint = CN_INVALID; 557 if (lkdtm.entry != NULL) 558 unregister_jprobe(&lkdtm); 559 560 switch (which) { 561 case CN_DIRECT: 562 lkdtm_do_action(cptype); 563 return 0; 564 case CN_INT_HARDWARE_ENTRY: 565 lkdtm.kp.symbol_name = "do_IRQ"; 566 lkdtm.entry = (kprobe_opcode_t*) jp_do_irq; 567 break; 568 case CN_INT_HW_IRQ_EN: 569 lkdtm.kp.symbol_name = "handle_IRQ_event"; 570 lkdtm.entry = (kprobe_opcode_t*) jp_handle_irq_event; 571 break; 572 case CN_INT_TASKLET_ENTRY: 573 lkdtm.kp.symbol_name = "tasklet_action"; 574 lkdtm.entry = (kprobe_opcode_t*) jp_tasklet_action; 575 break; 576 case CN_FS_DEVRW: 577 lkdtm.kp.symbol_name = "ll_rw_block"; 578 lkdtm.entry = (kprobe_opcode_t*) jp_ll_rw_block; 579 break; 580 case CN_MEM_SWAPOUT: 581 lkdtm.kp.symbol_name = "shrink_inactive_list"; 582 lkdtm.entry = (kprobe_opcode_t*) jp_shrink_inactive_list; 583 break; 584 case CN_TIMERADD: 585 lkdtm.kp.symbol_name = "hrtimer_start"; 586 lkdtm.entry = (kprobe_opcode_t*) jp_hrtimer_start; 587 break; 588 case CN_SCSI_DISPATCH_CMD: 589 lkdtm.kp.symbol_name = "scsi_dispatch_cmd"; 590 lkdtm.entry = (kprobe_opcode_t*) jp_scsi_dispatch_cmd; 591 break; 592 case CN_IDE_CORE_CP: 593#ifdef CONFIG_IDE 594 lkdtm.kp.symbol_name = "generic_ide_ioctl"; 595 lkdtm.entry = (kprobe_opcode_t*) jp_generic_ide_ioctl; 596#else 597 pr_info("Crash point not available\n"); 598 return -EINVAL; 599#endif 600 break; 601 default: 602 pr_info("Invalid Crash Point\n"); 603 return -EINVAL; 604 } 605 606 cpoint = which; 607 if ((ret = register_jprobe(&lkdtm)) < 0) { 608 pr_info("Couldn't register jprobe\n"); 609 cpoint = CN_INVALID; 610 } 611 612 return ret; 613} 614 615static ssize_t do_register_entry(enum cname which, struct file *f, 616 const char __user *user_buf, size_t count, loff_t *off) 617{ 618 char *buf; 619 int err; 620 621 if (count >= PAGE_SIZE) 622 return -EINVAL; 623 624 buf = (char *)__get_free_page(GFP_KERNEL); 625 if (!buf) 626 return -ENOMEM; 627 if (copy_from_user(buf, user_buf, count)) { 628 free_page((unsigned long) buf); 629 return -EFAULT; 630 } 631 /* NULL-terminate and remove enter */ 632 buf[count] = '\0'; 633 strim(buf); 634 635 cptype = parse_cp_type(buf, count); 636 free_page((unsigned long) buf); 637 638 if (cptype == CT_NONE) 639 return -EINVAL; 640 641 err = lkdtm_register_cpoint(which); 642 if (err < 0) 643 return err; 644 645 *off += count; 646 647 return count; 648} 649 650/* Generic read callback that just prints out the available crash types */ 651static ssize_t lkdtm_debugfs_read(struct file *f, char __user *user_buf, 652 size_t count, loff_t *off) 653{ 654 char *buf; 655 int i, n, out; 656 657 buf = (char *)__get_free_page(GFP_KERNEL); 658 if (buf == NULL) 659 return -ENOMEM; 660 661 n = snprintf(buf, PAGE_SIZE, "Available crash types:\n"); 662 for (i = 0; i < ARRAY_SIZE(cp_type); i++) 663 n += snprintf(buf + n, PAGE_SIZE - n, "%s\n", cp_type[i]); 664 buf[n] = '\0'; 665 666 out = simple_read_from_buffer(user_buf, count, off, 667 buf, n); 668 free_page((unsigned long) buf); 669 670 return out; 671} 672 673static int lkdtm_debugfs_open(struct inode *inode, struct file *file) 674{ 675 return 0; 676} 677 678 679static ssize_t int_hardware_entry(struct file *f, const char __user *buf, 680 size_t count, loff_t *off) 681{ 682 return do_register_entry(CN_INT_HARDWARE_ENTRY, f, buf, count, off); 683} 684 685static ssize_t int_hw_irq_en(struct file *f, const char __user *buf, 686 size_t count, loff_t *off) 687{ 688 return do_register_entry(CN_INT_HW_IRQ_EN, f, buf, count, off); 689} 690 691static ssize_t int_tasklet_entry(struct file *f, const char __user *buf, 692 size_t count, loff_t *off) 693{ 694 return do_register_entry(CN_INT_TASKLET_ENTRY, f, buf, count, off); 695} 696 697static ssize_t fs_devrw_entry(struct file *f, const char __user *buf, 698 size_t count, loff_t *off) 699{ 700 return do_register_entry(CN_FS_DEVRW, f, buf, count, off); 701} 702 703static ssize_t mem_swapout_entry(struct file *f, const char __user *buf, 704 size_t count, loff_t *off) 705{ 706 return do_register_entry(CN_MEM_SWAPOUT, f, buf, count, off); 707} 708 709static ssize_t timeradd_entry(struct file *f, const char __user *buf, 710 size_t count, loff_t *off) 711{ 712 return do_register_entry(CN_TIMERADD, f, buf, count, off); 713} 714 715static ssize_t scsi_dispatch_cmd_entry(struct file *f, 716 const char __user *buf, size_t count, loff_t *off) 717{ 718 return do_register_entry(CN_SCSI_DISPATCH_CMD, f, buf, count, off); 719} 720 721static ssize_t ide_core_cp_entry(struct file *f, const char __user *buf, 722 size_t count, loff_t *off) 723{ 724 return do_register_entry(CN_IDE_CORE_CP, f, buf, count, off); 725} 726 727/* Special entry to just crash directly. Available without KPROBEs */ 728static ssize_t direct_entry(struct file *f, const char __user *user_buf, 729 size_t count, loff_t *off) 730{ 731 enum ctype type; 732 char *buf; 733 734 if (count >= PAGE_SIZE) 735 return -EINVAL; 736 if (count < 1) 737 return -EINVAL; 738 739 buf = (char *)__get_free_page(GFP_KERNEL); 740 if (!buf) 741 return -ENOMEM; 742 if (copy_from_user(buf, user_buf, count)) { 743 free_page((unsigned long) buf); 744 return -EFAULT; 745 } 746 /* NULL-terminate and remove enter */ 747 buf[count] = '\0'; 748 strim(buf); 749 750 type = parse_cp_type(buf, count); 751 free_page((unsigned long) buf); 752 if (type == CT_NONE) 753 return -EINVAL; 754 755 pr_info("Performing direct entry %s\n", cp_type_to_str(type)); 756 lkdtm_do_action(type); 757 *off += count; 758 759 return count; 760} 761 762struct crash_entry { 763 const char *name; 764 const struct file_operations fops; 765}; 766 767static const struct crash_entry crash_entries[] = { 768 {"DIRECT", {.read = lkdtm_debugfs_read, 769 .llseek = generic_file_llseek, 770 .open = lkdtm_debugfs_open, 771 .write = direct_entry} }, 772 {"INT_HARDWARE_ENTRY", {.read = lkdtm_debugfs_read, 773 .llseek = generic_file_llseek, 774 .open = lkdtm_debugfs_open, 775 .write = int_hardware_entry} }, 776 {"INT_HW_IRQ_EN", {.read = lkdtm_debugfs_read, 777 .llseek = generic_file_llseek, 778 .open = lkdtm_debugfs_open, 779 .write = int_hw_irq_en} }, 780 {"INT_TASKLET_ENTRY", {.read = lkdtm_debugfs_read, 781 .llseek = generic_file_llseek, 782 .open = lkdtm_debugfs_open, 783 .write = int_tasklet_entry} }, 784 {"FS_DEVRW", {.read = lkdtm_debugfs_read, 785 .llseek = generic_file_llseek, 786 .open = lkdtm_debugfs_open, 787 .write = fs_devrw_entry} }, 788 {"MEM_SWAPOUT", {.read = lkdtm_debugfs_read, 789 .llseek = generic_file_llseek, 790 .open = lkdtm_debugfs_open, 791 .write = mem_swapout_entry} }, 792 {"TIMERADD", {.read = lkdtm_debugfs_read, 793 .llseek = generic_file_llseek, 794 .open = lkdtm_debugfs_open, 795 .write = timeradd_entry} }, 796 {"SCSI_DISPATCH_CMD", {.read = lkdtm_debugfs_read, 797 .llseek = generic_file_llseek, 798 .open = lkdtm_debugfs_open, 799 .write = scsi_dispatch_cmd_entry} }, 800 {"IDE_CORE_CP", {.read = lkdtm_debugfs_read, 801 .llseek = generic_file_llseek, 802 .open = lkdtm_debugfs_open, 803 .write = ide_core_cp_entry} }, 804}; 805 806static struct dentry *lkdtm_debugfs_root; 807 808static int __init lkdtm_module_init(void) 809{ 810 int ret = -EINVAL; 811 int n_debugfs_entries = 1; /* Assume only the direct entry */ 812 int i; 813 814 /* Register debugfs interface */ 815 lkdtm_debugfs_root = debugfs_create_dir("provoke-crash", NULL); 816 if (!lkdtm_debugfs_root) { 817 pr_err("creating root dir failed\n"); 818 return -ENODEV; 819 } 820 821#ifdef CONFIG_KPROBES 822 n_debugfs_entries = ARRAY_SIZE(crash_entries); 823#endif 824 825 for (i = 0; i < n_debugfs_entries; i++) { 826 const struct crash_entry *cur = &crash_entries[i]; 827 struct dentry *de; 828 829 de = debugfs_create_file(cur->name, 0644, lkdtm_debugfs_root, 830 NULL, &cur->fops); 831 if (de == NULL) { 832 pr_err("could not create %s\n", cur->name); 833 goto out_err; 834 } 835 } 836 837 if (lkdtm_parse_commandline() == -EINVAL) { 838 pr_info("Invalid command\n"); 839 goto out_err; 840 } 841 842 if (cpoint != CN_INVALID && cptype != CT_NONE) { 843 ret = lkdtm_register_cpoint(cpoint); 844 if (ret < 0) { 845 pr_info("Invalid crash point %d\n", cpoint); 846 goto out_err; 847 } 848 pr_info("Crash point %s of type %s registered\n", 849 cpoint_name, cpoint_type); 850 } else { 851 pr_info("No crash points registered, enable through debugfs\n"); 852 } 853 854 return 0; 855 856out_err: 857 debugfs_remove_recursive(lkdtm_debugfs_root); 858 return ret; 859} 860 861static void __exit lkdtm_module_exit(void) 862{ 863 debugfs_remove_recursive(lkdtm_debugfs_root); 864 865 unregister_jprobe(&lkdtm); 866 pr_info("Crash point unregistered\n"); 867} 868 869module_init(lkdtm_module_init); 870module_exit(lkdtm_module_exit); 871 872MODULE_LICENSE("GPL"); 873MODULE_DESCRIPTION("Kprobe module for testing crash dumps"); 874