diff options
-rw-r--r-- | Documentation/kernel-parameters.txt | 4 | ||||
-rw-r--r-- | init/main.c | 68 |
2 files changed, 72 insertions, 0 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index adea3a22fa00..9973a7e2e0ac 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt | |||
@@ -1312,6 +1312,10 @@ bytes respectively. Such letter suffixes can also be entirely omitted. | |||
1312 | for working out where the kernel is dying during | 1312 | for working out where the kernel is dying during |
1313 | startup. | 1313 | startup. |
1314 | 1314 | ||
1315 | initcall_blacklist= [KNL] Do not execute a comma-separated list of | ||
1316 | initcall functions. Useful for debugging built-in | ||
1317 | modules and initcalls. | ||
1318 | |||
1315 | initrd= [BOOT] Specify the location of the initial ramdisk | 1319 | initrd= [BOOT] Specify the location of the initial ramdisk |
1316 | 1320 | ||
1317 | inport.irq= [HW] Inport (ATI XL and Microsoft) busmouse driver | 1321 | inport.irq= [HW] Inport (ATI XL and Microsoft) busmouse driver |
diff --git a/init/main.c b/init/main.c index 9d3a7b84de5c..8ac3833f2bdf 100644 --- a/init/main.c +++ b/init/main.c | |||
@@ -77,6 +77,7 @@ | |||
77 | #include <linux/sched_clock.h> | 77 | #include <linux/sched_clock.h> |
78 | #include <linux/context_tracking.h> | 78 | #include <linux/context_tracking.h> |
79 | #include <linux/random.h> | 79 | #include <linux/random.h> |
80 | #include <linux/list.h> | ||
80 | 81 | ||
81 | #include <asm/io.h> | 82 | #include <asm/io.h> |
82 | #include <asm/bugs.h> | 83 | #include <asm/bugs.h> |
@@ -665,6 +666,70 @@ static void __init do_ctors(void) | |||
665 | bool initcall_debug; | 666 | bool initcall_debug; |
666 | core_param(initcall_debug, initcall_debug, bool, 0644); | 667 | core_param(initcall_debug, initcall_debug, bool, 0644); |
667 | 668 | ||
669 | #ifdef CONFIG_KALLSYMS | ||
670 | struct blacklist_entry { | ||
671 | struct list_head next; | ||
672 | char *buf; | ||
673 | }; | ||
674 | |||
675 | static __initdata_or_module LIST_HEAD(blacklisted_initcalls); | ||
676 | |||
677 | static int __init initcall_blacklist(char *str) | ||
678 | { | ||
679 | char *str_entry; | ||
680 | struct blacklist_entry *entry; | ||
681 | |||
682 | /* str argument is a comma-separated list of functions */ | ||
683 | do { | ||
684 | str_entry = strsep(&str, ","); | ||
685 | if (str_entry) { | ||
686 | pr_debug("blacklisting initcall %s\n", str_entry); | ||
687 | entry = alloc_bootmem(sizeof(*entry)); | ||
688 | entry->buf = alloc_bootmem(strlen(str_entry) + 1); | ||
689 | strcpy(entry->buf, str_entry); | ||
690 | list_add(&entry->next, &blacklisted_initcalls); | ||
691 | } | ||
692 | } while (str_entry); | ||
693 | |||
694 | return 0; | ||
695 | } | ||
696 | |||
697 | static bool __init_or_module initcall_blacklisted(initcall_t fn) | ||
698 | { | ||
699 | struct list_head *tmp; | ||
700 | struct blacklist_entry *entry; | ||
701 | char *fn_name; | ||
702 | |||
703 | fn_name = kasprintf(GFP_KERNEL, "%pf", fn); | ||
704 | if (!fn_name) | ||
705 | return false; | ||
706 | |||
707 | list_for_each(tmp, &blacklisted_initcalls) { | ||
708 | entry = list_entry(tmp, struct blacklist_entry, next); | ||
709 | if (!strcmp(fn_name, entry->buf)) { | ||
710 | pr_debug("initcall %s blacklisted\n", fn_name); | ||
711 | kfree(fn_name); | ||
712 | return true; | ||
713 | } | ||
714 | } | ||
715 | |||
716 | kfree(fn_name); | ||
717 | return false; | ||
718 | } | ||
719 | #else | ||
720 | static int __init initcall_blacklist(char *str) | ||
721 | { | ||
722 | pr_warn("initcall_blacklist requires CONFIG_KALLSYMS\n"); | ||
723 | return 0; | ||
724 | } | ||
725 | |||
726 | static bool __init_or_module initcall_blacklisted(initcall_t fn) | ||
727 | { | ||
728 | return false; | ||
729 | } | ||
730 | #endif | ||
731 | __setup("initcall_blacklist=", initcall_blacklist); | ||
732 | |||
668 | static int __init_or_module do_one_initcall_debug(initcall_t fn) | 733 | static int __init_or_module do_one_initcall_debug(initcall_t fn) |
669 | { | 734 | { |
670 | ktime_t calltime, delta, rettime; | 735 | ktime_t calltime, delta, rettime; |
@@ -689,6 +754,9 @@ int __init_or_module do_one_initcall(initcall_t fn) | |||
689 | int ret; | 754 | int ret; |
690 | char msgbuf[64]; | 755 | char msgbuf[64]; |
691 | 756 | ||
757 | if (initcall_blacklisted(fn)) | ||
758 | return -EPERM; | ||
759 | |||
692 | if (initcall_debug) | 760 | if (initcall_debug) |
693 | ret = do_one_initcall_debug(fn); | 761 | ret = do_one_initcall_debug(fn); |
694 | else | 762 | else |