]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - init/main.c
init/main.c: add initcall_blacklist kernel parameter
[karo-tx-linux.git] / init / main.c
index 48655ceb66f45cdf27cf8bf769d9de296175a21c..8ac3833f2bdf62552030757de13916e9bc6d1011 100644 (file)
@@ -77,6 +77,7 @@
 #include <linux/sched_clock.h>
 #include <linux/context_tracking.h>
 #include <linux/random.h>
+#include <linux/list.h>
 
 #include <asm/io.h>
 #include <asm/bugs.h>
@@ -203,13 +204,13 @@ EXPORT_SYMBOL(loops_per_jiffy);
 
 static int __init debug_kernel(char *str)
 {
-       console_loglevel = 10;
+       console_loglevel = CONSOLE_LOGLEVEL_DEBUG;
        return 0;
 }
 
 static int __init quiet_kernel(char *str)
 {
-       console_loglevel = 4;
+       console_loglevel = CONSOLE_LOGLEVEL_QUIET;
        return 0;
 }
 
@@ -507,7 +508,6 @@ asmlinkage __visible void __init start_kernel(void)
        page_address_init();
        pr_notice("%s", linux_banner);
        setup_arch(&command_line);
-       mm_init_owner(&init_mm, &init_task);
        mm_init_cpumask(&init_mm);
        setup_command_line(command_line);
        setup_nr_cpu_ids();
@@ -666,19 +666,83 @@ static void __init do_ctors(void)
 bool initcall_debug;
 core_param(initcall_debug, initcall_debug, bool, 0644);
 
+#ifdef CONFIG_KALLSYMS
+struct blacklist_entry {
+       struct list_head next;
+       char *buf;
+};
+
+static __initdata_or_module LIST_HEAD(blacklisted_initcalls);
+
+static int __init initcall_blacklist(char *str)
+{
+       char *str_entry;
+       struct blacklist_entry *entry;
+
+       /* str argument is a comma-separated list of functions */
+       do {
+               str_entry = strsep(&str, ",");
+               if (str_entry) {
+                       pr_debug("blacklisting initcall %s\n", str_entry);
+                       entry = alloc_bootmem(sizeof(*entry));
+                       entry->buf = alloc_bootmem(strlen(str_entry) + 1);
+                       strcpy(entry->buf, str_entry);
+                       list_add(&entry->next, &blacklisted_initcalls);
+               }
+       } while (str_entry);
+
+       return 0;
+}
+
+static bool __init_or_module initcall_blacklisted(initcall_t fn)
+{
+       struct list_head *tmp;
+       struct blacklist_entry *entry;
+       char *fn_name;
+
+       fn_name = kasprintf(GFP_KERNEL, "%pf", fn);
+       if (!fn_name)
+               return false;
+
+       list_for_each(tmp, &blacklisted_initcalls) {
+               entry = list_entry(tmp, struct blacklist_entry, next);
+               if (!strcmp(fn_name, entry->buf)) {
+                       pr_debug("initcall %s blacklisted\n", fn_name);
+                       kfree(fn_name);
+                       return true;
+               }
+       }
+
+       kfree(fn_name);
+       return false;
+}
+#else
+static int __init initcall_blacklist(char *str)
+{
+       pr_warn("initcall_blacklist requires CONFIG_KALLSYMS\n");
+       return 0;
+}
+
+static bool __init_or_module initcall_blacklisted(initcall_t fn)
+{
+       return false;
+}
+#endif
+__setup("initcall_blacklist=", initcall_blacklist);
+
 static int __init_or_module do_one_initcall_debug(initcall_t fn)
 {
        ktime_t calltime, delta, rettime;
        unsigned long long duration;
        int ret;
 
-       pr_debug("calling  %pF @ %i\n", fn, task_pid_nr(current));
+       printk(KERN_DEBUG "calling  %pF @ %i\n", fn, task_pid_nr(current));
        calltime = ktime_get();
        ret = fn();
        rettime = ktime_get();
        delta = ktime_sub(rettime, calltime);
        duration = (unsigned long long) ktime_to_ns(delta) >> 10;
-       pr_debug("initcall %pF returned %d after %lld usecs\n",
+       printk(KERN_DEBUG "initcall %pF returned %d after %lld usecs\n",
                 fn, ret, duration);
 
        return ret;
@@ -690,6 +754,9 @@ int __init_or_module do_one_initcall(initcall_t fn)
        int ret;
        char msgbuf[64];
 
+       if (initcall_blacklisted(fn))
+               return -EPERM;
+
        if (initcall_debug)
                ret = do_one_initcall_debug(fn);
        else