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
4343 #ifdef CONFIG_MODVERSIONS
4444 /* Mark the CRC weak since genksyms apparently decides not to
4545 * 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)
4653 #define __CRC_SYMBOL(sym, sec) \
4754 extern __visible void *__crc_##sym __attribute__((weak)); \
4855 static const unsigned long __kcrctab_##sym \
@@ -50,6 +57,13 @@ extern struct module __this_module; · 1 unmodified line
5057 __attribute__((section("___kcrctab" sec "+" #sym), used)) \
5158 = (unsigned long) &__crc_##sym;
5259 #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
5367 #define __CRC_SYMBOL(sym, sec)
5468 #endif
5569
include/linux/module.h+7−7
@@ -346,7 +346,7 @@ struct module { · 345 unmodified lines
346346
347347 /* Exported symbols */
348348 const struct kernel_symbol *syms;
349− const unsigned long *crcs;
349+ const s32 *crcs;
350350 unsigned int num_syms;
351351
352352 /* Kernel parameters. */
@@ -359,18 +359,18 @@ struct module { · 6 unmodified lines
359359 /* GPL-only exported symbols. */
360360 unsigned int num_gpl_syms;
361361 const struct kernel_symbol *gpl_syms;
362− const unsigned long *gpl_crcs;
362+ const s32 *gpl_crcs;
363363
364364 #ifdef CONFIG_UNUSED_SYMBOLS
365365 /* unused exported symbols. */
366366 const struct kernel_symbol *unused_syms;
367− const unsigned long *unused_crcs;
367+ const s32 *unused_crcs;
368368 unsigned int num_unused_syms;
369369
370370 /* GPL-only, unused exported symbols. */
371371 unsigned int num_unused_gpl_syms;
372372 const struct kernel_symbol *unused_gpl_syms;
373− const unsigned long *unused_gpl_crcs;
373+ const s32 *unused_gpl_crcs;
374374 #endif
375375
376376 #ifdef CONFIG_MODULE_SIG
@@ -382,7 +382,7 @@ struct module { · 5 unmodified lines
382382
383383 /* symbols that will be GPL-only in the near future. */
384384 const struct kernel_symbol *gpl_future_syms;
385− const unsigned long *gpl_future_crcs;
385+ const s32 *gpl_future_crcs;
386386 unsigned int num_gpl_future_syms;
387387
388388 /* Exception table */
@@ -523,7 +523,7 @@ struct module *find_module(const char *name); · 134 unmodified lines
523523
524524 struct symsearch {
525525 const struct kernel_symbol *start, *stop;
526− const unsigned long *crcs;
526+ const s32 *crcs;
527527 enum {
528528 NOT_GPL_ONLY,
529529 GPL_ONLY,
@@ -539,7 +539,7 @@ struct symsearch { · 9 unmodified lines
539539 */
540540 const struct kernel_symbol *find_symbol(const char *name,
541541 struct module **owner,
542− const unsigned long **crc,
542+ const s32 **crc,
543543 bool gplok,
544544 bool warn);
545545