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