2022-02-22 15:11:58

by Aaron Tomlin

[permalink] [raw]
Subject: [PATCH v8 13/13] module: Move version support into a separate file

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.

Signed-off-by: Aaron Tomlin <[email protected]>
---
kernel/module/Makefile | 1 +
kernel/module/internal.h | 48 ++++++++++++
kernel/module/main.c | 156 ++-------------------------------------
kernel/module/version.c | 109 +++++++++++++++++++++++++++
4 files changed, 166 insertions(+), 148 deletions(-)
create mode 100644 kernel/module/version.c

diff --git a/kernel/module/Makefile b/kernel/module/Makefile
index cf8dcdc6b55f..a46e6361017f 100644
--- a/kernel/module/Makefile
+++ b/kernel/module/Makefile
@@ -17,3 +17,4 @@ obj-$(CONFIG_DEBUG_KMEMLEAK) += debug_kmemleak.o
obj-$(CONFIG_KALLSYMS) += kallsyms.o
obj-$(CONFIG_PROC_FS) += procfs.o
obj-$(CONFIG_SYSFS) += sysfs.o
+obj-$(CONFIG_MODVERSIONS) += version.o
diff --git a/kernel/module/internal.h b/kernel/module/internal.h
index 62d749ef695e..3fc139d5074b 100644
--- a/kernel/module/internal.h
+++ b/kernel/module/internal.h
@@ -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 */
diff --git a/kernel/module/main.c b/kernel/module/main.c
index bcc4f7a82649..0749afdc34b5 100644
--- a/kernel/module/main.c
+++ b/kernel/module/main.c
@@ -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
index 000000000000..adaedce1dc97
--- /dev/null
+++ b/kernel/module/version.c
@@ -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);
--
2.34.1


2022-02-22 20:48:54

by Christophe Leroy

[permalink] [raw]
Subject: Re: [PATCH v8 13/13] module: Move version support into a separate file



Le 22/02/2022 à 15:13, Aaron Tomlin a écrit :
> 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.
>
> Signed-off-by: Aaron Tomlin <[email protected]>

Reviewed-by: Christophe Leroy <[email protected]>

> ---
> kernel/module/Makefile | 1 +
> kernel/module/internal.h | 48 ++++++++++++
> kernel/module/main.c | 156 ++-------------------------------------
> kernel/module/version.c | 109 +++++++++++++++++++++++++++
> 4 files changed, 166 insertions(+), 148 deletions(-)
> create mode 100644 kernel/module/version.c
>
> diff --git a/kernel/module/Makefile b/kernel/module/Makefile
> index cf8dcdc6b55f..a46e6361017f 100644
> --- a/kernel/module/Makefile
> +++ b/kernel/module/Makefile
> @@ -17,3 +17,4 @@ obj-$(CONFIG_DEBUG_KMEMLEAK) += debug_kmemleak.o
> obj-$(CONFIG_KALLSYMS) += kallsyms.o
> obj-$(CONFIG_PROC_FS) += procfs.o
> obj-$(CONFIG_SYSFS) += sysfs.o
> +obj-$(CONFIG_MODVERSIONS) += version.o
> diff --git a/kernel/module/internal.h b/kernel/module/internal.h
> index 62d749ef695e..3fc139d5074b 100644
> --- a/kernel/module/internal.h
> +++ b/kernel/module/internal.h
> @@ -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 */
> diff --git a/kernel/module/main.c b/kernel/module/main.c
> index bcc4f7a82649..0749afdc34b5 100644
> --- a/kernel/module/main.c
> +++ b/kernel/module/main.c
> @@ -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
> index 000000000000..adaedce1dc97
> --- /dev/null
> +++ b/kernel/module/version.c
> @@ -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);