mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	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>
This commit is contained in:
		
							parent
							
								
									34e00accf6
								
							
						
					
					
						commit
						56067812d5
					
				
					 5 changed files with 42 additions and 5 deletions
				
			
		| 
						 | 
					@ -1987,6 +1987,10 @@ config MODVERSIONS
 | 
				
			||||||
	  make them incompatible with the kernel you are running.  If
 | 
						  make them incompatible with the kernel you are running.  If
 | 
				
			||||||
	  unsure, say N.
 | 
						  unsure, say N.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					config MODULE_REL_CRCS
 | 
				
			||||||
 | 
						bool
 | 
				
			||||||
 | 
						depends on MODVERSIONS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
config MODULE_SRCVERSION_ALL
 | 
					config MODULE_SRCVERSION_ALL
 | 
				
			||||||
	bool "Source checksum for all modules"
 | 
						bool "Source checksum for all modules"
 | 
				
			||||||
	help
 | 
						help
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -164,6 +164,7 @@ cmd_gensymtypes_c =                                                         \
 | 
				
			||||||
    $(CPP) -D__GENKSYMS__ $(c_flags) $< |                                   \
 | 
					    $(CPP) -D__GENKSYMS__ $(c_flags) $< |                                   \
 | 
				
			||||||
    $(GENKSYMS) $(if $(1), -T $(2))                                         \
 | 
					    $(GENKSYMS) $(if $(1), -T $(2))                                         \
 | 
				
			||||||
     $(patsubst y,-s _,$(CONFIG_HAVE_UNDERSCORE_SYMBOL_PREFIX))             \
 | 
					     $(patsubst y,-s _,$(CONFIG_HAVE_UNDERSCORE_SYMBOL_PREFIX))             \
 | 
				
			||||||
 | 
					     $(patsubst y,-R,$(CONFIG_MODULE_REL_CRCS))                             \
 | 
				
			||||||
     $(if $(KBUILD_PRESERVE),-p)                                            \
 | 
					     $(if $(KBUILD_PRESERVE),-p)                                            \
 | 
				
			||||||
     -r $(firstword $(wildcard $(2:.symtypes=.symref) /dev/null))
 | 
					     -r $(firstword $(wildcard $(2:.symtypes=.symref) /dev/null))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -337,6 +338,7 @@ cmd_gensymtypes_S =                                                         \
 | 
				
			||||||
    $(CPP) -D__GENKSYMS__ $(c_flags) -xc - |                                \
 | 
					    $(CPP) -D__GENKSYMS__ $(c_flags) -xc - |                                \
 | 
				
			||||||
    $(GENKSYMS) $(if $(1), -T $(2))                                         \
 | 
					    $(GENKSYMS) $(if $(1), -T $(2))                                         \
 | 
				
			||||||
     $(patsubst y,-s _,$(CONFIG_HAVE_UNDERSCORE_SYMBOL_PREFIX))             \
 | 
					     $(patsubst y,-s _,$(CONFIG_HAVE_UNDERSCORE_SYMBOL_PREFIX))             \
 | 
				
			||||||
 | 
					     $(patsubst y,-R,$(CONFIG_MODULE_REL_CRCS))                             \
 | 
				
			||||||
     $(if $(KBUILD_PRESERVE),-p)                                            \
 | 
					     $(if $(KBUILD_PRESERVE),-p)                                            \
 | 
				
			||||||
     -r $(firstword $(wildcard $(2:.symtypes=.symref) /dev/null))
 | 
					     -r $(firstword $(wildcard $(2:.symtypes=.symref) /dev/null))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -44,7 +44,7 @@ char *cur_filename, *source_file;
 | 
				
			||||||
int in_source_file;
 | 
					int in_source_file;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int flag_debug, flag_dump_defs, flag_reference, flag_dump_types,
 | 
					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 const char *mod_prefix = "";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int errors;
 | 
					static int errors;
 | 
				
			||||||
| 
						 | 
					@ -693,7 +693,10 @@ void export_symbol(const char *name)
 | 
				
			||||||
			fputs(">\n", debugfile);
 | 
								fputs(">\n", debugfile);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/* Used as a linker script. */
 | 
							/* 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);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -730,7 +733,7 @@ void error_with_pos(const char *fmt, ...)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void genksyms_usage(void)
 | 
					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__
 | 
					#ifdef __GNU_LIBRARY__
 | 
				
			||||||
	      "  -s, --symbol-prefix   Select symbol prefix\n"
 | 
						      "  -s, --symbol-prefix   Select symbol prefix\n"
 | 
				
			||||||
	      "  -d, --debug           Increment the debug level (repeatable)\n"
 | 
						      "  -d, --debug           Increment the debug level (repeatable)\n"
 | 
				
			||||||
| 
						 | 
					@ -742,6 +745,7 @@ static void genksyms_usage(void)
 | 
				
			||||||
	      "  -q, --quiet           Disable warnings (default)\n"
 | 
						      "  -q, --quiet           Disable warnings (default)\n"
 | 
				
			||||||
	      "  -h, --help            Print this message\n"
 | 
						      "  -h, --help            Print this message\n"
 | 
				
			||||||
	      "  -V, --version         Print the release version\n"
 | 
						      "  -V, --version         Print the release version\n"
 | 
				
			||||||
 | 
						      "  -R, --relative-crc    Emit section relative symbol CRCs\n"
 | 
				
			||||||
#else				/* __GNU_LIBRARY__ */
 | 
					#else				/* __GNU_LIBRARY__ */
 | 
				
			||||||
	      "  -s                    Select symbol prefix\n"
 | 
						      "  -s                    Select symbol prefix\n"
 | 
				
			||||||
	      "  -d                    Increment the debug level (repeatable)\n"
 | 
						      "  -d                    Increment the debug level (repeatable)\n"
 | 
				
			||||||
| 
						 | 
					@ -753,6 +757,7 @@ static void genksyms_usage(void)
 | 
				
			||||||
	      "  -q                    Disable warnings (default)\n"
 | 
						      "  -q                    Disable warnings (default)\n"
 | 
				
			||||||
	      "  -h                    Print this message\n"
 | 
						      "  -h                    Print this message\n"
 | 
				
			||||||
	      "  -V                    Print the release version\n"
 | 
						      "  -V                    Print the release version\n"
 | 
				
			||||||
 | 
						      "  -R                    Emit section relative symbol CRCs\n"
 | 
				
			||||||
#endif				/* __GNU_LIBRARY__ */
 | 
					#endif				/* __GNU_LIBRARY__ */
 | 
				
			||||||
	      , stderr);
 | 
						      , stderr);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -774,13 +779,14 @@ int main(int argc, char **argv)
 | 
				
			||||||
		{"preserve", 0, 0, 'p'},
 | 
							{"preserve", 0, 0, 'p'},
 | 
				
			||||||
		{"version", 0, 0, 'V'},
 | 
							{"version", 0, 0, 'V'},
 | 
				
			||||||
		{"help", 0, 0, 'h'},
 | 
							{"help", 0, 0, 'h'},
 | 
				
			||||||
 | 
							{"relative-crc", 0, 0, 'R'},
 | 
				
			||||||
		{0, 0, 0, 0}
 | 
							{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)
 | 
									&long_opts[0], NULL)) != EOF)
 | 
				
			||||||
#else				/* __GNU_LIBRARY__ */
 | 
					#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__ */
 | 
					#endif				/* __GNU_LIBRARY__ */
 | 
				
			||||||
		switch (o) {
 | 
							switch (o) {
 | 
				
			||||||
		case 's':
 | 
							case 's':
 | 
				
			||||||
| 
						 | 
					@ -823,6 +829,9 @@ int main(int argc, char **argv)
 | 
				
			||||||
		case 'h':
 | 
							case 'h':
 | 
				
			||||||
			genksyms_usage();
 | 
								genksyms_usage();
 | 
				
			||||||
			return 0;
 | 
								return 0;
 | 
				
			||||||
 | 
							case 'R':
 | 
				
			||||||
 | 
								flag_rel_crcs = 1;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
		default:
 | 
							default:
 | 
				
			||||||
			genksyms_usage();
 | 
								genksyms_usage();
 | 
				
			||||||
			return 1;
 | 
								return 1;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -219,6 +219,10 @@ static int symbol_valid(struct sym_entry *s)
 | 
				
			||||||
		"_SDA2_BASE_",		/* ppc */
 | 
							"_SDA2_BASE_",		/* ppc */
 | 
				
			||||||
		NULL };
 | 
							NULL };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						static char *special_prefixes[] = {
 | 
				
			||||||
 | 
							"__crc_",		/* modversions */
 | 
				
			||||||
 | 
							NULL };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	static char *special_suffixes[] = {
 | 
						static char *special_suffixes[] = {
 | 
				
			||||||
		"_veneer",		/* arm */
 | 
							"_veneer",		/* arm */
 | 
				
			||||||
		"_from_arm",		/* arm */
 | 
							"_from_arm",		/* arm */
 | 
				
			||||||
| 
						 | 
					@ -259,6 +263,14 @@ static int symbol_valid(struct sym_entry *s)
 | 
				
			||||||
		if (strcmp(sym_name, special_symbols[i]) == 0)
 | 
							if (strcmp(sym_name, special_symbols[i]) == 0)
 | 
				
			||||||
			return 0;
 | 
								return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = 0; special_prefixes[i]; i++) {
 | 
				
			||||||
 | 
							int l = strlen(special_prefixes[i]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (l <= strlen(sym_name) &&
 | 
				
			||||||
 | 
							    strncmp(sym_name, special_prefixes[i], l) == 0)
 | 
				
			||||||
 | 
								return 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (i = 0; special_suffixes[i]; i++) {
 | 
						for (i = 0; special_suffixes[i]; i++) {
 | 
				
			||||||
		int l = strlen(sym_name) - strlen(special_suffixes[i]);
 | 
							int l = strlen(sym_name) - strlen(special_suffixes[i]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -621,6 +621,16 @@ static void handle_modversions(struct module *mod, struct elf_info *info,
 | 
				
			||||||
	if (strncmp(symname, CRC_PFX, strlen(CRC_PFX)) == 0) {
 | 
						if (strncmp(symname, CRC_PFX, strlen(CRC_PFX)) == 0) {
 | 
				
			||||||
		is_crc = true;
 | 
							is_crc = true;
 | 
				
			||||||
		crc = (unsigned int) sym->st_value;
 | 
							crc = (unsigned int) sym->st_value;
 | 
				
			||||||
 | 
							if (sym->st_shndx != SHN_UNDEF && sym->st_shndx != SHN_ABS) {
 | 
				
			||||||
 | 
								unsigned int *crcp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								/* symbol points to the CRC in the ELF object */
 | 
				
			||||||
 | 
								crcp = (void *)info->hdr + sym->st_value +
 | 
				
			||||||
 | 
								       info->sechdrs[sym->st_shndx].sh_offset -
 | 
				
			||||||
 | 
								       (info->hdr->e_type != ET_REL ?
 | 
				
			||||||
 | 
									info->sechdrs[sym->st_shndx].sh_addr : 0);
 | 
				
			||||||
 | 
								crc = *crcp;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		sym_update_crc(symname + strlen(CRC_PFX), mod, crc,
 | 
							sym_update_crc(symname + strlen(CRC_PFX), mod, crc,
 | 
				
			||||||
				export);
 | 
									export);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue