linuxppc-dev.lists.ozlabs.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v4 0/2] modversions: redefine kcrctab entries as 32-bit values
@ 2017-01-24 16:16 Ard Biesheuvel
  2017-01-24 16:16 ` [PATCH v4 1/2] kbuild: modversions: add infrastructure for emitting relative CRCs Ard Biesheuvel
                   ` (3 more replies)
  0 siblings, 4 replies; 7+ messages in thread
From: Ard Biesheuvel @ 2017-01-24 16:16 UTC (permalink / raw)
  To: linux-kernel
  Cc: linuxppc-dev, akpm, torvalds, arnd, rusty, jeyu, mpe, viro,
	linux-arm-kernel, linux, linux-arch, Ard Biesheuvel

This v4 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.

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

Patch #2 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.

v4: make relative CRCs kconfig selectable
    use absolute CRC symbols in modules regardless of kconfig selection
    split into two patches

v3: emit CRCs into .rodata rather than .rodata.modver, given that the latter
    will be emitted with read-write permissions, making the CRCs end up in a
    writable module segment.

    fold the modpost fix to ensure that the section address is only substracted
    from the symbol address when the ELF object in question is fully linked
    (i.e., ET_DYN or ET_EXEC, and not ET_REL)

v2: update modpost as well, so that genksyms no longer has to emit symbols
    for both the actual CRC value and the reference to where it is stored
    in the image

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

Ard Biesheuvel (2):
  kbuild: modversions: add infrastructure for emitting relative CRCs
  modversions: treat symbol CRCs as 32 bit quantities

 arch/powerpc/Kconfig              |  1 +
 arch/powerpc/include/asm/module.h |  4 --
 arch/powerpc/kernel/module_64.c   |  8 ----
 include/asm-generic/export.h      | 11 ++---
 include/linux/export.h            | 14 ++++++
 include/linux/module.h            | 14 +++---
 init/Kconfig                      |  4 ++
 kernel/module.c                   | 45 ++++++++++----------
 scripts/Makefile.build            |  2 +
 scripts/genksyms/genksyms.c       | 19 ++++++---
 scripts/kallsyms.c                | 12 ++++++
 scripts/mod/modpost.c             | 10 +++++
 12 files changed, 93 insertions(+), 51 deletions(-)

-- 
2.7.4

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH v4 1/2] kbuild: modversions: add infrastructure for emitting relative CRCs
  2017-01-24 16:16 [PATCH v4 0/2] modversions: redefine kcrctab entries as 32-bit values Ard Biesheuvel
@ 2017-01-24 16:16 ` Ard Biesheuvel
  2017-01-24 16:16 ` [PATCH v4 2/2] modversions: treat symbol CRCs as 32 bit quantities Ard Biesheuvel
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 7+ messages in thread
From: Ard Biesheuvel @ 2017-01-24 16:16 UTC (permalink / raw)
  To: linux-kernel
  Cc: linuxppc-dev, akpm, torvalds, arnd, rusty, jeyu, mpe, viro,
	linux-arm-kernel, linux, linux-arch, Ard Biesheuvel

This add the kbuild infrastructure that will allow architectures to emit
vmlinux symbol CRCs as 32-bit offsets to other locations in the kernel
where the actual values are 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, and emitting the actual value
  into it
- 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>
---
 init/Kconfig                |  4 ++++
 scripts/Makefile.build      |  2 ++
 scripts/genksyms/genksyms.c | 19 ++++++++++++++-----
 scripts/kallsyms.c          | 12 ++++++++++++
 scripts/mod/modpost.c       | 10 ++++++++++
 5 files changed, 42 insertions(+), 5 deletions(-)

diff --git a/init/Kconfig b/init/Kconfig
index e1a937348a3e..4dd8bd232a1d 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -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
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index eadcd4d359d9..a9cfab2ee7c1 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -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))             \
+     $(if $(part-of-module),,$(patsubst y,-R,$(CONFIG_MODULE_REL_CRCS)))    \
      $(if $(KBUILD_PRESERVE),-p)                                            \
      -r $(firstword $(wildcard $(2:.symtypes=.symref) /dev/null))
 
@@ -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))             \
+     $(if $(part-of-module),,$(patsubst y,-R,$(CONFIG_MODULE_REL_CRCS)))    \
      $(if $(KBUILD_PRESERVE),-p)                                            \
      -r $(firstword $(wildcard $(2:.symtypes=.symref) /dev/null))
 
diff --git a/scripts/genksyms/genksyms.c b/scripts/genksyms/genksyms.c
index 06121ce524a7..c9235d8340f1 100644
--- a/scripts/genksyms/genksyms.c
+++ b/scripts/genksyms/genksyms.c
@@ -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;
@@ -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);
 	}
 }
 
@@ -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"
@@ -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"
@@ -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);
 }
@@ -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':
@@ -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;
diff --git a/scripts/kallsyms.c b/scripts/kallsyms.c
index 299b92ca1ae0..5d554419170b 100644
--- a/scripts/kallsyms.c
+++ b/scripts/kallsyms.c
@@ -219,6 +219,10 @@ static int symbol_valid(struct sym_entry *s)
 		"_SDA2_BASE_",		/* ppc */
 		NULL };
 
+	static char *special_prefixes[] = {
+		"__crc_",		/* modversions */
+		NULL };
+
 	static char *special_suffixes[] = {
 		"_veneer",		/* arm */
 		"_from_arm",		/* arm */
@@ -259,6 +263,14 @@ static int symbol_valid(struct sym_entry *s)
 		if (strcmp(sym_name, special_symbols[i]) == 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++) {
 		int l = strlen(sym_name) - strlen(special_suffixes[i]);
 
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index 29c89a6bad3d..ba89e5e953b5 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -619,8 +619,18 @@ static void handle_modversions(struct module *mod, struct elf_info *info,
 
 	/* CRC'd symbol */
 	if (strncmp(symname, CRC_PFX, strlen(CRC_PFX)) == 0) {
+		unsigned int *crcp = NULL;
+
 		is_crc = true;
 		crc = (unsigned int) sym->st_value;
+		if (sym->st_shndx != SHN_UNDEF && sym->st_shndx != SHN_ABS) {
+			/* 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 ? *crcp : 0;
+		}
 		sym_update_crc(symname + strlen(CRC_PFX), mod, crc,
 				export);
 	}
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH v4 2/2] modversions: treat symbol CRCs as 32 bit quantities
  2017-01-24 16:16 [PATCH v4 0/2] modversions: redefine kcrctab entries as 32-bit values Ard Biesheuvel
  2017-01-24 16:16 ` [PATCH v4 1/2] kbuild: modversions: add infrastructure for emitting relative CRCs Ard Biesheuvel
@ 2017-01-24 16:16 ` Ard Biesheuvel
  2017-01-27 16:13 ` [PATCH v4 0/2] modversions: redefine kcrctab entries as 32-bit values Ard Biesheuvel
  2017-02-03  3:54 ` Jessica Yu
  3 siblings, 0 replies; 7+ messages in thread
From: Ard Biesheuvel @ 2017-01-24 16:16 UTC (permalink / raw)
  To: linux-kernel
  Cc: linuxppc-dev, akpm, torvalds, arnd, rusty, jeyu, mpe, viro,
	linux-arm-kernel, linux, linux-arch, Ard Biesheuvel

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 core kernel's absolute CRC references
into relative references to where the actual CRC value is stored in .rodata

So redefine all CRC fields and variables as s32, 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")

Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 arch/powerpc/Kconfig              |  1 +
 arch/powerpc/include/asm/module.h |  4 --
 arch/powerpc/kernel/module_64.c   |  8 ----
 include/asm-generic/export.h      | 11 ++---
 include/linux/export.h            | 14 ++++++
 include/linux/module.h            | 14 +++---
 kernel/module.c                   | 45 ++++++++++----------
 7 files changed, 51 insertions(+), 46 deletions(-)

diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index a8ee573fe610..db8a1ef6bfaf 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -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
diff --git a/arch/powerpc/include/asm/module.h b/arch/powerpc/include/asm/module.h
index cc12c61ef315..53885512b8d3 100644
--- a/arch/powerpc/include/asm/module.h
+++ b/arch/powerpc/include/asm/module.h
@@ -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 */
diff --git a/arch/powerpc/kernel/module_64.c b/arch/powerpc/kernel/module_64.c
index bb1807184bad..0b0f89685b67 100644
--- a/arch/powerpc/kernel/module_64.c
+++ b/arch/powerpc/kernel/module_64.c
@@ -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
 		}
 }
 
diff --git a/include/asm-generic/export.h b/include/asm-generic/export.h
index 63554e9f6e0c..0dc6da121c49 100644
--- a/include/asm-generic/export.h
+++ b/include/asm-generic/export.h
@@ -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
@@ -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) && !defined(MODULE)
+	.long KSYM(__crc_\name) - .
+#else
+	.long KSYM(__crc_\name)
+#endif
 	.weak KSYM(__crc_\name)
 	.previous
 #endif
diff --git a/include/linux/export.h b/include/linux/export.h
index 2a0f61fbc731..fd197a5f0cc8 100644
--- a/include/linux/export.h
+++ b/include/linux/export.h
@@ -43,6 +43,13 @@ 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) && !defined(MODULE)
+#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");
+#elif !defined(CONFIG_64BIT)
 #define __CRC_SYMBOL(sym, sec)						\
 	extern __visible void *__crc_##sym __attribute__((weak));	\
 	static const unsigned long __kcrctab_##sym			\
@@ -50,6 +57,13 @@ extern struct module __this_module;
 	__attribute__((section("___kcrctab" sec "+" #sym), used))	\
 	= (unsigned long) &__crc_##sym;
 #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
 
diff --git a/include/linux/module.h b/include/linux/module.h
index 7c84273d60b9..cc7cba219b20 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -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. */
@@ -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
@@ -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 */
@@ -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,
@@ -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);
 
diff --git a/kernel/module.c b/kernel/module.c
index 5088784c0cf9..0ddfa3adf90d 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -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
@@ -497,7 +497,7 @@ struct find_symbol_arg {
 
 	/* Output */
 	struct module *owner;
-	const unsigned long *crc;
+	const s32 *crc;
 	const struct kernel_symbol *sym;
 };
 
@@ -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)
 {
@@ -1249,22 +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_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 s32 *crc,
 			 const struct module *crc_owner)
 {
 	unsigned int i, num_versions;
@@ -1283,13 +1278,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) && !crc_owner)
+			crcval = resolve_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;
 	}
 
@@ -1307,7 +1308,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
@@ -1340,7 +1341,7 @@ static inline int check_version(Elf_Shdr *sechdrs,
 				unsigned int versindex,
 				const char *symname,
 				struct module *mod,
-				const unsigned long *crc,
+				const s32 *crc,
 				const struct module *crc_owner)
 {
 	return 1;
@@ -1368,7 +1369,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;
 
 	/*
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH v4 0/2] modversions: redefine kcrctab entries as 32-bit values
  2017-01-24 16:16 [PATCH v4 0/2] modversions: redefine kcrctab entries as 32-bit values Ard Biesheuvel
  2017-01-24 16:16 ` [PATCH v4 1/2] kbuild: modversions: add infrastructure for emitting relative CRCs Ard Biesheuvel
  2017-01-24 16:16 ` [PATCH v4 2/2] modversions: treat symbol CRCs as 32 bit quantities Ard Biesheuvel
@ 2017-01-27 16:13 ` Ard Biesheuvel
  2017-02-03  3:54 ` Jessica Yu
  3 siblings, 0 replies; 7+ messages in thread
From: Ard Biesheuvel @ 2017-01-27 16:13 UTC (permalink / raw)
  To: linux-kernel@vger.kernel.org, Andrew Morton, Linus Torvalds
  Cc: linuxppc-dev, Arnd Bergmann, Rusty Russell, Jessica Yu,
	Michael Ellerman, viro@zeniv.linux.org.uk,
	linux-arm-kernel@lists.infradead.org, Russell King,
	linux-arch@vger.kernel.org, Ard Biesheuvel

On 24 January 2017 at 16:16, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
> This v4 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.
>
> Patch #1 introduces the MODULE_REL_CRCS Kconfig symbol, and adds the kbuild
> handling of it, i.e., modpost, genksyms and kallsyms.
>
> Patch #2 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.
>
> v4: make relative CRCs kconfig selectable
>     use absolute CRC symbols in modules regardless of kconfig selection
>     split into two patches
>
> v3: emit CRCs into .rodata rather than .rodata.modver, given that the latter
>     will be emitted with read-write permissions, making the CRCs end up in a
>     writable module segment.
>
>     fold the modpost fix to ensure that the section address is only substracted
>     from the symbol address when the ELF object in question is fully linked
>     (i.e., ET_DYN or ET_EXEC, and not ET_REL)
>
> v2: update modpost as well, so that genksyms no longer has to emit symbols
>     for both the actual CRC value and the reference to where it is stored
>     in the image
>
> [0] http://marc.info/?l=linux-arch&m=148493613415294&w=2
>
> Ard Biesheuvel (2):
>   kbuild: modversions: add infrastructure for emitting relative CRCs
>   modversions: treat symbol CRCs as 32 bit quantities
>

Linus, Andrew,

I think this code is in good shape now, given that I had to revert the
full switch to relative CRC references due to the fact many
architectures don't support that in modules, and so the only arch that
opts into these relative CRCs is power with CONFIG_RELOCATABLE=y.

I haven't heard any complaints or objections, so perhaps it is time to
get this queued somewhere.

Andrew, is this something you would be able to pick up? Thanks.

Regards,
Ard.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: modversions: redefine kcrctab entries as 32-bit values
  2017-01-24 16:16 [PATCH v4 0/2] modversions: redefine kcrctab entries as 32-bit values Ard Biesheuvel
                   ` (2 preceding siblings ...)
  2017-01-27 16:13 ` [PATCH v4 0/2] modversions: redefine kcrctab entries as 32-bit values Ard Biesheuvel
@ 2017-02-03  3:54 ` Jessica Yu
  2017-02-03  5:09   ` Jessica Yu
  3 siblings, 1 reply; 7+ messages in thread
From: Jessica Yu @ 2017-02-03  3:54 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: linux-kernel, linuxppc-dev, akpm, torvalds, arnd, rusty, mpe,
	viro, linux-arm-kernel, linux, linux-arch

+++ Ard Biesheuvel [24/01/17 16:16 +0000]:
>This v4 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.
>
>Patch #1 introduces the MODULE_REL_CRCS Kconfig symbol, and adds the kbuild
>handling of it, i.e., modpost, genksyms and kallsyms.
>
>Patch #2 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.
>
>v4: make relative CRCs kconfig selectable
>    use absolute CRC symbols in modules regardless of kconfig selection
>    split into two patches

This asymmetry threw me off a bit, especially the Kconfig naming (only
vmlinux crcs get the relative offsets, and only on powerpc atm, but all
modules keep the absolute syms, but it is called MODULE_REL_CRCS...),
if we keep this asymmetric crc treatment, it would be really nice to
note this discrepancy this somewhere, perhaps in the Kconfig, to keep
our heads from spinning :-)

I'm still catching up on the previous discussion threads, but can you
explain a bit more why you switched away from full blown relative crcs
from your last patchset [1]? I had lightly tested your v3 on ppc64le
previously, and relative offsets with modules seemed to worked very
well. I'm probably missing something very obvious.

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

>v3: emit CRCs into .rodata rather than .rodata.modver, given that the latter
>    will be emitted with read-write permissions, making the CRCs end up in a
>    writable module segment.
>
>    fold the modpost fix to ensure that the section address is only substracted
>    from the symbol address when the ELF object in question is fully linked
>    (i.e., ET_DYN or ET_EXEC, and not ET_REL)
>
>v2: update modpost as well, so that genksyms no longer has to emit symbols
>    for both the actual CRC value and the reference to where it is stored
>    in the image
>
>[0] http://marc.info/?l=linux-arch&m=148493613415294&w=2
>
>Ard Biesheuvel (2):
>  kbuild: modversions: add infrastructure for emitting relative CRCs
>  modversions: treat symbol CRCs as 32 bit quantities
>
> arch/powerpc/Kconfig              |  1 +
> arch/powerpc/include/asm/module.h |  4 --
> arch/powerpc/kernel/module_64.c   |  8 ----
> include/asm-generic/export.h      | 11 ++---
> include/linux/export.h            | 14 ++++++
> include/linux/module.h            | 14 +++---
> init/Kconfig                      |  4 ++
> kernel/module.c                   | 45 ++++++++++----------
> scripts/Makefile.build            |  2 +
> scripts/genksyms/genksyms.c       | 19 ++++++---
> scripts/kallsyms.c                | 12 ++++++
> scripts/mod/modpost.c             | 10 +++++
> 12 files changed, 93 insertions(+), 51 deletions(-)
>
>-- 
>2.7.4
>

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: modversions: redefine kcrctab entries as 32-bit values
  2017-02-03  3:54 ` Jessica Yu
@ 2017-02-03  5:09   ` Jessica Yu
  2017-02-03  8:31     ` Ard Biesheuvel
  0 siblings, 1 reply; 7+ messages in thread
From: Jessica Yu @ 2017-02-03  5:09 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: linux-kernel, linuxppc-dev, akpm, torvalds, arnd, rusty, mpe,
	viro, linux-arm-kernel, linux, linux-arch

+++ Jessica Yu [02/02/17 22:54 -0500]:
>+++ Ard Biesheuvel [24/01/17 16:16 +0000]:
>>This v4 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.
>>
>>Patch #1 introduces the MODULE_REL_CRCS Kconfig symbol, and adds the kbuild
>>handling of it, i.e., modpost, genksyms and kallsyms.
>>
>>Patch #2 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.
>>
>>v4: make relative CRCs kconfig selectable
>>   use absolute CRC symbols in modules regardless of kconfig selection
>>   split into two patches
>
>This asymmetry threw me off a bit, especially the Kconfig naming (only
>vmlinux crcs get the relative offsets, and only on powerpc atm, but all
>modules keep the absolute syms, but it is called MODULE_REL_CRCS...),
>if we keep this asymmetric crc treatment, it would be really nice to
>note this discrepancy this somewhere, perhaps in the Kconfig, to keep
>our heads from spinning :-)
>
>I'm still catching up on the previous discussion threads, but can you
>explain a bit more why you switched away from full blown relative crcs
>from your last patchset [1]? I had lightly tested your v3 on ppc64le
>previously, and relative offsets with modules seemed to worked very
>well. I'm probably missing something very obvious.

Ah, I just saw your other comment about other arches not having support
for the rel32 offsets :-/

The asymmetry still bothers me though. Can't we have something that just
switches relative crcs on and off, that applies to *both* vmlinux and modules?
Then we can get rid of the crc_owner check in check_version() and just have
something like:

   if (IS_ENABLED(CONFIG_RELATIVE_CRCS))
       crcval = resolve_crc(crc);

Also we could get rid of the '&& !defined(MODULE)' checks scattered in
export.h. Then the arches that want relative crcs and that *do* have rel32
relocation support can turn relative crcs on, and powerpc can enable it, right?

Would that work or is there another reason this won't work with modules
(assuming that the arches that select this option support the relative
offsets)?

Jessica

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: modversions: redefine kcrctab entries as 32-bit values
  2017-02-03  5:09   ` Jessica Yu
@ 2017-02-03  8:31     ` Ard Biesheuvel
  0 siblings, 0 replies; 7+ messages in thread
From: Ard Biesheuvel @ 2017-02-03  8:31 UTC (permalink / raw)
  To: Jessica Yu
  Cc: linux-kernel@vger.kernel.org, linuxppc-dev, Andrew Morton,
	Linus Torvalds, Arnd Bergmann, Rusty Russell, Michael Ellerman,
	viro@zeniv.linux.org.uk, linux-arm-kernel@lists.infradead.org,
	Russell King, linux-arch@vger.kernel.org

On 3 February 2017 at 05:09, Jessica Yu <jeyu@redhat.com> wrote:
> +++ Jessica Yu [02/02/17 22:54 -0500]:
>>
>> +++ Ard Biesheuvel [24/01/17 16:16 +0000]:
>>>
>>> This v4 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.
>>>
>>> Patch #1 introduces the MODULE_REL_CRCS Kconfig symbol, and adds the
>>> kbuild
>>> handling of it, i.e., modpost, genksyms and kallsyms.
>>>
>>> Patch #2 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.
>>>
>>> v4: make relative CRCs kconfig selectable
>>>   use absolute CRC symbols in modules regardless of kconfig selection
>>>   split into two patches
>>
>>
>> This asymmetry threw me off a bit, especially the Kconfig naming (only
>> vmlinux crcs get the relative offsets, and only on powerpc atm, but all
>> modules keep the absolute syms, but it is called MODULE_REL_CRCS...),
>> if we keep this asymmetric crc treatment, it would be really nice to
>> note this discrepancy this somewhere, perhaps in the Kconfig, to keep
>> our heads from spinning :-)
>>
>> I'm still catching up on the previous discussion threads, but can you
>> explain a bit more why you switched away from full blown relative crcs
>> from your last patchset [1]? I had lightly tested your v3 on ppc64le
>> previously, and relative offsets with modules seemed to worked very
>> well. I'm probably missing something very obvious.
>
>
> Ah, I just saw your other comment about other arches not having support
> for the rel32 offsets :-/
>
> The asymmetry still bothers me though. Can't we have something that just
> switches relative crcs on and off, that applies to *both* vmlinux and
> modules?
> Then we can get rid of the crc_owner check in check_version() and just have
> something like:
>
>   if (IS_ENABLED(CONFIG_RELATIVE_CRCS))
>       crcval = resolve_crc(crc);
>
> Also we could get rid of the '&& !defined(MODULE)' checks scattered in
> export.h. Then the arches that want relative crcs and that *do* have rel32
> relocation support can turn relative crcs on, and powerpc can enable it,
> right?
>

Indeed. My reasoning was that, given that we need to support both
absolute and relative CRCs anyway, it would make sense for modules to
keep using absolute ones regardless of what vmlinux is using, but it
does obfuscate the code a bit.

> Would that work or is there another reason this won't work with modules
> (assuming that the arches that select this option support the relative
> offsets)?
>

PowerPC with CONFIG_RELOCATABLE=y is really the only arch that
requires this atm, and it supports REL32 relocations just fine, both
for 32-bit and 64-bit.

I will respin the patches with the above modification.

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2017-02-03  8:31 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-01-24 16:16 [PATCH v4 0/2] modversions: redefine kcrctab entries as 32-bit values Ard Biesheuvel
2017-01-24 16:16 ` [PATCH v4 1/2] kbuild: modversions: add infrastructure for emitting relative CRCs Ard Biesheuvel
2017-01-24 16:16 ` [PATCH v4 2/2] modversions: treat symbol CRCs as 32 bit quantities Ard Biesheuvel
2017-01-27 16:13 ` [PATCH v4 0/2] modversions: redefine kcrctab entries as 32-bit values Ard Biesheuvel
2017-02-03  3:54 ` Jessica Yu
2017-02-03  5:09   ` Jessica Yu
2017-02-03  8:31     ` Ard Biesheuvel

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).