diff options
Diffstat (limited to 'drivers/misc/lkdtm.c')
-rw-r--r-- | drivers/misc/lkdtm.c | 74 |
1 files changed, 57 insertions, 17 deletions
diff --git a/drivers/misc/lkdtm.c b/drivers/misc/lkdtm.c index 49c7a23f02fc..d66a2f24f6b3 100644 --- a/drivers/misc/lkdtm.c +++ b/drivers/misc/lkdtm.c | |||
@@ -30,6 +30,7 @@ | |||
30 | * | 30 | * |
31 | * See Documentation/fault-injection/provoke-crashes.txt for instructions | 31 | * See Documentation/fault-injection/provoke-crashes.txt for instructions |
32 | */ | 32 | */ |
33 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
33 | 34 | ||
34 | #include <linux/kernel.h> | 35 | #include <linux/kernel.h> |
35 | #include <linux/fs.h> | 36 | #include <linux/fs.h> |
@@ -45,6 +46,7 @@ | |||
45 | #include <linux/debugfs.h> | 46 | #include <linux/debugfs.h> |
46 | #include <linux/vmalloc.h> | 47 | #include <linux/vmalloc.h> |
47 | #include <linux/mman.h> | 48 | #include <linux/mman.h> |
49 | #include <asm/cacheflush.h> | ||
48 | 50 | ||
49 | #ifdef CONFIG_IDE | 51 | #ifdef CONFIG_IDE |
50 | #include <linux/ide.h> | 52 | #include <linux/ide.h> |
@@ -101,6 +103,7 @@ enum ctype { | |||
101 | CT_EXEC_USERSPACE, | 103 | CT_EXEC_USERSPACE, |
102 | CT_ACCESS_USERSPACE, | 104 | CT_ACCESS_USERSPACE, |
103 | CT_WRITE_RO, | 105 | CT_WRITE_RO, |
106 | CT_WRITE_KERN, | ||
104 | }; | 107 | }; |
105 | 108 | ||
106 | static char* cp_name[] = { | 109 | static char* cp_name[] = { |
@@ -137,6 +140,7 @@ static char* cp_type[] = { | |||
137 | "EXEC_USERSPACE", | 140 | "EXEC_USERSPACE", |
138 | "ACCESS_USERSPACE", | 141 | "ACCESS_USERSPACE", |
139 | "WRITE_RO", | 142 | "WRITE_RO", |
143 | "WRITE_KERN", | ||
140 | }; | 144 | }; |
141 | 145 | ||
142 | static struct jprobe lkdtm; | 146 | static struct jprobe lkdtm; |
@@ -316,6 +320,13 @@ static void do_nothing(void) | |||
316 | return; | 320 | return; |
317 | } | 321 | } |
318 | 322 | ||
323 | /* Must immediately follow do_nothing for size calculuations to work out. */ | ||
324 | static void do_overwritten(void) | ||
325 | { | ||
326 | pr_info("do_overwritten wasn't overwritten!\n"); | ||
327 | return; | ||
328 | } | ||
329 | |||
319 | static noinline void corrupt_stack(void) | 330 | static noinline void corrupt_stack(void) |
320 | { | 331 | { |
321 | /* Use default char array length that triggers stack protection. */ | 332 | /* Use default char array length that triggers stack protection. */ |
@@ -328,7 +339,12 @@ static void execute_location(void *dst) | |||
328 | { | 339 | { |
329 | void (*func)(void) = dst; | 340 | void (*func)(void) = dst; |
330 | 341 | ||
342 | pr_info("attempting ok execution at %p\n", do_nothing); | ||
343 | do_nothing(); | ||
344 | |||
331 | memcpy(dst, do_nothing, EXEC_SIZE); | 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); | ||
332 | func(); | 348 | func(); |
333 | } | 349 | } |
334 | 350 | ||
@@ -337,8 +353,13 @@ static void execute_user_location(void *dst) | |||
337 | /* Intentionally crossing kernel/user memory boundary. */ | 353 | /* Intentionally crossing kernel/user memory boundary. */ |
338 | void (*func)(void) = dst; | 354 | void (*func)(void) = dst; |
339 | 355 | ||
356 | pr_info("attempting ok execution at %p\n", do_nothing); | ||
357 | do_nothing(); | ||
358 | |||
340 | if (copy_to_user((void __user *)dst, do_nothing, EXEC_SIZE)) | 359 | if (copy_to_user((void __user *)dst, do_nothing, EXEC_SIZE)) |
341 | return; | 360 | return; |
361 | flush_icache_range((unsigned long)dst, (unsigned long)dst + EXEC_SIZE); | ||
362 | pr_info("attempting bad execution at %p\n", func); | ||
342 | func(); | 363 | func(); |
343 | } | 364 | } |
344 | 365 | ||
@@ -463,8 +484,12 @@ static void lkdtm_do_action(enum ctype which) | |||
463 | } | 484 | } |
464 | 485 | ||
465 | ptr = (unsigned long *)user_addr; | 486 | ptr = (unsigned long *)user_addr; |
487 | |||
488 | pr_info("attempting bad read at %p\n", ptr); | ||
466 | tmp = *ptr; | 489 | tmp = *ptr; |
467 | tmp += 0xc0dec0de; | 490 | tmp += 0xc0dec0de; |
491 | |||
492 | pr_info("attempting bad write at %p\n", ptr); | ||
468 | *ptr = tmp; | 493 | *ptr = tmp; |
469 | 494 | ||
470 | vm_munmap(user_addr, PAGE_SIZE); | 495 | vm_munmap(user_addr, PAGE_SIZE); |
@@ -475,10 +500,28 @@ static void lkdtm_do_action(enum ctype which) | |||
475 | unsigned long *ptr; | 500 | unsigned long *ptr; |
476 | 501 | ||
477 | ptr = (unsigned long *)&rodata; | 502 | ptr = (unsigned long *)&rodata; |
503 | |||
504 | pr_info("attempting bad write at %p\n", ptr); | ||
478 | *ptr ^= 0xabcd1234; | 505 | *ptr ^= 0xabcd1234; |
479 | 506 | ||
480 | break; | 507 | break; |
481 | } | 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 | } | ||
482 | case CT_NONE: | 525 | case CT_NONE: |
483 | default: | 526 | default: |
484 | break; | 527 | break; |
@@ -493,8 +536,8 @@ static void lkdtm_handler(void) | |||
493 | 536 | ||
494 | spin_lock_irqsave(&count_lock, flags); | 537 | spin_lock_irqsave(&count_lock, flags); |
495 | count--; | 538 | count--; |
496 | printk(KERN_INFO "lkdtm: Crash point %s of type %s hit, trigger in %d rounds\n", | 539 | pr_info("Crash point %s of type %s hit, trigger in %d rounds\n", |
497 | cp_name_to_str(cpoint), cp_type_to_str(cptype), count); | 540 | cp_name_to_str(cpoint), cp_type_to_str(cptype), count); |
498 | 541 | ||
499 | if (count == 0) { | 542 | if (count == 0) { |
500 | do_it = true; | 543 | do_it = true; |
@@ -551,18 +594,18 @@ static int lkdtm_register_cpoint(enum cname which) | |||
551 | lkdtm.kp.symbol_name = "generic_ide_ioctl"; | 594 | lkdtm.kp.symbol_name = "generic_ide_ioctl"; |
552 | lkdtm.entry = (kprobe_opcode_t*) jp_generic_ide_ioctl; | 595 | lkdtm.entry = (kprobe_opcode_t*) jp_generic_ide_ioctl; |
553 | #else | 596 | #else |
554 | printk(KERN_INFO "lkdtm: Crash point not available\n"); | 597 | pr_info("Crash point not available\n"); |
555 | return -EINVAL; | 598 | return -EINVAL; |
556 | #endif | 599 | #endif |
557 | break; | 600 | break; |
558 | default: | 601 | default: |
559 | printk(KERN_INFO "lkdtm: Invalid Crash Point\n"); | 602 | pr_info("Invalid Crash Point\n"); |
560 | return -EINVAL; | 603 | return -EINVAL; |
561 | } | 604 | } |
562 | 605 | ||
563 | cpoint = which; | 606 | cpoint = which; |
564 | if ((ret = register_jprobe(&lkdtm)) < 0) { | 607 | if ((ret = register_jprobe(&lkdtm)) < 0) { |
565 | printk(KERN_INFO "lkdtm: Couldn't register jprobe\n"); | 608 | pr_info("Couldn't register jprobe\n"); |
566 | cpoint = CN_INVALID; | 609 | cpoint = CN_INVALID; |
567 | } | 610 | } |
568 | 611 | ||
@@ -709,8 +752,7 @@ static ssize_t direct_entry(struct file *f, const char __user *user_buf, | |||
709 | if (type == CT_NONE) | 752 | if (type == CT_NONE) |
710 | return -EINVAL; | 753 | return -EINVAL; |
711 | 754 | ||
712 | printk(KERN_INFO "lkdtm: Performing direct entry %s\n", | 755 | pr_info("Performing direct entry %s\n", cp_type_to_str(type)); |
713 | cp_type_to_str(type)); | ||
714 | lkdtm_do_action(type); | 756 | lkdtm_do_action(type); |
715 | *off += count; | 757 | *off += count; |
716 | 758 | ||
@@ -772,7 +814,7 @@ static int __init lkdtm_module_init(void) | |||
772 | /* Register debugfs interface */ | 814 | /* Register debugfs interface */ |
773 | lkdtm_debugfs_root = debugfs_create_dir("provoke-crash", NULL); | 815 | lkdtm_debugfs_root = debugfs_create_dir("provoke-crash", NULL); |
774 | if (!lkdtm_debugfs_root) { | 816 | if (!lkdtm_debugfs_root) { |
775 | printk(KERN_ERR "lkdtm: creating root dir failed\n"); | 817 | pr_err("creating root dir failed\n"); |
776 | return -ENODEV; | 818 | return -ENODEV; |
777 | } | 819 | } |
778 | 820 | ||
@@ -787,28 +829,26 @@ static int __init lkdtm_module_init(void) | |||
787 | de = debugfs_create_file(cur->name, 0644, lkdtm_debugfs_root, | 829 | de = debugfs_create_file(cur->name, 0644, lkdtm_debugfs_root, |
788 | NULL, &cur->fops); | 830 | NULL, &cur->fops); |
789 | if (de == NULL) { | 831 | if (de == NULL) { |
790 | printk(KERN_ERR "lkdtm: could not create %s\n", | 832 | pr_err("could not create %s\n", cur->name); |
791 | cur->name); | ||
792 | goto out_err; | 833 | goto out_err; |
793 | } | 834 | } |
794 | } | 835 | } |
795 | 836 | ||
796 | if (lkdtm_parse_commandline() == -EINVAL) { | 837 | if (lkdtm_parse_commandline() == -EINVAL) { |
797 | printk(KERN_INFO "lkdtm: Invalid command\n"); | 838 | pr_info("Invalid command\n"); |
798 | goto out_err; | 839 | goto out_err; |
799 | } | 840 | } |
800 | 841 | ||
801 | if (cpoint != CN_INVALID && cptype != CT_NONE) { | 842 | if (cpoint != CN_INVALID && cptype != CT_NONE) { |
802 | ret = lkdtm_register_cpoint(cpoint); | 843 | ret = lkdtm_register_cpoint(cpoint); |
803 | if (ret < 0) { | 844 | if (ret < 0) { |
804 | printk(KERN_INFO "lkdtm: Invalid crash point %d\n", | 845 | pr_info("Invalid crash point %d\n", cpoint); |
805 | cpoint); | ||
806 | goto out_err; | 846 | goto out_err; |
807 | } | 847 | } |
808 | printk(KERN_INFO "lkdtm: Crash point %s of type %s registered\n", | 848 | pr_info("Crash point %s of type %s registered\n", |
809 | cpoint_name, cpoint_type); | 849 | cpoint_name, cpoint_type); |
810 | } else { | 850 | } else { |
811 | printk(KERN_INFO "lkdtm: No crash points registered, enable through debugfs\n"); | 851 | pr_info("No crash points registered, enable through debugfs\n"); |
812 | } | 852 | } |
813 | 853 | ||
814 | return 0; | 854 | return 0; |
@@ -823,7 +863,7 @@ static void __exit lkdtm_module_exit(void) | |||
823 | debugfs_remove_recursive(lkdtm_debugfs_root); | 863 | debugfs_remove_recursive(lkdtm_debugfs_root); |
824 | 864 | ||
825 | unregister_jprobe(&lkdtm); | 865 | unregister_jprobe(&lkdtm); |
826 | printk(KERN_INFO "lkdtm: Crash point unregistered\n"); | 866 | pr_info("Crash point unregistered\n"); |
827 | } | 867 | } |
828 | 868 | ||
829 | module_init(lkdtm_module_init); | 869 | module_init(lkdtm_module_init); |