Skip to content

Commit 5606781

Browse files
Ard Biesheuveltorvalds
authored andcommitted
kbuild: modversions: add infrastructure for emitting relative CRCs
This add the kbuild infrastructure that will allow architectures to emit vmlinux symbol CRCs as 32-bit offsets to another location in the kernel where the actual value is stored. This works around problems with CRCs being mistaken for relocatable symbols on kernels that self relocate at runtime (i.e., powerpc with CONFIG_RELOCATABLE=y) For the kbuild side of things, this comes down to the following: - introducing a Kconfig symbol MODULE_REL_CRCS - adding a -R switch to genksyms to instruct it to emit the CRC symbols as references into the .rodata section - making modpost distinguish such references from absolute CRC symbols by the section index (SHN_ABS) - making kallsyms disregard non-absolute symbols with a __crc_ prefix Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
1 parent 34e00ac commit 5606781

File tree

5 files changed

+42
-5
lines changed

5 files changed

+42
-5
lines changed

init/Kconfig

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1987,6 +1987,10 @@ config MODVERSIONS
19871987
make them incompatible with the kernel you are running. If
19881988
unsure, say N.
19891989

1990+
config MODULE_REL_CRCS
1991+
bool
1992+
depends on MODVERSIONS
1993+
19901994
config MODULE_SRCVERSION_ALL
19911995
bool "Source checksum for all modules"
19921996
help

scripts/Makefile.build

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@ cmd_gensymtypes_c = \
164164
$(CPP) -D__GENKSYMS__ $(c_flags) $< | \
165165
$(GENKSYMS) $(if $(1), -T $(2)) \
166166
$(patsubst y,-s _,$(CONFIG_HAVE_UNDERSCORE_SYMBOL_PREFIX)) \
167+
$(patsubst y,-R,$(CONFIG_MODULE_REL_CRCS)) \
167168
$(if $(KBUILD_PRESERVE),-p) \
168169
-r $(firstword $(wildcard $(2:.symtypes=.symref) /dev/null))
169170

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

scripts/genksyms/genksyms.c

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ char *cur_filename, *source_file;
4444
int in_source_file;
4545

4646
static int flag_debug, flag_dump_defs, flag_reference, flag_dump_types,
47-
flag_preserve, flag_warnings;
47+
flag_preserve, flag_warnings, flag_rel_crcs;
4848
static const char *mod_prefix = "";
4949

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

695695
/* Used as a linker script. */
696-
printf("%s__crc_%s = 0x%08lx ;\n", mod_prefix, name, crc);
696+
printf(!flag_rel_crcs ? "%s__crc_%s = 0x%08lx;\n" :
697+
"SECTIONS { .rodata : ALIGN(4) { "
698+
"%s__crc_%s = .; LONG(0x%08lx); } }\n",
699+
mod_prefix, name, crc);
697700
}
698701
}
699702

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

731734
static void genksyms_usage(void)
732735
{
733-
fputs("Usage:\n" "genksyms [-adDTwqhV] > /path/to/.tmp_obj.ver\n" "\n"
736+
fputs("Usage:\n" "genksyms [-adDTwqhVR] > /path/to/.tmp_obj.ver\n" "\n"
734737
#ifdef __GNU_LIBRARY__
735738
" -s, --symbol-prefix Select symbol prefix\n"
736739
" -d, --debug Increment the debug level (repeatable)\n"
@@ -742,6 +745,7 @@ static void genksyms_usage(void)
742745
" -q, --quiet Disable warnings (default)\n"
743746
" -h, --help Print this message\n"
744747
" -V, --version Print the release version\n"
748+
" -R, --relative-crc Emit section relative symbol CRCs\n"
745749
#else /* __GNU_LIBRARY__ */
746750
" -s Select symbol prefix\n"
747751
" -d Increment the debug level (repeatable)\n"
@@ -753,6 +757,7 @@ static void genksyms_usage(void)
753757
" -q Disable warnings (default)\n"
754758
" -h Print this message\n"
755759
" -V Print the release version\n"
760+
" -R Emit section relative symbol CRCs\n"
756761
#endif /* __GNU_LIBRARY__ */
757762
, stderr);
758763
}
@@ -774,13 +779,14 @@ int main(int argc, char **argv)
774779
{"preserve", 0, 0, 'p'},
775780
{"version", 0, 0, 'V'},
776781
{"help", 0, 0, 'h'},
782+
{"relative-crc", 0, 0, 'R'},
777783
{0, 0, 0, 0}
778784
};
779785

780-
while ((o = getopt_long(argc, argv, "s:dwqVDr:T:ph",
786+
while ((o = getopt_long(argc, argv, "s:dwqVDr:T:phR",
781787
&long_opts[0], NULL)) != EOF)
782788
#else /* __GNU_LIBRARY__ */
783-
while ((o = getopt(argc, argv, "s:dwqVDr:T:ph")) != EOF)
789+
while ((o = getopt(argc, argv, "s:dwqVDr:T:phR")) != EOF)
784790
#endif /* __GNU_LIBRARY__ */
785791
switch (o) {
786792
case 's':
@@ -823,6 +829,9 @@ int main(int argc, char **argv)
823829
case 'h':
824830
genksyms_usage();
825831
return 0;
832+
case 'R':
833+
flag_rel_crcs = 1;
834+
break;
826835
default:
827836
genksyms_usage();
828837
return 1;

scripts/kallsyms.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,10 @@ static int symbol_valid(struct sym_entry *s)
219219
"_SDA2_BASE_", /* ppc */
220220
NULL };
221221

222+
static char *special_prefixes[] = {
223+
"__crc_", /* modversions */
224+
NULL };
225+
222226
static char *special_suffixes[] = {
223227
"_veneer", /* arm */
224228
"_from_arm", /* arm */
@@ -259,6 +263,14 @@ static int symbol_valid(struct sym_entry *s)
259263
if (strcmp(sym_name, special_symbols[i]) == 0)
260264
return 0;
261265

266+
for (i = 0; special_prefixes[i]; i++) {
267+
int l = strlen(special_prefixes[i]);
268+
269+
if (l <= strlen(sym_name) &&
270+
strncmp(sym_name, special_prefixes[i], l) == 0)
271+
return 0;
272+
}
273+
262274
for (i = 0; special_suffixes[i]; i++) {
263275
int l = strlen(sym_name) - strlen(special_suffixes[i]);
264276

scripts/mod/modpost.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -621,6 +621,16 @@ static void handle_modversions(struct module *mod, struct elf_info *info,
621621
if (strncmp(symname, CRC_PFX, strlen(CRC_PFX)) == 0) {
622622
is_crc = true;
623623
crc = (unsigned int) sym->st_value;
624+
if (sym->st_shndx != SHN_UNDEF && sym->st_shndx != SHN_ABS) {
625+
unsigned int *crcp;
626+
627+
/* symbol points to the CRC in the ELF object */
628+
crcp = (void *)info->hdr + sym->st_value +
629+
info->sechdrs[sym->st_shndx].sh_offset -
630+
(info->hdr->e_type != ET_REL ?
631+
info->sechdrs[sym->st_shndx].sh_addr : 0);
632+
crc = *crcp;
633+
}
624634
sym_update_crc(symname + strlen(CRC_PFX), mod, crc,
625635
export);
626636
}

0 commit comments

Comments
 (0)