Linux 6.7-rc7
[linux-modified.git] / kernel / module / version.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Module version support
4  *
5  * Copyright (C) 2008 Rusty Russell
6  */
7
8 #include <linux/module.h>
9 #include <linux/string.h>
10 #include <linux/printk.h>
11 #include "internal.h"
12
13 int check_version(const struct load_info *info,
14                   const char *symname,
15                          struct module *mod,
16                          const s32 *crc)
17 {
18         Elf_Shdr *sechdrs = info->sechdrs;
19         unsigned int versindex = info->index.vers;
20         unsigned int i, num_versions;
21         struct modversion_info *versions;
22
23         /* Exporting module didn't supply crcs?  OK, we're already tainted. */
24         if (!crc)
25                 return 1;
26
27         /* No versions at all?  modprobe --force does this. */
28         if (versindex == 0)
29                 return try_to_force_load(mod, symname) == 0;
30
31         versions = (void *)sechdrs[versindex].sh_addr;
32         num_versions = sechdrs[versindex].sh_size
33                 / sizeof(struct modversion_info);
34
35         for (i = 0; i < num_versions; i++) {
36                 u32 crcval;
37
38                 if (strcmp(versions[i].name, symname) != 0)
39                         continue;
40
41                 crcval = *crc;
42                 if (versions[i].crc == crcval)
43                         return 1;
44                 pr_debug("Found checksum %X vs module %lX\n",
45                          crcval, versions[i].crc);
46                 goto bad_version;
47         }
48
49         /* Broken toolchain. Warn once, then let it go.. */
50         pr_warn_once("%s: no symbol version for %s\n", info->name, symname);
51         return 1;
52
53 bad_version:
54         pr_warn("%s: disagrees about version of symbol %s\n", info->name, symname);
55         return 0;
56 }
57
58 int check_modstruct_version(const struct load_info *info,
59                             struct module *mod)
60 {
61         struct find_symbol_arg fsa = {
62                 .name   = "module_layout",
63                 .gplok  = true,
64         };
65
66         /*
67          * Since this should be found in kernel (which can't be removed), no
68          * locking is necessary -- use preempt_disable() to placate lockdep.
69          */
70         preempt_disable();
71         if (!find_symbol(&fsa)) {
72                 preempt_enable();
73                 BUG();
74         }
75         preempt_enable();
76         return check_version(info, "module_layout", mod, fsa.crc);
77 }
78
79 /* First part is kernel version, which we ignore if module has crcs. */
80 int same_magic(const char *amagic, const char *bmagic,
81                bool has_crcs)
82 {
83         if (has_crcs) {
84                 amagic += strcspn(amagic, " ");
85                 bmagic += strcspn(bmagic, " ");
86         }
87         return strcmp(amagic, bmagic) == 0;
88 }
89
90 /*
91  * Generate the signature for all relevant module structures here.
92  * If these change, we don't want to try to parse the module.
93  */
94 void module_layout(struct module *mod,
95                    struct modversion_info *ver,
96                    struct kernel_param *kp,
97                    struct kernel_symbol *ks,
98                    struct tracepoint * const *tp)
99 {
100 }
101 EXPORT_SYMBOL(module_layout);