Skip to content

Commit

Permalink
Merge branch 'modversions' (modversions fixes for powerpc from Ard)
Browse files Browse the repository at this point in the history
Merge kcrctab entry fixes from Ard Biesheuvel:
 "This is a followup to [0] 'modversions: redefine kcrctab entries as
  relative CRC pointers', but since relative CRC pointers do not work in
  modules, and are actually only needed by powerpc with
  CONFIG_RELOCATABLE=y, I have made it a Kconfig selectable feature
  instead.

  First it introduces the MODULE_REL_CRCS Kconfig symbol, and adds the
  kbuild handling of it, i.e., modpost, genksyms and kallsyms.

  Then it switches all architectures to 32-bit CRC entries in kcrctab,
  where all architectures except powerpc with CONFIG_RELOCATABLE=y use
  absolute ELF symbol references as before"

[0] http://marc.info/?l=linux-arch&m=148493613415294&w=2

* emailed patches from Ard Biesheuvel:
  module: unify absolute krctab definitions for 32-bit and 64-bit
  modversions: treat symbol CRCs as 32 bit quantities
  kbuild: modversions: add infrastructure for emitting relative CRCs
  • Loading branch information
torvalds committed Feb 3, 2017
2 parents 29905b5 + 4b9eee9 commit 2cb54ce
Show file tree
Hide file tree
Showing 12 changed files with 93 additions and 62 deletions.
1 change: 1 addition & 0 deletions arch/powerpc/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -484,6 +484,7 @@ config RELOCATABLE
bool "Build a relocatable kernel"
depends on (PPC64 && !COMPILE_TEST) || (FLATMEM && (44x || FSL_BOOKE))
select NONSTATIC_KERNEL
select MODULE_REL_CRCS if MODVERSIONS
help
This builds a kernel image that is capable of running at the
location the kernel is loaded at. For ppc32, there is no any
Expand Down
4 changes: 0 additions & 4 deletions arch/powerpc/include/asm/module.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,5 @@ static inline int module_finalize_ftrace(struct module *mod, const Elf_Shdr *sec
}
#endif

#if defined(CONFIG_MODVERSIONS) && defined(CONFIG_PPC64)
#define ARCH_RELOCATES_KCRCTAB
#define reloc_start PHYSICAL_START
#endif
#endif /* __KERNEL__ */
#endif /* _ASM_POWERPC_MODULE_H */
8 changes: 0 additions & 8 deletions arch/powerpc/kernel/module_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -286,14 +286,6 @@ static void dedotify_versions(struct modversion_info *vers,
for (end = (void *)vers + size; vers < end; vers++)
if (vers->name[0] == '.') {
memmove(vers->name, vers->name+1, strlen(vers->name));
#ifdef ARCH_RELOCATES_KCRCTAB
/* The TOC symbol has no CRC computed. To avoid CRC
* check failing, we must force it to the expected
* value (see CRC check in module.c).
*/
if (!strcmp(vers->name, "TOC."))
vers->crc = -(unsigned long)reloc_start;
#endif
}
}

Expand Down
11 changes: 6 additions & 5 deletions include/asm-generic/export.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,15 @@
#ifndef KSYM_ALIGN
#define KSYM_ALIGN 8
#endif
#ifndef KCRC_ALIGN
#define KCRC_ALIGN 8
#endif
#else
#define __put .long
#ifndef KSYM_ALIGN
#define KSYM_ALIGN 4
#endif
#endif
#ifndef KCRC_ALIGN
#define KCRC_ALIGN 4
#endif
#endif

#ifdef CONFIG_HAVE_UNDERSCORE_SYMBOL_PREFIX
#define KSYM(name) _##name
Expand Down Expand Up @@ -52,7 +49,11 @@ KSYM(__kstrtab_\name):
.section ___kcrctab\sec+\name,"a"
.balign KCRC_ALIGN
KSYM(__kcrctab_\name):
__put KSYM(__crc_\name)
#if defined(CONFIG_MODULE_REL_CRCS)
.long KSYM(__crc_\name) - .
#else
.long KSYM(__crc_\name)
#endif
.weak KSYM(__crc_\name)
.previous
#endif
Expand Down
17 changes: 12 additions & 5 deletions include/linux/export.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,19 @@ extern struct module __this_module;
#ifdef CONFIG_MODVERSIONS
/* Mark the CRC weak since genksyms apparently decides not to
* generate a checksums for some symbols */
#if defined(CONFIG_MODULE_REL_CRCS)
#define __CRC_SYMBOL(sym, sec) \
extern __visible void *__crc_##sym __attribute__((weak)); \
static const unsigned long __kcrctab_##sym \
__used \
__attribute__((section("___kcrctab" sec "+" #sym), used)) \
= (unsigned long) &__crc_##sym;
asm(" .section \"___kcrctab" sec "+" #sym "\", \"a\" \n" \
" .weak " VMLINUX_SYMBOL_STR(__crc_##sym) " \n" \
" .long " VMLINUX_SYMBOL_STR(__crc_##sym) " - . \n" \
" .previous \n");
#else
#define __CRC_SYMBOL(sym, sec) \
asm(" .section \"___kcrctab" sec "+" #sym "\", \"a\" \n" \
" .weak " VMLINUX_SYMBOL_STR(__crc_##sym) " \n" \
" .long " VMLINUX_SYMBOL_STR(__crc_##sym) " \n" \
" .previous \n");
#endif
#else
#define __CRC_SYMBOL(sym, sec)
#endif
Expand Down
14 changes: 7 additions & 7 deletions include/linux/module.h
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,7 @@ struct module {

/* Exported symbols */
const struct kernel_symbol *syms;
const unsigned long *crcs;
const s32 *crcs;
unsigned int num_syms;

/* Kernel parameters. */
Expand All @@ -359,18 +359,18 @@ struct module {
/* GPL-only exported symbols. */
unsigned int num_gpl_syms;
const struct kernel_symbol *gpl_syms;
const unsigned long *gpl_crcs;
const s32 *gpl_crcs;

#ifdef CONFIG_UNUSED_SYMBOLS
/* unused exported symbols. */
const struct kernel_symbol *unused_syms;
const unsigned long *unused_crcs;
const s32 *unused_crcs;
unsigned int num_unused_syms;

/* GPL-only, unused exported symbols. */
unsigned int num_unused_gpl_syms;
const struct kernel_symbol *unused_gpl_syms;
const unsigned long *unused_gpl_crcs;
const s32 *unused_gpl_crcs;
#endif

#ifdef CONFIG_MODULE_SIG
Expand All @@ -382,7 +382,7 @@ struct module {

/* symbols that will be GPL-only in the near future. */
const struct kernel_symbol *gpl_future_syms;
const unsigned long *gpl_future_crcs;
const s32 *gpl_future_crcs;
unsigned int num_gpl_future_syms;

/* Exception table */
Expand Down Expand Up @@ -523,7 +523,7 @@ struct module *find_module(const char *name);

struct symsearch {
const struct kernel_symbol *start, *stop;
const unsigned long *crcs;
const s32 *crcs;
enum {
NOT_GPL_ONLY,
GPL_ONLY,
Expand All @@ -539,7 +539,7 @@ struct symsearch {
*/
const struct kernel_symbol *find_symbol(const char *name,
struct module **owner,
const unsigned long **crc,
const s32 **crc,
bool gplok,
bool warn);

Expand Down
4 changes: 4 additions & 0 deletions init/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -1987,6 +1987,10 @@ config MODVERSIONS
make them incompatible with the kernel you are running. If
unsure, say N.

config MODULE_REL_CRCS
bool
depends on MODVERSIONS

config MODULE_SRCVERSION_ALL
bool "Source checksum for all modules"
help
Expand Down
53 changes: 25 additions & 28 deletions kernel/module.c
Original file line number Diff line number Diff line change
Expand Up @@ -389,16 +389,16 @@ extern const struct kernel_symbol __start___ksymtab_gpl[];
extern const struct kernel_symbol __stop___ksymtab_gpl[];
extern const struct kernel_symbol __start___ksymtab_gpl_future[];
extern const struct kernel_symbol __stop___ksymtab_gpl_future[];
extern const unsigned long __start___kcrctab[];
extern const unsigned long __start___kcrctab_gpl[];
extern const unsigned long __start___kcrctab_gpl_future[];
extern const s32 __start___kcrctab[];
extern const s32 __start___kcrctab_gpl[];
extern const s32 __start___kcrctab_gpl_future[];
#ifdef CONFIG_UNUSED_SYMBOLS
extern const struct kernel_symbol __start___ksymtab_unused[];
extern const struct kernel_symbol __stop___ksymtab_unused[];
extern const struct kernel_symbol __start___ksymtab_unused_gpl[];
extern const struct kernel_symbol __stop___ksymtab_unused_gpl[];
extern const unsigned long __start___kcrctab_unused[];
extern const unsigned long __start___kcrctab_unused_gpl[];
extern const s32 __start___kcrctab_unused[];
extern const s32 __start___kcrctab_unused_gpl[];
#endif

#ifndef CONFIG_MODVERSIONS
Expand Down Expand Up @@ -497,7 +497,7 @@ struct find_symbol_arg {

/* Output */
struct module *owner;
const unsigned long *crc;
const s32 *crc;
const struct kernel_symbol *sym;
};

Expand Down Expand Up @@ -563,7 +563,7 @@ static bool find_symbol_in_section(const struct symsearch *syms,
* (optional) module which owns it. Needs preempt disabled or module_mutex. */
const struct kernel_symbol *find_symbol(const char *name,
struct module **owner,
const unsigned long **crc,
const s32 **crc,
bool gplok,
bool warn)
{
Expand Down Expand Up @@ -1249,23 +1249,17 @@ static int try_to_force_load(struct module *mod, const char *reason)
}

#ifdef CONFIG_MODVERSIONS
/* If the arch applies (non-zero) relocations to kernel kcrctab, unapply it. */
static unsigned long maybe_relocated(unsigned long crc,
const struct module *crc_owner)

static u32 resolve_rel_crc(const s32 *crc)
{
#ifdef ARCH_RELOCATES_KCRCTAB
if (crc_owner == NULL)
return crc - (unsigned long)reloc_start;
#endif
return crc;
return *(u32 *)((void *)crc + *crc);
}

static int check_version(Elf_Shdr *sechdrs,
unsigned int versindex,
const char *symname,
struct module *mod,
const unsigned long *crc,
const struct module *crc_owner)
const s32 *crc)
{
unsigned int i, num_versions;
struct modversion_info *versions;
Expand All @@ -1283,13 +1277,19 @@ static int check_version(Elf_Shdr *sechdrs,
/ sizeof(struct modversion_info);

for (i = 0; i < num_versions; i++) {
u32 crcval;

if (strcmp(versions[i].name, symname) != 0)
continue;

if (versions[i].crc == maybe_relocated(*crc, crc_owner))
if (IS_ENABLED(CONFIG_MODULE_REL_CRCS))
crcval = resolve_rel_crc(crc);
else
crcval = *crc;
if (versions[i].crc == crcval)
return 1;
pr_debug("Found checksum %lX vs module %lX\n",
maybe_relocated(*crc, crc_owner), versions[i].crc);
pr_debug("Found checksum %X vs module %lX\n",
crcval, versions[i].crc);
goto bad_version;
}

Expand All @@ -1307,7 +1307,7 @@ static inline int check_modstruct_version(Elf_Shdr *sechdrs,
unsigned int versindex,
struct module *mod)
{
const unsigned long *crc;
const s32 *crc;

/*
* Since this should be found in kernel (which can't be removed), no
Expand All @@ -1321,8 +1321,7 @@ static inline int check_modstruct_version(Elf_Shdr *sechdrs,
}
preempt_enable();
return check_version(sechdrs, versindex,
VMLINUX_SYMBOL_STR(module_layout), mod, crc,
NULL);
VMLINUX_SYMBOL_STR(module_layout), mod, crc);
}

/* First part is kernel version, which we ignore if module has crcs. */
Expand All @@ -1340,8 +1339,7 @@ static inline int check_version(Elf_Shdr *sechdrs,
unsigned int versindex,
const char *symname,
struct module *mod,
const unsigned long *crc,
const struct module *crc_owner)
const s32 *crc)
{
return 1;
}
Expand All @@ -1368,7 +1366,7 @@ static const struct kernel_symbol *resolve_symbol(struct module *mod,
{
struct module *owner;
const struct kernel_symbol *sym;
const unsigned long *crc;
const s32 *crc;
int err;

/*
Expand All @@ -1383,8 +1381,7 @@ static const struct kernel_symbol *resolve_symbol(struct module *mod,
if (!sym)
goto unlock;

if (!check_version(info->sechdrs, info->index.vers, name, mod, crc,
owner)) {
if (!check_version(info->sechdrs, info->index.vers, name, mod, crc)) {
sym = ERR_PTR(-EINVAL);
goto getname;
}
Expand Down
2 changes: 2 additions & 0 deletions scripts/Makefile.build
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ cmd_gensymtypes_c = \
$(CPP) -D__GENKSYMS__ $(c_flags) $< | \
$(GENKSYMS) $(if $(1), -T $(2)) \
$(patsubst y,-s _,$(CONFIG_HAVE_UNDERSCORE_SYMBOL_PREFIX)) \
$(patsubst y,-R,$(CONFIG_MODULE_REL_CRCS)) \
$(if $(KBUILD_PRESERVE),-p) \
-r $(firstword $(wildcard $(2:.symtypes=.symref) /dev/null))

Expand Down Expand Up @@ -337,6 +338,7 @@ cmd_gensymtypes_S = \
$(CPP) -D__GENKSYMS__ $(c_flags) -xc - | \
$(GENKSYMS) $(if $(1), -T $(2)) \
$(patsubst y,-s _,$(CONFIG_HAVE_UNDERSCORE_SYMBOL_PREFIX)) \
$(patsubst y,-R,$(CONFIG_MODULE_REL_CRCS)) \
$(if $(KBUILD_PRESERVE),-p) \
-r $(firstword $(wildcard $(2:.symtypes=.symref) /dev/null))

Expand Down
19 changes: 14 additions & 5 deletions scripts/genksyms/genksyms.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ char *cur_filename, *source_file;
int in_source_file;

static int flag_debug, flag_dump_defs, flag_reference, flag_dump_types,
flag_preserve, flag_warnings;
flag_preserve, flag_warnings, flag_rel_crcs;
static const char *mod_prefix = "";

static int errors;
Expand Down Expand Up @@ -693,7 +693,10 @@ void export_symbol(const char *name)
fputs(">\n", debugfile);

/* Used as a linker script. */
printf("%s__crc_%s = 0x%08lx ;\n", mod_prefix, name, crc);
printf(!flag_rel_crcs ? "%s__crc_%s = 0x%08lx;\n" :
"SECTIONS { .rodata : ALIGN(4) { "
"%s__crc_%s = .; LONG(0x%08lx); } }\n",
mod_prefix, name, crc);
}
}

Expand Down Expand Up @@ -730,7 +733,7 @@ void error_with_pos(const char *fmt, ...)

static void genksyms_usage(void)
{
fputs("Usage:\n" "genksyms [-adDTwqhV] > /path/to/.tmp_obj.ver\n" "\n"
fputs("Usage:\n" "genksyms [-adDTwqhVR] > /path/to/.tmp_obj.ver\n" "\n"
#ifdef __GNU_LIBRARY__
" -s, --symbol-prefix Select symbol prefix\n"
" -d, --debug Increment the debug level (repeatable)\n"
Expand All @@ -742,6 +745,7 @@ static void genksyms_usage(void)
" -q, --quiet Disable warnings (default)\n"
" -h, --help Print this message\n"
" -V, --version Print the release version\n"
" -R, --relative-crc Emit section relative symbol CRCs\n"
#else /* __GNU_LIBRARY__ */
" -s Select symbol prefix\n"
" -d Increment the debug level (repeatable)\n"
Expand All @@ -753,6 +757,7 @@ static void genksyms_usage(void)
" -q Disable warnings (default)\n"
" -h Print this message\n"
" -V Print the release version\n"
" -R Emit section relative symbol CRCs\n"
#endif /* __GNU_LIBRARY__ */
, stderr);
}
Expand All @@ -774,13 +779,14 @@ int main(int argc, char **argv)
{"preserve", 0, 0, 'p'},
{"version", 0, 0, 'V'},
{"help", 0, 0, 'h'},
{"relative-crc", 0, 0, 'R'},
{0, 0, 0, 0}
};

while ((o = getopt_long(argc, argv, "s:dwqVDr:T:ph",
while ((o = getopt_long(argc, argv, "s:dwqVDr:T:phR",
&long_opts[0], NULL)) != EOF)
#else /* __GNU_LIBRARY__ */
while ((o = getopt(argc, argv, "s:dwqVDr:T:ph")) != EOF)
while ((o = getopt(argc, argv, "s:dwqVDr:T:phR")) != EOF)
#endif /* __GNU_LIBRARY__ */
switch (o) {
case 's':
Expand Down Expand Up @@ -823,6 +829,9 @@ int main(int argc, char **argv)
case 'h':
genksyms_usage();
return 0;
case 'R':
flag_rel_crcs = 1;
break;
default:
genksyms_usage();
return 1;
Expand Down
Loading

0 comments on commit 2cb54ce

Please sign in to comment.