2024-05-09 05:53:41 +00:00
|
|
|
// 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"
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
kbuild: link symbol CRCs at final link, removing CONFIG_MODULE_REL_CRCS
JIRA: https://issues.redhat.com/browse/RHEL-28063
Conflicts:
Minor ordering in patch-diff listing, but content the same.
Well, after the objtool update, cs9 05c520e6c27d backport of upstream
5d45950dffb and cs9 b206f546c7f3 backport of upstream b42d230650241 were
applied out of order. Maintain those changes by dropping 3
shell functions.
commit 7b4537199a4a8480b8c3ba37a2d44765ce76cd9b
Author: Masahiro Yamada <masahiroy@kernel.org>
Date: Fri May 13 20:39:22 2022 +0900
kbuild: link symbol CRCs at final link, removing CONFIG_MODULE_REL_CRCS
include/{linux,asm-generic}/export.h defines a weak symbol, __crc_*
as a placeholder.
Genksyms writes the version CRCs into the linker script, which will be
used for filling the __crc_* symbols. The linker script format depends
on CONFIG_MODULE_REL_CRCS. If it is enabled, __crc_* holds the offset
to the reference of CRC.
It is time to get rid of this complexity.
Now that modpost parses text files (.*.cmd) to collect all the CRCs,
it can generate C code that will be linked to the vmlinux or modules.
Generate a new C file, .vmlinux.export.c, which contains the CRCs of
symbols exported by vmlinux. It is compiled and linked to vmlinux in
scripts/link-vmlinux.sh.
Put the CRCs of symbols exported by modules into the existing *.mod.c
files. No additional build step is needed for modules. As before,
*.mod.c are compiled and linked to *.ko in scripts/Makefile.modfinal.
No linker magic is used here. The new C implementation works in the
same way, whether CONFIG_RELOCATABLE is enabled or not.
CONFIG_MODULE_REL_CRCS is no longer needed.
Previously, Kbuild invoked additional $(LD) to update the CRCs in
objects, but this step is unneeded too.
Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
Tested-by: Nathan Chancellor <nathan@kernel.org>
Tested-by: Nicolas Schier <nicolas@fjasle.eu>
Reviewed-by: Nicolas Schier <nicolas@fjasle.eu>
Tested-by: Sedat Dilek <sedat.dilek@gmail.com> # LLVM-14 (x86-64)
Signed-off-by: Donald Dutile <ddutile@redhat.com>
2024-05-09 05:53:48 +00:00
|
|
|
crcval = *crc;
|
2024-05-09 05:53:41 +00:00
|
|
|
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);
|