summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2008-05-04 17:04:16 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2008-05-04 17:04:16 -0700
commit826e4506a0acb6487910a5ebafe839f708a00e1c (patch)
tree20cc66b6b38c0414930d85a8a9705a3a3eff8ddf
parentafa26be86b65a7183ceac29bdf1f51d6fc6932f0 (diff)
downloadlinux-stable-826e4506a0acb6487910a5ebafe839f708a00e1c.tar.gz
linux-stable-826e4506a0acb6487910a5ebafe839f708a00e1c.tar.bz2
linux-stable-826e4506a0acb6487910a5ebafe839f708a00e1c.zip
Make forced module loading optional
The kernel module loader used to be much too happy to allow loading of modules for the wrong kernel version by default. For example, if you had MODVERSIONS enabled, but tried to load a module with no version info, it would happily load it and taint the kernel - whether it was likely to actually work or not! Generally, such forced module loading should be considered a really really bad idea, so make it conditional on a new config option (MODULE_FORCE_LOAD), and make it default to off. If somebody really wants to force module loads, that's their problem, but we should not encourage it. Especially as it happened to me by mistake (ie regular unversioned Fedora modules getting loaded) causing lots of strange behavior. Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--init/Kconfig9
-rw-r--r--kernel/module.c44
2 files changed, 38 insertions, 15 deletions
diff --git a/init/Kconfig b/init/Kconfig
index 6a44defac3ec..f0e62e5ce0dc 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -825,6 +825,15 @@ menuconfig MODULES
If unsure, say Y.
+config MODULE_FORCE_LOAD
+ bool "Forced module loading"
+ depends on MODULES
+ default n
+ help
+ This option allows loading of modules even if that would set the
+ 'F' (forced) taint, due to lack of version info. Which is
+ usually a really bad idea.
+
config MODULE_UNLOAD
bool "Module unloading"
depends on MODULES
diff --git a/kernel/module.c b/kernel/module.c
index 8674a390a2e8..8e4528c9909f 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -890,6 +890,19 @@ static struct module_attribute *modinfo_attrs[] = {
static const char vermagic[] = VERMAGIC_STRING;
+static int try_to_force_load(struct module *mod, const char *symname)
+{
+#ifdef CONFIG_MODULE_FORCE_LOAD
+ if (!(tainted & TAINT_FORCED_MODULE))
+ printk("%s: no version for \"%s\" found: kernel tainted.\n",
+ mod->name, symname);
+ add_taint_module(mod, TAINT_FORCED_MODULE);
+ return 0;
+#else
+ return -ENOEXEC;
+#endif
+}
+
#ifdef CONFIG_MODVERSIONS
static int check_version(Elf_Shdr *sechdrs,
unsigned int versindex,
@@ -914,18 +927,18 @@ static int check_version(Elf_Shdr *sechdrs,
if (versions[i].crc == *crc)
return 1;
- printk("%s: disagrees about version of symbol %s\n",
- mod->name, symname);
DEBUGP("Found checksum %lX vs module %lX\n",
*crc, versions[i].crc);
- return 0;
+ goto bad_version;
}
- /* Not in module's version table. OK, but that taints the kernel. */
- if (!(tainted & TAINT_FORCED_MODULE))
- printk("%s: no version for \"%s\" found: kernel tainted.\n",
- mod->name, symname);
- add_taint_module(mod, TAINT_FORCED_MODULE);
- return 1;
+
+ if (!try_to_force_load(mod, symname))
+ return 1;
+
+bad_version:
+ printk("%s: disagrees about version of symbol %s\n",
+ mod->name, symname);
+ return 0;
}
static inline int check_modstruct_version(Elf_Shdr *sechdrs,
@@ -1853,9 +1866,9 @@ static struct module *load_module(void __user *umod,
modmagic = get_modinfo(sechdrs, infoindex, "vermagic");
/* This is allowed: modprobe --force will invalidate it. */
if (!modmagic) {
- add_taint_module(mod, TAINT_FORCED_MODULE);
- printk(KERN_WARNING "%s: no version magic, tainting kernel.\n",
- mod->name);
+ err = try_to_force_load(mod, "magic");
+ if (err)
+ goto free_hdr;
} else if (!same_magic(modmagic, vermagic)) {
printk(KERN_ERR "%s: version magic '%s' should be '%s'\n",
mod->name, modmagic, vermagic);
@@ -2006,9 +2019,10 @@ static struct module *load_module(void __user *umod,
(mod->num_gpl_future_syms && !gplfuturecrcindex) ||
(mod->num_unused_syms && !unusedcrcindex) ||
(mod->num_unused_gpl_syms && !unusedgplcrcindex)) {
- printk(KERN_WARNING "%s: No versions for exported symbols."
- " Tainting kernel.\n", mod->name);
- add_taint_module(mod, TAINT_FORCED_MODULE);
+ printk(KERN_WARNING "%s: No versions for exported symbols.\n", mod->name);
+ err = try_to_force_load(mod, "nocrc");
+ if (err)
+ goto cleanup;
}
#endif
markersindex = find_sec(hdr, sechdrs, secstrings, "__markers");