From patchwork Tue Jan 24 16:16:39 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 92371 Delivered-To: patch@linaro.org Received: by 10.182.3.34 with SMTP id 2csp1774394obz; Tue, 24 Jan 2017 08:16:59 -0800 (PST) X-Received: by 10.98.192.72 with SMTP id x69mr40247581pff.129.1485274619100; Tue, 24 Jan 2017 08:16:59 -0800 (PST) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id 16si19745573pfw.94.2017.01.24.08.16.58; Tue, 24 Jan 2017 08:16:59 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751211AbdAXQQ4 (ORCPT + 25 others); Tue, 24 Jan 2017 11:16:56 -0500 Received: from mail-wm0-f48.google.com ([74.125.82.48]:34032 "EHLO mail-wm0-f48.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751179AbdAXQQw (ORCPT ); Tue, 24 Jan 2017 11:16:52 -0500 Received: by mail-wm0-f48.google.com with SMTP id f73so44020164wmf.1 for ; Tue, 24 Jan 2017 08:16:51 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=Xm4wNHikED+4yRYlD55Gr7MLURhwa1TupfQRHXqIjHc=; b=LaLoEvtoBMG/ykOx6cVvlQBoI3ix+0dFP8nZ+EUSQt0U440vbhUDpWliiPg2DHtY1Y HRsT+p+jz7XTB/jmerXPHQPXs7ZUoEsvBJEN9hoO42jC/vXlHJNg3WHVPpzxJ7GavQDP dCJcl5EBOeDMFfB16OQ9e6MlDPwQZmxz4mRiI= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=Xm4wNHikED+4yRYlD55Gr7MLURhwa1TupfQRHXqIjHc=; b=WU+sNLy8nc6VsQbxCAGH9tffKMjGl+hFjwG2xWnLBJonEYH3nrG4Ac9a2ykLDpGmNF BW2dtlOgi3vqRJEzfOJjeUK6AYc/cC350MXzrhHc9TxN19QoyfJX2f31yczAjD4DlvTg o7eEHex+sS9K8Skj/KbMMUxjXPpYKjdBKjEaZYm2DHtF5LAfXmTI3K2dyLxhAgKs4SWj 5iJMKE6jtHqfjGwJrTZLRpTn69utqE/NmLiJramllwxAF9gcCssM1fLMAbbdkP0vm6ZK 4DHr29fRX0P+CLwQFkkDMBCNgamMpnmSv5Z+c2QfzoYa/JEtbv0Dwh6bA/gwGbFgwMxt JK1w== X-Gm-Message-State: AIkVDXLmqJjzfOPdDqgrP4I7LDhIpcphVt4Mk46W4ThZx5h9q9oZFv5WOsZW5u824h4k2mv3 X-Received: by 10.223.135.146 with SMTP id b18mr28631353wrb.189.1485274611039; Tue, 24 Jan 2017 08:16:51 -0800 (PST) Received: from localhost.localdomain ([160.163.215.165]) by smtp.gmail.com with ESMTPSA id n13sm17142511wrn.40.2017.01.24.08.16.48 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 24 Jan 2017 08:16:50 -0800 (PST) From: Ard Biesheuvel To: linux-kernel@vger.kernel.org Cc: linuxppc-dev@lists.ozlabs.org, akpm@linux-foundation.org, torvalds@linux-foundation.org, arnd@arndb.de, rusty@rustcorp.com.au, jeyu@redhat.com, mpe@ellerman.id.au, viro@zeniv.linux.org.uk, linux-arm-kernel@lists.infradead.org, linux@armlinux.org.uk, linux-arch@vger.kernel.org, Ard Biesheuvel Subject: [PATCH v4 1/2] kbuild: modversions: add infrastructure for emitting relative CRCs Date: Tue, 24 Jan 2017 16:16:39 +0000 Message-Id: <1485274600-21976-2-git-send-email-ard.biesheuvel@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1485274600-21976-1-git-send-email-ard.biesheuvel@linaro.org> References: <1485274600-21976-1-git-send-email-ard.biesheuvel@linaro.org> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 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 --- 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(-) -- 2.7.4 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); } From patchwork Tue Jan 24 16:16:40 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 92372 Delivered-To: patch@linaro.org Received: by 10.182.3.34 with SMTP id 2csp1774452obz; Tue, 24 Jan 2017 08:17:08 -0800 (PST) X-Received: by 10.98.44.10 with SMTP id s10mr39897081pfs.161.1485274628336; Tue, 24 Jan 2017 08:17:08 -0800 (PST) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id a71si19718339pfg.294.2017.01.24.08.17.08; Tue, 24 Jan 2017 08:17:08 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751228AbdAXQQ6 (ORCPT + 25 others); Tue, 24 Jan 2017 11:16:58 -0500 Received: from mail-wm0-f41.google.com ([74.125.82.41]:36164 "EHLO mail-wm0-f41.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751182AbdAXQQz (ORCPT ); Tue, 24 Jan 2017 11:16:55 -0500 Received: by mail-wm0-f41.google.com with SMTP id c85so189378839wmi.1 for ; Tue, 24 Jan 2017 08:16:55 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=DheGS+5lVPWbjxpMCvAd1ARetS4GdMx1bbCaf799eIg=; b=hb25ATWaAvmCLmKj310yOnUNSr+SuIc2XfQ5sMEc74BlzO3Vm+4FRNg8sYh3vH36Mk m8KSC9j+dGYx/1H44T0FZM2WfBnuPtBOnZDpaej594TU48bwq8bz5VXkQezIUmzioxQb 7KxZVbR7pE57UE1dYYgVsmQgAlZbBRvrlmDJg= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=DheGS+5lVPWbjxpMCvAd1ARetS4GdMx1bbCaf799eIg=; b=A/YklbZi/dGuzvCkvEodnqCrXacSqnTT5qlgk8r2P+N6tvJgYvmnkb1/swmuYy8OQ+ 1seE1FS/0jTJ0yjqWr2PHW9GnzXZPBnm2qyMkYXE0UQdUvd88Sst5BBnJh93FJek4e8a k3y6GNb7LhOnCIYCOZsUATb0EuY6cFfuAInF8thhXTRrUCeiWSVRZrjRbOYxwwbq1tWi svzLteFWli7O0n7IyHIdY/Y2OjAIxNRTR5pnRg2PZhdQ7f4n0qXw54xOjZvD7L/XGO0z Ceu0O7JTXQatKSkdJaGfAyQuVb3fdbPRPgzZZ2tYAFYo/hoL/2mCMk3yxl+bNYFxT2Zg TfSA== X-Gm-Message-State: AIkVDXICk/O+cscYksegH9w887JI63H+X38Gt7D/1xe/CtMmDFB1tEMjEjMnzmdhty/tqf9o X-Received: by 10.223.134.173 with SMTP id 42mr35500080wrx.95.1485274614070; Tue, 24 Jan 2017 08:16:54 -0800 (PST) Received: from localhost.localdomain ([160.163.215.165]) by smtp.gmail.com with ESMTPSA id n13sm17142511wrn.40.2017.01.24.08.16.51 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 24 Jan 2017 08:16:53 -0800 (PST) From: Ard Biesheuvel To: linux-kernel@vger.kernel.org Cc: linuxppc-dev@lists.ozlabs.org, akpm@linux-foundation.org, torvalds@linux-foundation.org, arnd@arndb.de, rusty@rustcorp.com.au, jeyu@redhat.com, mpe@ellerman.id.au, viro@zeniv.linux.org.uk, linux-arm-kernel@lists.infradead.org, linux@armlinux.org.uk, linux-arch@vger.kernel.org, Ard Biesheuvel Subject: [PATCH v4 2/2] modversions: treat symbol CRCs as 32 bit quantities Date: Tue, 24 Jan 2017 16:16:40 +0000 Message-Id: <1485274600-21976-3-git-send-email-ard.biesheuvel@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1485274600-21976-1-git-send-email-ard.biesheuvel@linaro.org> References: <1485274600-21976-1-git-send-email-ard.biesheuvel@linaro.org> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 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__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 --- 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(-) -- 2.7.4 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; /*