From patchwork Wed Oct 31 08:42:53 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vincent Whitchurch X-Patchwork-Id: 10662213 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 14E4C14E2 for ; Wed, 31 Oct 2018 08:43:34 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 023852A491 for ; Wed, 31 Oct 2018 08:43:34 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id EA28D2A497; Wed, 31 Oct 2018 08:43:33 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.9 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI,RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 2A6092A491 for ; Wed, 31 Oct 2018 08:43:33 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:Message-Id:Date: Subject:To:From:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To: References:List-Owner; bh=XSX1llenF5HocQcCCn6ztCQFtRNUjCMP+dRRene8Tzo=; b=Zd+ fTkG8ef18bD2Han6DPSQBrXfShHbu7883hR4T4gFjO/ClLey88zt76/wwReZGA8LJLAlATUVGf/hh +9OfzEpfBQHA4xmV68SHMKuEi2LHqvZHsX/cWlA7mRaIgbx4t23mf3yurmGKipeo0dcjmCanuxVk7 fncDcG67SIWYrP+S0HW0oXQNo0RgbYSuxofr3lY9Ld2Q/+DAvC2dEzgpEL1jJtWcziNa7uPcj3lcW q70FIu5x6nYi29JabgsneA9zH+ltYoKDLVj8GBltuCQgplpYeC3SqNkoYI2yXd0W8uEfgXnZuymBZ flMjZ0F+Q9u+16wYYnT4ruF57ZJzXqw==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1gHm62-00034z-8m; Wed, 31 Oct 2018 08:43:26 +0000 Received: from bastet.se.axis.com ([195.60.68.11]) by bombadil.infradead.org with esmtps (Exim 4.90_1 #2 (Red Hat Linux)) id 1gHm5y-00034G-GE for linux-arm-kernel@lists.infradead.org; Wed, 31 Oct 2018 08:43:24 +0000 Received: from localhost (localhost [127.0.0.1]) by bastet.se.axis.com (Postfix) with ESMTP id 0688A18477; Wed, 31 Oct 2018 09:43:09 +0100 (CET) X-Virus-Scanned: Debian amavisd-new at bastet.se.axis.com Received: from bastet.se.axis.com ([IPv6:::ffff:127.0.0.1]) by localhost (bastet.se.axis.com [::ffff:127.0.0.1]) (amavisd-new, port 10024) with LMTP id yRc14r5GZQ2w; Wed, 31 Oct 2018 09:43:08 +0100 (CET) Received: from boulder03.se.axis.com (boulder03.se.axis.com [10.0.8.17]) by bastet.se.axis.com (Postfix) with ESMTPS id 0F6AE18393; Wed, 31 Oct 2018 09:43:07 +0100 (CET) Received: from boulder03.se.axis.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id D3E5C1E08D; Wed, 31 Oct 2018 09:43:07 +0100 (CET) Received: from boulder03.se.axis.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id C87101E081; Wed, 31 Oct 2018 09:43:07 +0100 (CET) Received: from seth.se.axis.com (unknown [10.0.2.172]) by boulder03.se.axis.com (Postfix) with ESMTP; Wed, 31 Oct 2018 09:43:07 +0100 (CET) Received: from lnxartpec.se.axis.com (lnxartpec.se.axis.com [10.88.4.9]) by seth.se.axis.com (Postfix) with ESMTP id BC5002355; Wed, 31 Oct 2018 09:43:07 +0100 (CET) Received: by lnxartpec.se.axis.com (Postfix, from userid 10564) id B845780AD5; Wed, 31 Oct 2018 09:43:07 +0100 (CET) From: Vincent Whitchurch To: linux@armlinux.org.uk, jeyu@kernel.org Subject: [PATCH v2] ARM: module: Fix function kallsyms on Thumb-2 Date: Wed, 31 Oct 2018 09:42:53 +0100 Message-Id: <20181031084253.9650-1-vincent.whitchurch@axis.com> X-Mailer: git-send-email 2.11.0 X-TM-AS-GCONF: 00 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20181031_014322_869335_73C5B2AE X-CRM114-Status: GOOD ( 17.33 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, Vincent Whitchurch MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP Thumb-2 functions have the lowest bit set in the symbol value in the symtab. When kallsyms are generated for the vmlinux, the kallsyms are generated from the output of nm, and nm clears the lowest bit. $ arm-linux-gnueabihf-readelf -a vmlinux | grep show_interrupts 95947: 8015dc89 686 FUNC GLOBAL DEFAULT 2 show_interrupts $ arm-linux-gnueabihf-nm vmlinux | grep show_interrupts 8015dc88 T show_interrupts $ cat /proc/kallsyms | grep show_interrupts 8015dc88 T show_interrupts However, for modules, the kallsyms uses the values in the symbol table without modification, so for functions in modules, the lowest bit is set in kallsyms. $ arm-linux-gnueabihf-readelf -a drivers/net/tun.ko | grep tun_get_socket 268: 000000e1 44 FUNC GLOBAL DEFAULT 2 tun_get_socket $ arm-linux-gnueabihf-nm drivers/net/tun.ko | grep tun_get_socket 000000e0 T tun_get_socket $ cat /proc/kallsyms | grep tun_get_socket 7fcd30e1 t tun_get_socket [tun] Because of this, the offset of the crashing instruction shown in oopses is incorrect when the crash is in a module. For example, given a tun_get_socket which starts like this, 000000e0 : e0: b500 push {lr} e2: f7ff fffe bl 0 <__gnu_mcount_nc> e6: 4b08 ldr r3, [pc, #32] e8: 6942 ldr r2, [r0, #20] ea: 429a cmp r2, r3 ec: d002 beq.n f4 a crash when tun_get_socket is called with NULL results in: PC is at tun_get_socket+0x7/0x2c [tun] pc : [<7fcdb0e8>] which can result in the incorrect line being reported by gdb if this symbol+offset is used there. If the crash is on the first instruction of a function, the "PC is at" line would also report the symbol name of the preceding function. To solve this, fix up these symbols like nm does. For this, we need a new hook in the generic module loading code, before the symbols' st_info is overwritten by add_kallsyms(). After the fix: $ cat /proc/kallsyms | grep tun_get_socket 7fcd30e0 t tun_get_socket [tun] PC is at tun_get_socket+0x8/0x2c [tun] pc : [<7fcdb0e8>] Signed-off-by: Vincent Whitchurch --- v2: Fix build warning with !MODULES arch/arm/kernel/module.c | 14 ++++++++++++++ include/linux/moduleloader.h | 3 +++ kernel/module.c | 6 ++++++ 3 files changed, 23 insertions(+) diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c index 3ff571c2c71c..771f86318d84 100644 --- a/arch/arm/kernel/module.c +++ b/arch/arm/kernel/module.c @@ -399,6 +399,20 @@ int module_finalize(const Elf32_Ehdr *hdr, const Elf_Shdr *sechdrs, return 0; } +#if defined(CONFIG_THUMB2_KERNEL) && defined(CONFIG_KALLSYMS) +void module_fixup_kallsyms(struct mod_kallsyms *kallsyms) +{ + int i; + + for (i = 0; i < kallsyms->num_symtab; i++) { + Elf_Sym *sym = &kallsyms->symtab[i]; + + if (ELF_ST_TYPE(sym->st_info) == STT_FUNC) + sym->st_value &= ~1; + } +} +#endif + void module_arch_cleanup(struct module *mod) { diff --git a/include/linux/moduleloader.h b/include/linux/moduleloader.h index 31013c2effd3..b1ac5584eaa5 100644 --- a/include/linux/moduleloader.h +++ b/include/linux/moduleloader.h @@ -86,6 +86,9 @@ void module_arch_cleanup(struct module *mod); /* Any cleanup before freeing mod->module_init */ void module_arch_freeing_init(struct module *mod); +struct mod_kallsyms; +void module_fixup_kallsyms(struct mod_kallsyms *kallsyms); + #ifdef CONFIG_KASAN #include #define MODULE_ALIGN (PAGE_SIZE << KASAN_SHADOW_SCALE_SHIFT) diff --git a/kernel/module.c b/kernel/module.c index 49a405891587..ded4f4b49824 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -2659,6 +2659,10 @@ static void layout_symtab(struct module *mod, struct load_info *info) mod->init_layout.size = debug_align(mod->init_layout.size); } +void __weak module_fixup_kallsyms(struct mod_kallsyms *kallsyms) +{ +} + /* * We use the full symtab and strtab which layout_symtab arranged to * be appended to the init section. Later we switch to the cut-down @@ -2680,6 +2684,8 @@ static void add_kallsyms(struct module *mod, const struct load_info *info) /* Make sure we get permanent strtab: don't use info->strtab. */ mod->kallsyms->strtab = (void *)info->sechdrs[info->index.str].sh_addr; + module_fixup_kallsyms(mod->kallsyms); + /* Set types up while we still have access to sections. */ for (i = 0; i < mod->kallsyms->num_symtab; i++) mod->kallsyms->symtab[i].st_info