summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--kernel/module.c31
-rw-r--r--scripts/modpost.c13
2 files changed, 44 insertions, 0 deletions
diff --git a/kernel/module.c b/kernel/module.c
index 3e36848e0702..00d8b07c4fd1 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -771,6 +771,18 @@ static int check_version(Elf_Shdr *sechdrs,
return 1;
}
+static inline int check_modstruct_version(Elf_Shdr *sechdrs,
+ unsigned int versindex,
+ struct module *mod)
+{
+ unsigned int i;
+ struct kernel_symbol_group *ksg;
+
+ if (!__find_symbol("struct_module", &ksg, &i, 1))
+ BUG();
+ return check_version(sechdrs, versindex, "struct_module", mod, ksg, i);
+}
+
/* First part is kernel version, which we ignore. */
static inline int same_magic(const char *amagic, const char *bmagic)
{
@@ -789,6 +801,13 @@ static inline int check_version(Elf_Shdr *sechdrs,
return 1;
}
+static inline int check_modstruct_version(Elf_Shdr *sechdrs,
+ unsigned int versindex,
+ struct module *mod)
+{
+ return 1;
+}
+
static inline int same_magic(const char *amagic, const char *bmagic)
{
return strcmp(amagic, bmagic) == 0;
@@ -1185,6 +1204,12 @@ static struct module *load_module(void *umod,
}
mod = (void *)sechdrs[modindex].sh_addr;
+ /* Check module struct version now, before we try to use module. */
+ if (!check_modstruct_version(sechdrs, versindex, mod)) {
+ err = -ENOEXEC;
+ goto free_hdr;
+ }
+
/* This is allowed: modprobe --force will invalidate it. */
if (!vmagindex) {
tainted |= TAINT_FORCED_MODULE;
@@ -1630,3 +1655,9 @@ static int __init symbols_init(void)
}
__initcall(symbols_init);
+
+#ifdef CONFIG_MODVERSIONS
+/* Generate the signature for struct module here, too, for modversions. */
+void struct_module(struct module *mod) { return; }
+EXPORT_SYMBOL(struct_module);
+#endif
diff --git a/scripts/modpost.c b/scripts/modpost.c
index 5b21b7a27353..6da8241ce7a6 100644
--- a/scripts/modpost.c
+++ b/scripts/modpost.c
@@ -308,6 +308,7 @@ read_symbols(char *modname)
const char *symname;
struct module *mod;
struct elf_info info = { };
+ struct symbol *s;
Elf_Sym *sym;
/* When there's no vmlinux, don't print warnings about
@@ -326,6 +327,17 @@ read_symbols(char *modname)
handle_moddevtable(mod, &info, sym, symname);
}
parse_elf_finish(&info);
+
+ /* Our trick to get versioning for struct_module - it's
+ * never passed as an argument to an exported function, so
+ * the automatic versioning doesn't pick it up, but it's really
+ * important anyhow */
+ if (modversions) {
+ s = alloc_symbol("struct_module");
+ /* add to list */
+ s->next = mod->unres;
+ mod->unres = s;
+ }
}
#define SZ 500
@@ -502,6 +514,7 @@ main(int argc, char **argv)
{
struct module *mod;
struct buffer buf = { };
+ struct symbol *s;
char fname[SZ];
for (; argv[1]; argv++) {