History

modversions: treat symbol CRCs as 32 bit quantities

The modversion symbol CRCs are emitted as ELF symbols, which allows us to easily populate the kcrctab sections by relying on the linker to associate each kcrctab slot with the correct value. This has a couple of downsides: - Given that the CRCs are treated as memory addresses, we waste 4 bytes for each CRC on 64 bit architectures, - On architectures that support runtime relocation, a R_<arch>_RELATIVE relocation entry is emitted for each CRC value, which identifies it as a quantity that requires fixing up based on the actual runtime load offset of the kernel. This results in corrupted CRCs unless we explicitly undo the fixup (and this is currently being handled in the core module code) - Such runtime relocation entries take up 24 bytes of __init space each, resulting in a x8 overhead in [uncompressed] kernel size for CRCs. Switching to explicit 32 bit values on 64 bit architectures fixes most of these issues, given that 32 bit values are not treated as quantities that require fixing up based on the actual runtime load offset. Note that on some ELF64 architectures [such as PPC64], these 32-bit values are still emitted as [absolute] runtime relocatable quantities, even if the value resolves to a build time constant. Since relative relocations are always resolved at build time, this patch enables MODULE_REL_CRCS on powerpc when CONFIG_RELOCATABLE=y, which turns the absolute CRC references into relative references into .rodata where the actual CRC value is stored. So redefine all CRC fields and variables as u32, and redefine the __CRC_SYMBOL() macro for 64 bit builds to emit the CRC reference using inline assembler (which is necessary since 64-bit C code cannot use 32-bit types to hold memory addresses, even if they are ultimately resolved using values that do not exceed 0xffffffff). To avoid potential problems with legacy 32-bit architectures using legacy toolchains, the equivalent C definition of the kcrctab entry is retained for 32-bit architectures. Note that this mostly reverts commit d4703aefdbc8 ("module: handle ppc64 relocating kcrctabs when CONFIG_RELOCATABLE=y")

Ard Biesheuvel committed 9 years ago

Commit 71810db1 parent 56067817 files · +53 −52Browse files

Showing the changes to include/linux (2 of 7 files). Show all

Unified · Split

2 files
  1. include/linux/export.h +14 −0
  2. include/linux/module.h +7 −7
include/linux/export.h+14−0
@@ -43,6 +43,13 @@ extern struct module __this_module; · 42 unmodified lines
43#ifdef CONFIG_MODVERSIONS43#ifdef CONFIG_MODVERSIONS
44/* Mark the CRC weak since genksyms apparently decides not to44/* Mark the CRC weak since genksyms apparently decides not to
45 * generate a checksums for some symbols */45 * generate a checksums for some symbols */
46#if defined(CONFIG_MODULE_REL_CRCS)
47#define __CRC_SYMBOL(sym, sec) \
48 asm(" .section \"___kcrctab" sec "+" #sym "\", \"a\" \n" \
49 " .weak " VMLINUX_SYMBOL_STR(__crc_##sym) " \n" \
50 " .long " VMLINUX_SYMBOL_STR(__crc_##sym) " - . \n" \
51 " .previous \n");
52#elif !defined(CONFIG_64BIT)
46#define __CRC_SYMBOL(sym, sec) \53#define __CRC_SYMBOL(sym, sec) \
47 extern __visible void *__crc_##sym __attribute__((weak)); \54 extern __visible void *__crc_##sym __attribute__((weak)); \
48 static const unsigned long __kcrctab_##sym \55 static const unsigned long __kcrctab_##sym \
@@ -50,6 +57,13 @@ extern struct module __this_module; · 1 unmodified line
50 __attribute__((section("___kcrctab" sec "+" #sym), used)) \57 __attribute__((section("___kcrctab" sec "+" #sym), used)) \
51 = (unsigned long) &__crc_##sym;58 = (unsigned long) &__crc_##sym;
52#else59#else
60#define __CRC_SYMBOL(sym, sec) \
61 asm(" .section \"___kcrctab" sec "+" #sym "\", \"a\" \n" \
62 " .weak " VMLINUX_SYMBOL_STR(__crc_##sym) " \n" \
63 " .long " VMLINUX_SYMBOL_STR(__crc_##sym) " \n" \
64 " .previous \n");
65#endif
66#else
53#define __CRC_SYMBOL(sym, sec)67#define __CRC_SYMBOL(sym, sec)
54#endif68#endif
55 69
include/linux/module.h+7−7
@@ -346,7 +346,7 @@ struct module { · 345 unmodified lines
346 346
347 /* Exported symbols */347 /* Exported symbols */
348 const struct kernel_symbol *syms;348 const struct kernel_symbol *syms;
349 const unsigned long *crcs;349 const s32 *crcs;
350 unsigned int num_syms;350 unsigned int num_syms;
351 351
352 /* Kernel parameters. */352 /* Kernel parameters. */
@@ -359,18 +359,18 @@ struct module { · 6 unmodified lines
359 /* GPL-only exported symbols. */359 /* GPL-only exported symbols. */
360 unsigned int num_gpl_syms;360 unsigned int num_gpl_syms;
361 const struct kernel_symbol *gpl_syms;361 const struct kernel_symbol *gpl_syms;
362 const unsigned long *gpl_crcs;362 const s32 *gpl_crcs;
363 363
364#ifdef CONFIG_UNUSED_SYMBOLS364#ifdef CONFIG_UNUSED_SYMBOLS
365 /* unused exported symbols. */365 /* unused exported symbols. */
366 const struct kernel_symbol *unused_syms;366 const struct kernel_symbol *unused_syms;
367 const unsigned long *unused_crcs;367 const s32 *unused_crcs;
368 unsigned int num_unused_syms;368 unsigned int num_unused_syms;
369 369
370 /* GPL-only, unused exported symbols. */370 /* GPL-only, unused exported symbols. */
371 unsigned int num_unused_gpl_syms;371 unsigned int num_unused_gpl_syms;
372 const struct kernel_symbol *unused_gpl_syms;372 const struct kernel_symbol *unused_gpl_syms;
373 const unsigned long *unused_gpl_crcs;373 const s32 *unused_gpl_crcs;
374#endif374#endif
375 375
376#ifdef CONFIG_MODULE_SIG376#ifdef CONFIG_MODULE_SIG
@@ -382,7 +382,7 @@ struct module { · 5 unmodified lines
382 382
383 /* symbols that will be GPL-only in the near future. */383 /* symbols that will be GPL-only in the near future. */
384 const struct kernel_symbol *gpl_future_syms;384 const struct kernel_symbol *gpl_future_syms;
385 const unsigned long *gpl_future_crcs;385 const s32 *gpl_future_crcs;
386 unsigned int num_gpl_future_syms;386 unsigned int num_gpl_future_syms;
387 387
388 /* Exception table */388 /* Exception table */
@@ -523,7 +523,7 @@ struct module *find_module(const char *name); · 134 unmodified lines
523 523
524struct symsearch {524struct symsearch {
525 const struct kernel_symbol *start, *stop;525 const struct kernel_symbol *start, *stop;
526 const unsigned long *crcs;526 const s32 *crcs;
527 enum {527 enum {
528 NOT_GPL_ONLY,528 NOT_GPL_ONLY,
529 GPL_ONLY,529 GPL_ONLY,
@@ -539,7 +539,7 @@ struct symsearch { · 9 unmodified lines
539 */539 */
540const struct kernel_symbol *find_symbol(const char *name,540const struct kernel_symbol *find_symbol(const char *name,
541 struct module **owner,541 struct module **owner,
542 const unsigned long **crc,542 const s32 **crc,
543 bool gplok,543 bool gplok,
544 bool warn);544 bool warn);
545 545