Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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