Skip to content

Commit 4788979

Browse files
Aaron Tomlinmcgrof
authored andcommitted
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. Reviewed-by: Christophe Leroy <christophe.leroy@csgroup.eu> Signed-off-by: Aaron Tomlin <atomlin@redhat.com> Signed-off-by: Luis Chamberlain <mcgrof@kernel.org>
1 parent f64205a commit 4788979

4 files changed

Lines changed: 166 additions & 148 deletions

File tree

kernel/module/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,4 @@ obj-$(CONFIG_KALLSYMS) += kallsyms.o
1818
obj-$(CONFIG_PROC_FS) += procfs.o
1919
obj-$(CONFIG_SYSFS) += sysfs.o
2020
obj-$(CONFIG_KGDB_KDB) += kdb.o
21+
obj-$(CONFIG_MODVERSIONS) += version.o

kernel/module/internal.h

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,27 @@ struct load_info {
7070
} index;
7171
};
7272

73+
enum mod_license {
74+
NOT_GPL_ONLY,
75+
GPL_ONLY,
76+
};
77+
78+
struct find_symbol_arg {
79+
/* Input */
80+
const char *name;
81+
bool gplok;
82+
bool warn;
83+
84+
/* Output */
85+
struct module *owner;
86+
const s32 *crc;
87+
const struct kernel_symbol *sym;
88+
enum mod_license license;
89+
};
90+
7391
int mod_verify_sig(const void *mod, struct load_info *info);
92+
int try_to_force_load(struct module *mod, const char *reason);
93+
bool find_symbol(struct find_symbol_arg *fsa);
7494
struct module *find_module_all(const char *name, size_t len, bool even_unformed);
7595
int cmp_name(const void *name, const void *sym);
7696
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,
225245
static inline void mod_sysfs_teardown(struct module *mod) { }
226246
static inline void init_param_lock(struct module *mod) { }
227247
#endif /* CONFIG_SYSFS */
248+
249+
#ifdef CONFIG_MODVERSIONS
250+
int check_version(const struct load_info *info,
251+
const char *symname, struct module *mod, const s32 *crc);
252+
void module_layout(struct module *mod, struct modversion_info *ver, struct kernel_param *kp,
253+
struct kernel_symbol *ks, struct tracepoint * const *tp);
254+
int check_modstruct_version(const struct load_info *info, struct module *mod);
255+
int same_magic(const char *amagic, const char *bmagic, bool has_crcs);
256+
#else /* !CONFIG_MODVERSIONS */
257+
static inline int check_version(const struct load_info *info,
258+
const char *symname,
259+
struct module *mod,
260+
const s32 *crc)
261+
{
262+
return 1;
263+
}
264+
265+
static inline int check_modstruct_version(const struct load_info *info,
266+
struct module *mod)
267+
{
268+
return 1;
269+
}
270+
271+
static inline int same_magic(const char *amagic, const char *bmagic, bool has_crcs)
272+
{
273+
return strcmp(amagic, bmagic) == 0;
274+
}
275+
#endif /* CONFIG_MODVERSIONS */

kernel/module/main.c

Lines changed: 8 additions & 148 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,12 @@ struct mod_tree_root mod_tree __cacheline_aligned = {
8686
static unsigned long module_addr_min = -1UL, module_addr_max;
8787
#endif /* CONFIG_MODULES_TREE_LOOKUP */
8888

89+
struct symsearch {
90+
const struct kernel_symbol *start, *stop;
91+
const s32 *crcs;
92+
enum mod_license license;
93+
};
94+
8995
/*
9096
* Bounds of module text, for speeding up __module_address.
9197
* Protected by module_mutex.
@@ -244,28 +250,6 @@ static __maybe_unused void *any_section_objs(const struct load_info *info,
244250
#define symversion(base, idx) ((base != NULL) ? ((base) + (idx)) : NULL)
245251
#endif
246252

247-
struct symsearch {
248-
const struct kernel_symbol *start, *stop;
249-
const s32 *crcs;
250-
enum mod_license {
251-
NOT_GPL_ONLY,
252-
GPL_ONLY,
253-
} license;
254-
};
255-
256-
struct find_symbol_arg {
257-
/* Input */
258-
const char *name;
259-
bool gplok;
260-
bool warn;
261-
262-
/* Output */
263-
struct module *owner;
264-
const s32 *crc;
265-
const struct kernel_symbol *sym;
266-
enum mod_license license;
267-
};
268-
269253
static bool check_exported_symbol(const struct symsearch *syms,
270254
struct module *owner,
271255
unsigned int symnum, void *data)
@@ -327,7 +311,7 @@ static bool find_exported_symbol_in_section(const struct symsearch *syms,
327311
* Find an exported symbol and return it, along with, (optional) crc and
328312
* (optional) module which owns it. Needs preempt disabled or module_mutex.
329313
*/
330-
static bool find_symbol(struct find_symbol_arg *fsa)
314+
bool find_symbol(struct find_symbol_arg *fsa)
331315
{
332316
static const struct symsearch arr[] = {
333317
{ __start___ksymtab, __stop___ksymtab, __start___kcrctab,
@@ -1001,7 +985,7 @@ size_t modinfo_attrs_count = ARRAY_SIZE(modinfo_attrs);
1001985

1002986
static const char vermagic[] = VERMAGIC_STRING;
1003987

1004-
static int try_to_force_load(struct module *mod, const char *reason)
988+
int try_to_force_load(struct module *mod, const char *reason)
1005989
{
1006990
#ifdef CONFIG_MODULE_FORCE_LOAD
1007991
if (!test_taint(TAINT_FORCED_MODULE))
@@ -1013,115 +997,6 @@ static int try_to_force_load(struct module *mod, const char *reason)
1013997
#endif
1014998
}
1015999

1016-
#ifdef CONFIG_MODVERSIONS
1017-
1018-
static u32 resolve_rel_crc(const s32 *crc)
1019-
{
1020-
return *(u32 *)((void *)crc + *crc);
1021-
}
1022-
1023-
static int check_version(const struct load_info *info,
1024-
const char *symname,
1025-
struct module *mod,
1026-
const s32 *crc)
1027-
{
1028-
Elf_Shdr *sechdrs = info->sechdrs;
1029-
unsigned int versindex = info->index.vers;
1030-
unsigned int i, num_versions;
1031-
struct modversion_info *versions;
1032-
1033-
/* Exporting module didn't supply crcs? OK, we're already tainted. */
1034-
if (!crc)
1035-
return 1;
1036-
1037-
/* No versions at all? modprobe --force does this. */
1038-
if (versindex == 0)
1039-
return try_to_force_load(mod, symname) == 0;
1040-
1041-
versions = (void *) sechdrs[versindex].sh_addr;
1042-
num_versions = sechdrs[versindex].sh_size
1043-
/ sizeof(struct modversion_info);
1044-
1045-
for (i = 0; i < num_versions; i++) {
1046-
u32 crcval;
1047-
1048-
if (strcmp(versions[i].name, symname) != 0)
1049-
continue;
1050-
1051-
if (IS_ENABLED(CONFIG_MODULE_REL_CRCS))
1052-
crcval = resolve_rel_crc(crc);
1053-
else
1054-
crcval = *crc;
1055-
if (versions[i].crc == crcval)
1056-
return 1;
1057-
pr_debug("Found checksum %X vs module %lX\n",
1058-
crcval, versions[i].crc);
1059-
goto bad_version;
1060-
}
1061-
1062-
/* Broken toolchain. Warn once, then let it go.. */
1063-
pr_warn_once("%s: no symbol version for %s\n", info->name, symname);
1064-
return 1;
1065-
1066-
bad_version:
1067-
pr_warn("%s: disagrees about version of symbol %s\n",
1068-
info->name, symname);
1069-
return 0;
1070-
}
1071-
1072-
static inline int check_modstruct_version(const struct load_info *info,
1073-
struct module *mod)
1074-
{
1075-
struct find_symbol_arg fsa = {
1076-
.name = "module_layout",
1077-
.gplok = true,
1078-
};
1079-
1080-
/*
1081-
* Since this should be found in kernel (which can't be removed), no
1082-
* locking is necessary -- use preempt_disable() to placate lockdep.
1083-
*/
1084-
preempt_disable();
1085-
if (!find_symbol(&fsa)) {
1086-
preempt_enable();
1087-
BUG();
1088-
}
1089-
preempt_enable();
1090-
return check_version(info, "module_layout", mod, fsa.crc);
1091-
}
1092-
1093-
/* First part is kernel version, which we ignore if module has crcs. */
1094-
static inline int same_magic(const char *amagic, const char *bmagic,
1095-
bool has_crcs)
1096-
{
1097-
if (has_crcs) {
1098-
amagic += strcspn(amagic, " ");
1099-
bmagic += strcspn(bmagic, " ");
1100-
}
1101-
return strcmp(amagic, bmagic) == 0;
1102-
}
1103-
#else
1104-
static inline int check_version(const struct load_info *info,
1105-
const char *symname,
1106-
struct module *mod,
1107-
const s32 *crc)
1108-
{
1109-
return 1;
1110-
}
1111-
1112-
static inline int check_modstruct_version(const struct load_info *info,
1113-
struct module *mod)
1114-
{
1115-
return 1;
1116-
}
1117-
1118-
static inline int same_magic(const char *amagic, const char *bmagic,
1119-
bool has_crcs)
1120-
{
1121-
return strcmp(amagic, bmagic) == 0;
1122-
}
1123-
#endif /* CONFIG_MODVERSIONS */
1124-
11251000
static char *get_modinfo(const struct load_info *info, const char *tag);
11261001
static char *get_next_modinfo(const struct load_info *info, const char *tag,
11271002
char *prev);
@@ -3247,18 +3122,3 @@ void print_modules(void)
32473122
pr_cont(" [last unloaded: %s]", last_unloaded_module);
32483123
pr_cont("\n");
32493124
}
3250-
3251-
#ifdef CONFIG_MODVERSIONS
3252-
/*
3253-
* Generate the signature for all relevant module structures here.
3254-
* If these change, we don't want to try to parse the module.
3255-
*/
3256-
void module_layout(struct module *mod,
3257-
struct modversion_info *ver,
3258-
struct kernel_param *kp,
3259-
struct kernel_symbol *ks,
3260-
struct tracepoint * const *tp)
3261-
{
3262-
}
3263-
EXPORT_SYMBOL(module_layout);
3264-
#endif

kernel/module/version.c

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

0 commit comments

Comments
 (0)