module: Move version support into a separate file
authorAaron Tomlin <atomlin@redhat.com>
Tue, 22 Mar 2022 14:03:44 +0000 (14:03 +0000)
committerLuis Chamberlain <mcgrof@kernel.org>
Tue, 5 Apr 2022 15:43:04 +0000 (08:43 -0700)
No functional change.

This patch migrates module version support out of core code into
kernel/module/version.c. In addition simple code refactoring to
make this possible.

Reviewed-by: Christophe Leroy <christophe.leroy@csgroup.eu>
Signed-off-by: Aaron Tomlin <atomlin@redhat.com>
Signed-off-by: Luis Chamberlain <mcgrof@kernel.org>
kernel/module/Makefile
kernel/module/internal.h
kernel/module/main.c
kernel/module/version.c [new file with mode: 0644]

index 88f5cdc..e2eff98 100644 (file)
@@ -18,3 +18,4 @@ obj-$(CONFIG_KALLSYMS) += kallsyms.o
 obj-$(CONFIG_PROC_FS) += procfs.o
 obj-$(CONFIG_SYSFS) += sysfs.o
 obj-$(CONFIG_KGDB_KDB) += kdb.o
+obj-$(CONFIG_MODVERSIONS) += version.o
index 62d749e..3fc139d 100644 (file)
@@ -70,7 +70,27 @@ struct load_info {
        } index;
 };
 
+enum mod_license {
+       NOT_GPL_ONLY,
+       GPL_ONLY,
+};
+
+struct find_symbol_arg {
+       /* Input */
+       const char *name;
+       bool gplok;
+       bool warn;
+
+       /* Output */
+       struct module *owner;
+       const s32 *crc;
+       const struct kernel_symbol *sym;
+       enum mod_license license;
+};
+
 int mod_verify_sig(const void *mod, struct load_info *info);
+int try_to_force_load(struct module *mod, const char *reason);
+bool find_symbol(struct find_symbol_arg *fsa);
 struct module *find_module_all(const char *name, size_t len, bool even_unformed);
 int cmp_name(const void *name, const void *sym);
 long module_get_offset(struct module *mod, unsigned int *size, Elf_Shdr *sechdr,
@@ -225,3 +245,31 @@ static inline int mod_sysfs_setup(struct module *mod,
 static inline void mod_sysfs_teardown(struct module *mod) { }
 static inline void init_param_lock(struct module *mod) { }
 #endif /* CONFIG_SYSFS */
+
+#ifdef CONFIG_MODVERSIONS
+int check_version(const struct load_info *info,
+                 const char *symname, struct module *mod, const s32 *crc);
+void module_layout(struct module *mod, struct modversion_info *ver, struct kernel_param *kp,
+                  struct kernel_symbol *ks, struct tracepoint * const *tp);
+int check_modstruct_version(const struct load_info *info, struct module *mod);
+int same_magic(const char *amagic, const char *bmagic, bool has_crcs);
+#else /* !CONFIG_MODVERSIONS */
+static inline int check_version(const struct load_info *info,
+                               const char *symname,
+                               struct module *mod,
+                               const s32 *crc)
+{
+       return 1;
+}
+
+static inline int check_modstruct_version(const struct load_info *info,
+                                         struct module *mod)
+{
+       return 1;
+}
+
+static inline int same_magic(const char *amagic, const char *bmagic, bool has_crcs)
+{
+       return strcmp(amagic, bmagic) == 0;
+}
+#endif /* CONFIG_MODVERSIONS */
index a2dc547..5f06c06 100644 (file)
@@ -86,6 +86,12 @@ struct mod_tree_root mod_tree __cacheline_aligned = {
 static unsigned long module_addr_min = -1UL, module_addr_max;
 #endif /* CONFIG_MODULES_TREE_LOOKUP */
 
+struct symsearch {
+       const struct kernel_symbol *start, *stop;
+       const s32 *crcs;
+       enum mod_license license;
+};
+
 /*
  * Bounds of module text, for speeding up __module_address.
  * Protected by module_mutex.
@@ -244,28 +250,6 @@ static __maybe_unused void *any_section_objs(const struct load_info *info,
 #define symversion(base, idx) ((base != NULL) ? ((base) + (idx)) : NULL)
 #endif
 
-struct symsearch {
-       const struct kernel_symbol *start, *stop;
-       const s32 *crcs;
-       enum mod_license {
-               NOT_GPL_ONLY,
-               GPL_ONLY,
-       } license;
-};
-
-struct find_symbol_arg {
-       /* Input */
-       const char *name;
-       bool gplok;
-       bool warn;
-
-       /* Output */
-       struct module *owner;
-       const s32 *crc;
-       const struct kernel_symbol *sym;
-       enum mod_license license;
-};
-
 static bool check_exported_symbol(const struct symsearch *syms,
                                  struct module *owner,
                                  unsigned int symnum, void *data)
@@ -327,7 +311,7 @@ static bool find_exported_symbol_in_section(const struct symsearch *syms,
  * Find an exported symbol and return it, along with, (optional) crc and
  * (optional) module which owns it.  Needs preempt disabled or module_mutex.
  */
-static bool find_symbol(struct find_symbol_arg *fsa)
+bool find_symbol(struct find_symbol_arg *fsa)
 {
        static const struct symsearch arr[] = {
                { __start___ksymtab, __stop___ksymtab, __start___kcrctab,
@@ -1001,7 +985,7 @@ size_t modinfo_attrs_count = ARRAY_SIZE(modinfo_attrs);
 
 static const char vermagic[] = VERMAGIC_STRING;
 
-static int try_to_force_load(struct module *mod, const char *reason)
+int try_to_force_load(struct module *mod, const char *reason)
 {
 #ifdef CONFIG_MODULE_FORCE_LOAD
        if (!test_taint(TAINT_FORCED_MODULE))
@@ -1013,115 +997,6 @@ static int try_to_force_load(struct module *mod, const char *reason)
 #endif
 }
 
-#ifdef CONFIG_MODVERSIONS
-
-static u32 resolve_rel_crc(const s32 *crc)
-{
-       return *(u32 *)((void *)crc + *crc);
-}
-
-static int check_version(const struct load_info *info,
-                        const char *symname,
-                        struct module *mod,
-                        const s32 *crc)
-{
-       Elf_Shdr *sechdrs = info->sechdrs;
-       unsigned int versindex = info->index.vers;
-       unsigned int i, num_versions;
-       struct modversion_info *versions;
-
-       /* Exporting module didn't supply crcs?  OK, we're already tainted. */
-       if (!crc)
-               return 1;
-
-       /* No versions at all?  modprobe --force does this. */
-       if (versindex == 0)
-               return try_to_force_load(mod, symname) == 0;
-
-       versions = (void *) sechdrs[versindex].sh_addr;
-       num_versions = sechdrs[versindex].sh_size
-               / sizeof(struct modversion_info);
-
-       for (i = 0; i < num_versions; i++) {
-               u32 crcval;
-
-               if (strcmp(versions[i].name, symname) != 0)
-                       continue;
-
-               if (IS_ENABLED(CONFIG_MODULE_REL_CRCS))
-                       crcval = resolve_rel_crc(crc);
-               else
-                       crcval = *crc;
-               if (versions[i].crc == crcval)
-                       return 1;
-               pr_debug("Found checksum %X vs module %lX\n",
-                        crcval, versions[i].crc);
-               goto bad_version;
-       }
-
-       /* Broken toolchain. Warn once, then let it go.. */
-       pr_warn_once("%s: no symbol version for %s\n", info->name, symname);
-       return 1;
-
-bad_version:
-       pr_warn("%s: disagrees about version of symbol %s\n",
-              info->name, symname);
-       return 0;
-}
-
-static inline int check_modstruct_version(const struct load_info *info,
-                                         struct module *mod)
-{
-       struct find_symbol_arg fsa = {
-               .name   = "module_layout",
-               .gplok  = true,
-       };
-
-       /*
-        * Since this should be found in kernel (which can't be removed), no
-        * locking is necessary -- use preempt_disable() to placate lockdep.
-        */
-       preempt_disable();
-       if (!find_symbol(&fsa)) {
-               preempt_enable();
-               BUG();
-       }
-       preempt_enable();
-       return check_version(info, "module_layout", mod, fsa.crc);
-}
-
-/* First part is kernel version, which we ignore if module has crcs. */
-static inline int same_magic(const char *amagic, const char *bmagic,
-                            bool has_crcs)
-{
-       if (has_crcs) {
-               amagic += strcspn(amagic, " ");
-               bmagic += strcspn(bmagic, " ");
-       }
-       return strcmp(amagic, bmagic) == 0;
-}
-#else
-static inline int check_version(const struct load_info *info,
-                               const char *symname,
-                               struct module *mod,
-                               const s32 *crc)
-{
-       return 1;
-}
-
-static inline int check_modstruct_version(const struct load_info *info,
-                                         struct module *mod)
-{
-       return 1;
-}
-
-static inline int same_magic(const char *amagic, const char *bmagic,
-                            bool has_crcs)
-{
-       return strcmp(amagic, bmagic) == 0;
-}
-#endif /* CONFIG_MODVERSIONS */
-
 static char *get_modinfo(const struct load_info *info, const char *tag);
 static char *get_next_modinfo(const struct load_info *info, const char *tag,
                              char *prev);
@@ -3247,18 +3122,3 @@ void print_modules(void)
                pr_cont(" [last unloaded: %s]", last_unloaded_module);
        pr_cont("\n");
 }
-
-#ifdef CONFIG_MODVERSIONS
-/*
- * Generate the signature for all relevant module structures here.
- * If these change, we don't want to try to parse the module.
- */
-void module_layout(struct module *mod,
-                  struct modversion_info *ver,
-                  struct kernel_param *kp,
-                  struct kernel_symbol *ks,
-                  struct tracepoint * const *tp)
-{
-}
-EXPORT_SYMBOL(module_layout);
-#endif
diff --git a/kernel/module/version.c b/kernel/module/version.c
new file mode 100644 (file)
index 0000000..adaedce
--- /dev/null
@@ -0,0 +1,109 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Module version support
+ *
+ * Copyright (C) 2008 Rusty Russell
+ */
+
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/printk.h>
+#include "internal.h"
+
+static u32 resolve_rel_crc(const s32 *crc)
+{
+       return *(u32 *)((void *)crc + *crc);
+}
+
+int check_version(const struct load_info *info,
+                 const char *symname,
+                        struct module *mod,
+                        const s32 *crc)
+{
+       Elf_Shdr *sechdrs = info->sechdrs;
+       unsigned int versindex = info->index.vers;
+       unsigned int i, num_versions;
+       struct modversion_info *versions;
+
+       /* Exporting module didn't supply crcs?  OK, we're already tainted. */
+       if (!crc)
+               return 1;
+
+       /* No versions at all?  modprobe --force does this. */
+       if (versindex == 0)
+               return try_to_force_load(mod, symname) == 0;
+
+       versions = (void *)sechdrs[versindex].sh_addr;
+       num_versions = sechdrs[versindex].sh_size
+               / sizeof(struct modversion_info);
+
+       for (i = 0; i < num_versions; i++) {
+               u32 crcval;
+
+               if (strcmp(versions[i].name, symname) != 0)
+                       continue;
+
+               if (IS_ENABLED(CONFIG_MODULE_REL_CRCS))
+                       crcval = resolve_rel_crc(crc);
+               else
+                       crcval = *crc;
+               if (versions[i].crc == crcval)
+                       return 1;
+               pr_debug("Found checksum %X vs module %lX\n",
+                        crcval, versions[i].crc);
+               goto bad_version;
+       }
+
+       /* Broken toolchain. Warn once, then let it go.. */
+       pr_warn_once("%s: no symbol version for %s\n", info->name, symname);
+       return 1;
+
+bad_version:
+       pr_warn("%s: disagrees about version of symbol %s\n", info->name, symname);
+       return 0;
+}
+
+int check_modstruct_version(const struct load_info *info,
+                           struct module *mod)
+{
+       struct find_symbol_arg fsa = {
+               .name   = "module_layout",
+               .gplok  = true,
+       };
+
+       /*
+        * Since this should be found in kernel (which can't be removed), no
+        * locking is necessary -- use preempt_disable() to placate lockdep.
+        */
+       preempt_disable();
+       if (!find_symbol(&fsa)) {
+               preempt_enable();
+               BUG();
+       }
+       preempt_enable();
+       return check_version(info, "module_layout", mod, fsa.crc);
+}
+
+/* First part is kernel version, which we ignore if module has crcs. */
+int same_magic(const char *amagic, const char *bmagic,
+              bool has_crcs)
+{
+       if (has_crcs) {
+               amagic += strcspn(amagic, " ");
+               bmagic += strcspn(bmagic, " ");
+       }
+       return strcmp(amagic, bmagic) == 0;
+}
+
+/*
+ * Generate the signature for all relevant module structures here.
+ * If these change, we don't want to try to parse the module.
+ */
+void module_layout(struct module *mod,
+                  struct modversion_info *ver,
+                  struct kernel_param *kp,
+                  struct kernel_symbol *ks,
+                  struct tracepoint * const *tp)
+{
+}
+EXPORT_SYMBOL(module_layout);