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
13int 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
53bad_version:
54	pr_warn("%s: disagrees about version of symbol %s\n", info->name, symname);
55	return 0;
56}
57
58int 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. */
80int 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 */
94void 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}
101EXPORT_SYMBOL(module_layout);
102