modules: Add kernel parameter to blacklist modules
authorPrarit Bhargava <prarit@redhat.com>
Thu, 21 Jul 2016 06:07:56 +0000 (15:37 +0930)
committerRusty Russell <rusty@rustcorp.com.au>
Thu, 4 Aug 2016 00:46:53 +0000 (10:16 +0930)
Blacklisting a module in linux has long been a problem.  The current
procedure is to use rd.blacklist=module_name, however, that doesn't
cover the case after the initramfs and before a boot prompt (where one
is supposed to use /etc/modprobe.d/blacklist.conf to blacklist
runtime loading). Using rd.shell to get an early prompt is hit-or-miss,
and doesn't cover all situations AFAICT.

This patch adds this functionality of permanently blacklisting a module
by its name via the kernel parameter module_blacklist=module_name.

[v2]: Rusty, use core_param() instead of __setup() which simplifies
things.

[v3]: Rusty, undo wreckage from strsep()

[v4]: Rusty, simpler version of blacklisted()

Signed-off-by: Prarit Bhargava <prarit@redhat.com>
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: Rusty Russell <rusty@rustcorp.com.au>
Cc: linux-doc@vger.kernel.org
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Documentation/kernel-parameters.txt
kernel/module.c

index 724970a..c59ae1a 100644 (file)
@@ -2301,6 +2301,9 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
                        Note that if CONFIG_MODULE_SIG_FORCE is set, that
                        is always true, so this option does nothing.
 
+       module_blacklist=  [KNL] Do not load a comma-separated list of
+                       modules.  Useful for debugging problem modules.
+
        mousedev.tap_time=
                        [MOUSE] Maximum time between finger touching and
                        leaving touchpad surface for touch to be considered
index beaebea..c91c2fd 100644 (file)
@@ -3168,6 +3168,27 @@ int __weak module_frob_arch_sections(Elf_Ehdr *hdr,
        return 0;
 }
 
+/* module_blacklist is a comma-separated list of module names */
+static char *module_blacklist;
+static bool blacklisted(char *module_name)
+{
+       const char *p;
+       size_t len;
+
+       if (!module_blacklist)
+               return false;
+
+       for (p = module_blacklist; *p; p += len) {
+               len = strcspn(p, ",");
+               if (strlen(module_name) == len && !memcmp(module_name, p, len))
+                       return true;
+               if (p[len] == ',')
+                       len++;
+       }
+       return false;
+}
+core_param(module_blacklist, module_blacklist, charp, 0400);
+
 static struct module *layout_and_allocate(struct load_info *info, int flags)
 {
        /* Module within temporary copy. */
@@ -3178,6 +3199,9 @@ static struct module *layout_and_allocate(struct load_info *info, int flags)
        if (IS_ERR(mod))
                return mod;
 
+       if (blacklisted(mod->name))
+               return ERR_PTR(-EPERM);
+
        err = check_modinfo(mod, info, flags);
        if (err)
                return ERR_PTR(err);