From patchwork Thu Mar 10 10:24:00 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aaron Tomlin X-Patchwork-Id: 12776122 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5B993C433F5 for ; Thu, 10 Mar 2022 10:24:29 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S241199AbiCJKZ0 (ORCPT ); Thu, 10 Mar 2022 05:25:26 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43534 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241191AbiCJKZW (ORCPT ); Thu, 10 Mar 2022 05:25:22 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 9EBCFF8B9A for ; Thu, 10 Mar 2022 02:24:21 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1646907860; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=4EEwWZZAjwW/ysDjBUtGda9incLc4VBnaTI9ZWPATn8=; b=iRGZASbl+J2wrpdphWtt5JgO/7YXQtTAedTL38OaI2HHTvuPaWzU79vz3tTxyeKtArTfrP KEXhzmd8urG4ZWpqnq+lY0RG7vKQm0tPTSQxDuUl49OFCe7UtvKb/3uUQPjlJlzs0flBcS G79t/KJdrEOHAKg7x3lR9qtA6l0apM0= Received: from mail-wm1-f72.google.com (mail-wm1-f72.google.com [209.85.128.72]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-390-LI7BXrDFOj-art2phvV8hQ-1; Thu, 10 Mar 2022 05:24:19 -0500 X-MC-Unique: LI7BXrDFOj-art2phvV8hQ-1 Received: by mail-wm1-f72.google.com with SMTP id z9-20020a7bc7c9000000b00389bd375677so2109253wmk.4 for ; Thu, 10 Mar 2022 02:24:19 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=4EEwWZZAjwW/ysDjBUtGda9incLc4VBnaTI9ZWPATn8=; b=aICmcX11r2jf9uXhszhiFg7eqYfqMdlHb6fnOjP2TVjXg3Tp0NTf8/mHMlnejNo4hA VHClMEwMv0Pvu6mbPN2dQO4aAm/qSJIqXrHklZhdbZ3AjMcNTGSVD5W+Yufyo05bQrwQ foTCNyX+2ltnDMVrDKWKzqQg4HmeXzkJ/C4WDKgk0sAkwZxNH2H1RoRGiv0qup1xI3Ik XAns+Y4gOB5mUBIiL+PQf47AwtS/pzrWPUYdPD2oCrkdNuSSyqhwgmV7hzeq5zzxw8uY 47P6RjILPBvwvbQAJCBK/v5iA6J6Sebt+dX1lQ7heFxzJZ87ZKRsrJZosagtGMApvWqD ax9A== X-Gm-Message-State: AOAM532fpHatorUuw6VclFpv+/mwlEUxFw5NZm2kfwF4FL0YDLlmtxgl W28o+qXjLv/1qKtUZ8V8klSSMLUV8qIRZt2dFpq5lD3ZImgNI+SUwkkIRTp3oBGkHyhEHGUne0V mmq/4+KLYyx1lTlQsfm1qoEa+ X-Received: by 2002:a7b:c759:0:b0:389:82c6:ac44 with SMTP id w25-20020a7bc759000000b0038982c6ac44mr10771847wmk.168.1646907858070; Thu, 10 Mar 2022 02:24:18 -0800 (PST) X-Google-Smtp-Source: ABdhPJzaAIauJ3yRWVTIXwFzuMrdwrmf1De1vL7r2OQYYp66nGe0Zhv7x29e7Yq0S2Clbw2mADX6CQ== X-Received: by 2002:a7b:c759:0:b0:389:82c6:ac44 with SMTP id w25-20020a7bc759000000b0038982c6ac44mr10771821wmk.168.1646907857816; Thu, 10 Mar 2022 02:24:17 -0800 (PST) Received: from localhost (cpc111743-lutn13-2-0-cust979.9-3.cable.virginm.net. [82.17.115.212]) by smtp.gmail.com with ESMTPSA id e18-20020adfdbd2000000b001e4bbbe5b92sm4097689wrj.76.2022.03.10.02.24.16 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 10 Mar 2022 02:24:16 -0800 (PST) From: Aaron Tomlin To: mcgrof@kernel.org, christophe.leroy@csgroup.eu Cc: cl@linux.com, mbenes@suse.cz, akpm@linux-foundation.org, jeyu@kernel.org, linux-kernel@vger.kernel.org, linux-modules@vger.kernel.org, void@manifault.com, atomlin@atomlin.com, allen.lkml@gmail.com, joe@perches.com, msuchanek@suse.de, oleksandr@natalenko.name, jason.wessel@windriver.com, pmladek@suse.com, daniel.thompson@linaro.org, hch@infradead.org Subject: [PATCH v11 01/14] module: Move all into module/ Date: Thu, 10 Mar 2022 10:24:00 +0000 Message-Id: <20220310102413.3438665-2-atomlin@redhat.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220310102413.3438665-1-atomlin@redhat.com> References: <20220310102413.3438665-1-atomlin@redhat.com> MIME-Version: 1.0 Precedence: bulk List-ID: No functional changes. This patch moves all module related code into a separate directory, modifies each file name and creates a new Makefile. Note: this effort is in preparation to refactor core module code. Reviewed-by: Christophe Leroy Signed-off-by: Aaron Tomlin --- MAINTAINERS | 2 +- kernel/Makefile | 5 +---- kernel/module/Makefile | 12 ++++++++++++ kernel/{module_decompress.c => module/decompress.c} | 2 +- kernel/{module-internal.h => module/internal.h} | 0 kernel/{module.c => module/main.c} | 2 +- kernel/{module_signing.c => module/signing.c} | 2 +- 7 files changed, 17 insertions(+), 8 deletions(-) create mode 100644 kernel/module/Makefile rename kernel/{module_decompress.c => module/decompress.c} (99%) rename kernel/{module-internal.h => module/internal.h} (100%) rename kernel/{module.c => module/main.c} (99%) rename kernel/{module_signing.c => module/signing.c} (97%) diff --git a/MAINTAINERS b/MAINTAINERS index bd86ed9fbc79..463bdb829db4 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -13012,7 +13012,7 @@ L: linux-kernel@vger.kernel.org S: Maintained T: git git://git.kernel.org/pub/scm/linux/kernel/git/mcgrof/linux.git modules-next F: include/linux/module.h -F: kernel/module.c +F: kernel/module/ MONOLITHIC POWER SYSTEM PMIC DRIVER M: Saravanan Sekar diff --git a/kernel/Makefile b/kernel/Makefile index 56f4ee97f328..717075b65deb 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -29,7 +29,6 @@ KCOV_INSTRUMENT_softirq.o := n KCSAN_SANITIZE_softirq.o = n # These are called from save_stack_trace() on slub debug path, # and produce insane amounts of uninteresting coverage. -KCOV_INSTRUMENT_module.o := n KCOV_INSTRUMENT_extable.o := n KCOV_INSTRUMENT_stacktrace.o := n # Don't self-instrument. @@ -53,6 +52,7 @@ obj-y += rcu/ obj-y += livepatch/ obj-y += dma/ obj-y += entry/ +obj-$(CONFIG_MODULES) += module/ obj-$(CONFIG_KCMP) += kcmp.o obj-$(CONFIG_FREEZER) += freezer.o @@ -66,9 +66,6 @@ ifneq ($(CONFIG_SMP),y) obj-y += up.o endif obj-$(CONFIG_UID16) += uid16.o -obj-$(CONFIG_MODULES) += module.o -obj-$(CONFIG_MODULE_DECOMPRESS) += module_decompress.o -obj-$(CONFIG_MODULE_SIG) += module_signing.o obj-$(CONFIG_MODULE_SIG_FORMAT) += module_signature.o obj-$(CONFIG_KALLSYMS) += kallsyms.o obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o diff --git a/kernel/module/Makefile b/kernel/module/Makefile new file mode 100644 index 000000000000..cdd5c61b8c7f --- /dev/null +++ b/kernel/module/Makefile @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +# Makefile for linux kernel module support +# + +# These are called from save_stack_trace() on slub debug path, +# and produce insane amounts of uninteresting coverage. +KCOV_INSTRUMENT_module.o := n + +obj-y += main.o +obj-$(CONFIG_MODULE_DECOMPRESS) += decompress.o +obj-$(CONFIG_MODULE_SIG) += signing.o diff --git a/kernel/module_decompress.c b/kernel/module/decompress.c similarity index 99% rename from kernel/module_decompress.c rename to kernel/module/decompress.c index ffef98a20320..d14d6443225a 100644 --- a/kernel/module_decompress.c +++ b/kernel/module/decompress.c @@ -12,7 +12,7 @@ #include #include -#include "module-internal.h" +#include "internal.h" static int module_extend_max_pages(struct load_info *info, unsigned int extent) { diff --git a/kernel/module-internal.h b/kernel/module/internal.h similarity index 100% rename from kernel/module-internal.h rename to kernel/module/internal.h diff --git a/kernel/module.c b/kernel/module/main.c similarity index 99% rename from kernel/module.c rename to kernel/module/main.c index 46a5c2ed1928..34a2b0cf3c3e 100644 --- a/kernel/module.c +++ b/kernel/module/main.c @@ -58,7 +58,7 @@ #include #include #include -#include "module-internal.h" +#include "internal.h" #define CREATE_TRACE_POINTS #include diff --git a/kernel/module_signing.c b/kernel/module/signing.c similarity index 97% rename from kernel/module_signing.c rename to kernel/module/signing.c index 8723ae70ea1f..8aeb6d2ee94b 100644 --- a/kernel/module_signing.c +++ b/kernel/module/signing.c @@ -12,7 +12,7 @@ #include #include #include -#include "module-internal.h" +#include "internal.h" /* * Verify the signature on a module. From patchwork Thu Mar 10 10:24:01 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aaron Tomlin X-Patchwork-Id: 12776123 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id E373CC433EF for ; Thu, 10 Mar 2022 10:24:29 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S241191AbiCJKZ2 (ORCPT ); Thu, 10 Mar 2022 05:25:28 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43636 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241195AbiCJKZY (ORCPT ); Thu, 10 Mar 2022 05:25:24 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 8B57213D921 for ; Thu, 10 Mar 2022 02:24:23 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1646907862; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Zln+MaotO9F3OZWBQkZ8RRcCDDlcbIVRMz8zB5PgPNY=; b=iwIbBldS/uzkG+HxBmwSrc5sMLiUtkl6va6tpMmHvLodSJarGmqDcqKsee1qrp3teGRbfL dS4EZlY5FeyLTLlowNjqkjzMdkl2gZNHJZB1nvd4zwX7zXSPmVVd6VRa2acDy8SKZ+1yCT Jup/wL9suNprX3ELNEBF6CmF6TXfRqI= Received: from mail-wr1-f69.google.com (mail-wr1-f69.google.com [209.85.221.69]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-450-17fasO-5Pwasmbd7PUZXgQ-1; Thu, 10 Mar 2022 05:24:21 -0500 X-MC-Unique: 17fasO-5Pwasmbd7PUZXgQ-1 Received: by mail-wr1-f69.google.com with SMTP id n4-20020a5d4844000000b001f1ed76e943so1528969wrs.22 for ; Thu, 10 Mar 2022 02:24:21 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=Zln+MaotO9F3OZWBQkZ8RRcCDDlcbIVRMz8zB5PgPNY=; b=DzCbjg2ZsbR+cfLfVCYJPIsHYiKJIwoOOdLc3JYsQItRkpfxS7qeBlfNWggEhzSpbn 42jBaq/rjWQ/H4Z7eYj4hYNXLpidaHO5bOKhs17kt0yF7rvmsAtgI7x99UthGrhu1PHm ytgc3FNpTV3BLzfiKtZWPHA0Z7GbUWqm44akNW7s9aqIQJt++3/Gyw64hQ/jedxNakxi 6FHdqmF6lfbBLAYx91ZIElWrGC4UG0+bFtFiQS8x+CbeIWvv8X/UzXwvgyP4kEhliIZ8 7nOi0MARi2Debt/C3R4zNPxPbyjOwDsnkMoI83BeGgjArHFg9tKTqnn9QBNHzRjk+Y5U LcpQ== X-Gm-Message-State: AOAM531hjs9IiqwQQYWN429oBKY/yUqRvV6rwwznjnSkKvMwfugxypyp 8n8dzqUhn/rL30f+EM+mpwHRhe7QyF/fdevws6cwQZJrOa72xflJtbKnyYF1xgYvzaa2jfWcj4F a8en4bGbEe/Kinfxi1eiwu0OO X-Received: by 2002:adf:8b9d:0:b0:1f1:deb6:5607 with SMTP id o29-20020adf8b9d000000b001f1deb65607mr2898699wra.125.1646907860151; Thu, 10 Mar 2022 02:24:20 -0800 (PST) X-Google-Smtp-Source: ABdhPJweWv0RKrVmS2LB0J6otlaOeOM8tWh3gB/Ilz7OujiA3W2eZ8wcYwZRhNt3P2NVKdD+/5ZluQ== X-Received: by 2002:adf:8b9d:0:b0:1f1:deb6:5607 with SMTP id o29-20020adf8b9d000000b001f1deb65607mr2898680wra.125.1646907859922; Thu, 10 Mar 2022 02:24:19 -0800 (PST) Received: from localhost (cpc111743-lutn13-2-0-cust979.9-3.cable.virginm.net. [82.17.115.212]) by smtp.gmail.com with ESMTPSA id c12-20020a05600c0a4c00b00381141f4967sm5509758wmq.35.2022.03.10.02.24.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 10 Mar 2022 02:24:19 -0800 (PST) From: Aaron Tomlin To: mcgrof@kernel.org, christophe.leroy@csgroup.eu Cc: cl@linux.com, mbenes@suse.cz, akpm@linux-foundation.org, jeyu@kernel.org, linux-kernel@vger.kernel.org, linux-modules@vger.kernel.org, void@manifault.com, atomlin@atomlin.com, allen.lkml@gmail.com, joe@perches.com, msuchanek@suse.de, oleksandr@natalenko.name, jason.wessel@windriver.com, pmladek@suse.com, daniel.thompson@linaro.org, hch@infradead.org Subject: [PATCH v11 02/14] module: Simple refactor in preparation for split Date: Thu, 10 Mar 2022 10:24:01 +0000 Message-Id: <20220310102413.3438665-3-atomlin@redhat.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220310102413.3438665-1-atomlin@redhat.com> References: <20220310102413.3438665-1-atomlin@redhat.com> MIME-Version: 1.0 Precedence: bulk List-ID: No functional change. This patch makes it possible to move non-essential code out of core module code. Reviewed-by: Christophe Leroy Signed-off-by: Aaron Tomlin --- kernel/module/internal.h | 21 +++++++++++++++++++++ kernel/module/main.c | 22 ++-------------------- 2 files changed, 23 insertions(+), 20 deletions(-) diff --git a/kernel/module/internal.h b/kernel/module/internal.h index 8c381c99062f..ea8c4c02614c 100644 --- a/kernel/module/internal.h +++ b/kernel/module/internal.h @@ -7,6 +7,27 @@ #include #include +#include + +#ifndef ARCH_SHF_SMALL +#define ARCH_SHF_SMALL 0 +#endif + +/* If this is set, the section belongs in the init part of the module */ +#define INIT_OFFSET_MASK (1UL << (BITS_PER_LONG - 1)) +/* Maximum number of characters written by module_flags() */ +#define MODULE_FLAGS_BUF_SIZE (TAINT_FLAGS_COUNT + 4) + +extern struct mutex module_mutex; +extern struct list_head modules; + +/* Provided by the linker */ +extern const struct kernel_symbol __start___ksymtab[]; +extern const struct kernel_symbol __stop___ksymtab[]; +extern const struct kernel_symbol __start___ksymtab_gpl[]; +extern const struct kernel_symbol __stop___ksymtab_gpl[]; +extern const s32 __start___kcrctab[]; +extern const s32 __start___kcrctab_gpl[]; struct load_info { const char *name; diff --git a/kernel/module/main.c b/kernel/module/main.c index 34a2b0cf3c3e..5f5e21f972dd 100644 --- a/kernel/module/main.c +++ b/kernel/module/main.c @@ -63,10 +63,6 @@ #define CREATE_TRACE_POINTS #include -#ifndef ARCH_SHF_SMALL -#define ARCH_SHF_SMALL 0 -#endif - /* * Modules' sections will be aligned on page boundaries * to ensure complete separation of code and data, but @@ -78,9 +74,6 @@ # define debug_align(X) (X) #endif -/* If this is set, the section belongs in the init part of the module */ -#define INIT_OFFSET_MASK (1UL << (BITS_PER_LONG-1)) - /* * Mutex protects: * 1) List of modules (also safely readable with preempt_disable), @@ -88,8 +81,8 @@ * 3) module_addr_min/module_addr_max. * (delete and add uses RCU list operations). */ -static DEFINE_MUTEX(module_mutex); -static LIST_HEAD(modules); +DEFINE_MUTEX(module_mutex); +LIST_HEAD(modules); /* Work queue for freeing init sections in success case */ static void do_free_init(struct work_struct *w); @@ -408,14 +401,6 @@ static __maybe_unused void *any_section_objs(const struct load_info *info, return (void *)info->sechdrs[sec].sh_addr; } -/* Provided by the linker */ -extern const struct kernel_symbol __start___ksymtab[]; -extern const struct kernel_symbol __stop___ksymtab[]; -extern const struct kernel_symbol __start___ksymtab_gpl[]; -extern const struct kernel_symbol __stop___ksymtab_gpl[]; -extern const s32 __start___kcrctab[]; -extern const s32 __start___kcrctab_gpl[]; - #ifndef CONFIG_MODVERSIONS #define symversion(base, idx) NULL #else @@ -4542,9 +4527,6 @@ static void cfi_cleanup(struct module *mod) #endif } -/* Maximum number of characters written by module_flags() */ -#define MODULE_FLAGS_BUF_SIZE (TAINT_FLAGS_COUNT + 4) - /* Keep in sync with MODULE_FLAGS_BUF_SIZE !!! */ static char *module_flags(struct module *mod, char *buf) { From patchwork Thu Mar 10 10:24:02 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aaron Tomlin X-Patchwork-Id: 12776124 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id D5BECC43217 for ; Thu, 10 Mar 2022 10:24:30 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S241192AbiCJKZ3 (ORCPT ); Thu, 10 Mar 2022 05:25:29 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43588 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241200AbiCJKZ0 (ORCPT ); Thu, 10 Mar 2022 05:25:26 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 0B02A12E778 for ; Thu, 10 Mar 2022 02:24:25 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1646907865; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=wTqJ9ZbJUCgx8VrF++WoBF0cwmRu2Y/rNRNUF4x8BCg=; b=HdbP3EkvkzOWuMqN6BI1XvJAQH7HHTeZjIxIWtqW0poYreOop6GBfoTc1g5NoKt7a7PYyw BDQhNhq5C5kiK7QGqO+kB+GhUM4K3LhJCCWaIvr7W6AUlH2HGthnBRPbclQ7NfovRdSqfL pXtb183eeU/wt84rPaQcyrKSBOIvwN4= Received: from mail-wm1-f69.google.com (mail-wm1-f69.google.com [209.85.128.69]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-468-eeCqwYD0NDarrBKHiJHeXg-1; Thu, 10 Mar 2022 05:24:24 -0500 X-MC-Unique: eeCqwYD0NDarrBKHiJHeXg-1 Received: by mail-wm1-f69.google.com with SMTP id l2-20020a1ced02000000b0038482a47e7eso3885942wmh.5 for ; Thu, 10 Mar 2022 02:24:23 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=wTqJ9ZbJUCgx8VrF++WoBF0cwmRu2Y/rNRNUF4x8BCg=; b=iq9uzRedPjwSfuK7NrKyQesHQD4ZNeQne3Jcy3xoEq2bOtNTZXs2tB83fuwcYH9DEo JjFmrOYO8wsSVl9PJLzliyf3h17qqv/rSPhTgQXL1hC6tOungbRIn5atNgKjIRmTE1LB ZoDWuUDaoM9b98NvrxopAtwYQDT9wEf9GZXsdaoOmv/tIOlc0rMPwW02DDxtcFs2zSup wcsC+xr04GUDacomcXENyKQ6krDVisj1e11+auXIYkH6MNbAwUqnDB6vQTB3duhFeww/ t5CrQ03qAN7JODBfWOUgNkz3QPXRfOVXxgmqQzLfbzSOTSAFdKlolTxrjDkoF1UOSIJf T99g== X-Gm-Message-State: AOAM5318GkgFBErqXVLz3zo1Urv8u/5fVmRwcle+mLDuYDheDkF5gVQV OdS9IFNZlXSOAGtV+fjqd1y9B58+B+RCk49OTSJIVGgAa2bHpM8wu5JmwGpYzCqZuv5FZjwWvN1 oFosN+7IhSvqRmLM3YA34btOv X-Received: by 2002:a5d:6acd:0:b0:1ef:78e9:193a with SMTP id u13-20020a5d6acd000000b001ef78e9193amr2859252wrw.281.1646907862772; Thu, 10 Mar 2022 02:24:22 -0800 (PST) X-Google-Smtp-Source: ABdhPJxosp4vZlvZRV/3seb2hsEji50NlARffFszjS0khGhETtQMUvvUkqMrK8nSd3At8EwhIPhucA== X-Received: by 2002:a5d:6acd:0:b0:1ef:78e9:193a with SMTP id u13-20020a5d6acd000000b001ef78e9193amr2859239wrw.281.1646907862534; Thu, 10 Mar 2022 02:24:22 -0800 (PST) Received: from localhost (cpc111743-lutn13-2-0-cust979.9-3.cable.virginm.net. [82.17.115.212]) by smtp.gmail.com with ESMTPSA id v14-20020a7bcb4e000000b0034492fa24c6sm4135515wmj.34.2022.03.10.02.24.20 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 10 Mar 2022 02:24:21 -0800 (PST) From: Aaron Tomlin To: mcgrof@kernel.org, christophe.leroy@csgroup.eu Cc: cl@linux.com, mbenes@suse.cz, akpm@linux-foundation.org, jeyu@kernel.org, linux-kernel@vger.kernel.org, linux-modules@vger.kernel.org, void@manifault.com, atomlin@atomlin.com, allen.lkml@gmail.com, joe@perches.com, msuchanek@suse.de, oleksandr@natalenko.name, jason.wessel@windriver.com, pmladek@suse.com, daniel.thompson@linaro.org, hch@infradead.org Subject: [PATCH v11 03/14] module: Make internal.h and decompress.c more compliant Date: Thu, 10 Mar 2022 10:24:02 +0000 Message-Id: <20220310102413.3438665-4-atomlin@redhat.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220310102413.3438665-1-atomlin@redhat.com> References: <20220310102413.3438665-1-atomlin@redhat.com> MIME-Version: 1.0 Precedence: bulk List-ID: This patch will address the following warning and style violations generated by ./scripts/checkpatch.pl in strict mode: WARNING: Use #include instead of #10: FILE: kernel/module/internal.h:10: +#include CHECK: spaces preferred around that '-' (ctx:VxV) #18: FILE: kernel/module/internal.h:18: +#define INIT_OFFSET_MASK (1UL << (BITS_PER_LONG-1)) CHECK: Please use a blank line after function/struct/union/enum declarations #69: FILE: kernel/module/internal.h:69: +} +static inline void module_decompress_cleanup(struct load_info *info) ^ CHECK: extern prototypes should be avoided in .h files #84: FILE: kernel/module/internal.h:84: +extern int mod_verify_sig(const void *mod, struct load_info *info); WARNING: Missing a blank line after declarations #116: FILE: kernel/module/decompress.c:116: + struct page *page = module_get_next_page(info); + if (!page) { WARNING: Missing a blank line after declarations #174: FILE: kernel/module/decompress.c:174: + struct page *page = module_get_next_page(info); + if (!page) { CHECK: Please use a blank line after function/struct/union/enum declarations #258: FILE: kernel/module/decompress.c:258: +} +static struct kobj_attribute module_compression_attr = __ATTR_RO(compression); Note: Fortunately, the multiple-include optimisation found in include/linux/module.h will prevent duplication/or inclusion more than once. Fixes: f314dfea16a ("modsign: log module name in the event of an error") Reviewed-by: Christophe Leroy Signed-off-by: Aaron Tomlin --- kernel/module/decompress.c | 3 +++ kernel/module/internal.h | 6 ++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/kernel/module/decompress.c b/kernel/module/decompress.c index d14d6443225a..2fc7081dd7c1 100644 --- a/kernel/module/decompress.c +++ b/kernel/module/decompress.c @@ -113,6 +113,7 @@ static ssize_t module_gzip_decompress(struct load_info *info, do { struct page *page = module_get_next_page(info); + if (!page) { retval = -ENOMEM; goto out_inflate_end; @@ -171,6 +172,7 @@ static ssize_t module_xz_decompress(struct load_info *info, do { struct page *page = module_get_next_page(info); + if (!page) { retval = -ENOMEM; goto out; @@ -256,6 +258,7 @@ static ssize_t compression_show(struct kobject *kobj, { return sysfs_emit(buf, "%s\n", __stringify(MODULE_COMPRESSION)); } + static struct kobj_attribute module_compression_attr = __ATTR_RO(compression); static int __init module_decompress_sysfs_init(void) diff --git a/kernel/module/internal.h b/kernel/module/internal.h index ea8c4c02614c..e0775e66bcf7 100644 --- a/kernel/module/internal.h +++ b/kernel/module/internal.h @@ -6,7 +6,8 @@ */ #include -#include +#include +#include #include #ifndef ARCH_SHF_SMALL @@ -54,7 +55,7 @@ struct load_info { } index; }; -extern int mod_verify_sig(const void *mod, struct load_info *info); +int mod_verify_sig(const void *mod, struct load_info *info); #ifdef CONFIG_MODULE_DECOMPRESS int module_decompress(struct load_info *info, const void *buf, size_t size); @@ -65,6 +66,7 @@ static inline int module_decompress(struct load_info *info, { return -EOPNOTSUPP; } + static inline void module_decompress_cleanup(struct load_info *info) { } From patchwork Thu Mar 10 10:24:03 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aaron Tomlin X-Patchwork-Id: 12776125 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5430AC43219 for ; Thu, 10 Mar 2022 10:24:31 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S241200AbiCJKZ3 (ORCPT ); Thu, 10 Mar 2022 05:25:29 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43936 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241204AbiCJKZ2 (ORCPT ); Thu, 10 Mar 2022 05:25:28 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 0CD5EF70D7 for ; Thu, 10 Mar 2022 02:24:27 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1646907867; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=0XjJucHH84WkOaA2Fzv90/VbRq4leBo+7myOeJDewzQ=; b=X+5AarYzZsdMcySQcdudePNOzukab37eXVUY11wcvWx71z87HWIoNa73DCRO0nWMd79WXQ ZY/bvEaAPwrIQ+5UEBQnWNcWulVitSOMunvGiaIAv8H8EUZ7jxJ1C0kVrPvqSh/MIW7qT9 7ddU5QAEeywq1j4FAN5ZbC6H29SoYpM= Received: from mail-wr1-f70.google.com (mail-wr1-f70.google.com [209.85.221.70]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-633-sroQwxF7MkyTR8Itawl8TQ-1; Thu, 10 Mar 2022 05:24:25 -0500 X-MC-Unique: sroQwxF7MkyTR8Itawl8TQ-1 Received: by mail-wr1-f70.google.com with SMTP id q14-20020adfea0e000000b002036c16c6daso1524338wrm.8 for ; Thu, 10 Mar 2022 02:24:25 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=0XjJucHH84WkOaA2Fzv90/VbRq4leBo+7myOeJDewzQ=; b=lmBUhv+VKvLT0Rt0IAADs2VVWTbQutMezhcO3orpRrT2iot8/3ihT8qAYGzwMD02Ns BbJAAudTAdEb/vZw7rMFrMLBAeexHhApH/SxanibLUlrHe2P0tWxczSGp900oz+dRNuk /7wT21NQrjB9n1WWPWLbD/SCPoIsVxWRdTe7znRnuafvFjRkugAWAPugpSGhxWOf9jIc 8RauRBSU8xNutX01yhb2naOeryAhtf1PPvHvfStw0yfVB000XxnuxJLy+MU3pthR213s 3EPGqCKcGDaFOrIiWCtMkku3vJCtqNXoKDbPMZ6j2FWhdFGJxmivF7U5PD46ZK6g/l2u MdXw== X-Gm-Message-State: AOAM530k6wgo1uZc0ukpTn9qh7dpbKkJ/zVf+QpZpe5cG6ZcQUyGxycX ondBepxNRqkNJ4W5rSydJw9rd9xV1qsW0dqgNguJLqaYVmOpwrM2uv9BLOhXFPpmP//OpM47EpI hyeUKIEaCA6iu75nZjcREsUSR X-Received: by 2002:adf:fd0a:0:b0:1f0:25fd:4082 with SMTP id e10-20020adffd0a000000b001f025fd4082mr2913161wrr.501.1646907864738; Thu, 10 Mar 2022 02:24:24 -0800 (PST) X-Google-Smtp-Source: ABdhPJwPR22J9v/ekxOLTN9INTYY5z2VKqugszxmvmhgvsGsDIx0STWDDncpe0zYWqIkyQDdqKf1mg== X-Received: by 2002:adf:fd0a:0:b0:1f0:25fd:4082 with SMTP id e10-20020adffd0a000000b001f025fd4082mr2913145wrr.501.1646907864509; Thu, 10 Mar 2022 02:24:24 -0800 (PST) Received: from localhost (cpc111743-lutn13-2-0-cust979.9-3.cable.virginm.net. [82.17.115.212]) by smtp.gmail.com with ESMTPSA id f8-20020adfb608000000b0020229d72a4esm3651641wre.38.2022.03.10.02.24.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 10 Mar 2022 02:24:23 -0800 (PST) From: Aaron Tomlin To: mcgrof@kernel.org, christophe.leroy@csgroup.eu Cc: cl@linux.com, mbenes@suse.cz, akpm@linux-foundation.org, jeyu@kernel.org, linux-kernel@vger.kernel.org, linux-modules@vger.kernel.org, void@manifault.com, atomlin@atomlin.com, allen.lkml@gmail.com, joe@perches.com, msuchanek@suse.de, oleksandr@natalenko.name, jason.wessel@windriver.com, pmladek@suse.com, daniel.thompson@linaro.org, hch@infradead.org Subject: [PATCH v11 04/14] module: Move livepatch support to a separate file Date: Thu, 10 Mar 2022 10:24:03 +0000 Message-Id: <20220310102413.3438665-5-atomlin@redhat.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220310102413.3438665-1-atomlin@redhat.com> References: <20220310102413.3438665-1-atomlin@redhat.com> MIME-Version: 1.0 Precedence: bulk List-ID: No functional change. This patch migrates livepatch support (i.e. used during module add/or load and remove/or deletion) from core module code into kernel/module/livepatch.c. At the moment it contains code to persist Elf information about a given livepatch module, only. The new file was added to MAINTAINERS. Reviewed-by: Petr Mladek Tested-by: Petr Mladek Signed-off-by: Aaron Tomlin --- MAINTAINERS | 1 + include/linux/module.h | 9 ++-- kernel/module/Makefile | 1 + kernel/module/internal.h | 22 ++++++++ kernel/module/livepatch.c | 74 +++++++++++++++++++++++++++ kernel/module/main.c | 102 ++++---------------------------------- 6 files changed, 111 insertions(+), 98 deletions(-) create mode 100644 kernel/module/livepatch.c diff --git a/MAINTAINERS b/MAINTAINERS index 463bdb829db4..195cf1ac2ee8 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -11149,6 +11149,7 @@ F: arch/s390/include/asm/livepatch.h F: arch/x86/include/asm/livepatch.h F: include/linux/livepatch.h F: kernel/livepatch/ +F: kernel/module/livepatch.c F: lib/livepatch/ F: samples/livepatch/ F: tools/testing/selftests/livepatch/ diff --git a/include/linux/module.h b/include/linux/module.h index 1e135fd5c076..7ec9715de7dc 100644 --- a/include/linux/module.h +++ b/include/linux/module.h @@ -663,17 +663,14 @@ static inline bool module_requested_async_probing(struct module *module) return module && module->async_probe_requested; } -#ifdef CONFIG_LIVEPATCH static inline bool is_livepatch_module(struct module *mod) { +#ifdef CONFIG_LIVEPATCH return mod->klp; -} -#else /* !CONFIG_LIVEPATCH */ -static inline bool is_livepatch_module(struct module *mod) -{ +#else return false; +#endif } -#endif /* CONFIG_LIVEPATCH */ bool is_module_sig_enforced(void); void set_module_sig_enforced(void); diff --git a/kernel/module/Makefile b/kernel/module/Makefile index cdd5c61b8c7f..ed3aacb04f17 100644 --- a/kernel/module/Makefile +++ b/kernel/module/Makefile @@ -10,3 +10,4 @@ KCOV_INSTRUMENT_module.o := n obj-y += main.o obj-$(CONFIG_MODULE_DECOMPRESS) += decompress.o obj-$(CONFIG_MODULE_SIG) += signing.o +obj-$(CONFIG_LIVEPATCH) += livepatch.o diff --git a/kernel/module/internal.h b/kernel/module/internal.h index e0775e66bcf7..ad7a444253ed 100644 --- a/kernel/module/internal.h +++ b/kernel/module/internal.h @@ -57,6 +57,28 @@ struct load_info { int mod_verify_sig(const void *mod, struct load_info *info); +#ifdef CONFIG_LIVEPATCH +int copy_module_elf(struct module *mod, struct load_info *info); +void free_module_elf(struct module *mod); +#else /* !CONFIG_LIVEPATCH */ +static inline int copy_module_elf(struct module *mod, struct load_info *info) +{ + return 0; +} + +static inline void free_module_elf(struct module *mod) { } +#endif /* CONFIG_LIVEPATCH */ + +static inline bool set_livepatch_module(struct module *mod) +{ +#ifdef CONFIG_LIVEPATCH + mod->klp = true; + return true; +#else + return false; +#endif +} + #ifdef CONFIG_MODULE_DECOMPRESS int module_decompress(struct load_info *info, const void *buf, size_t size); void module_decompress_cleanup(struct load_info *info); diff --git a/kernel/module/livepatch.c b/kernel/module/livepatch.c new file mode 100644 index 000000000000..486d4ff92719 --- /dev/null +++ b/kernel/module/livepatch.c @@ -0,0 +1,74 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Module livepatch support + * + * Copyright (C) 2016 Jessica Yu + */ + +#include +#include +#include +#include "internal.h" + +/* + * Persist Elf information about a module. Copy the Elf header, + * section header table, section string table, and symtab section + * index from info to mod->klp_info. + */ +int copy_module_elf(struct module *mod, struct load_info *info) +{ + unsigned int size, symndx; + int ret; + + size = sizeof(*mod->klp_info); + mod->klp_info = kmalloc(size, GFP_KERNEL); + if (!mod->klp_info) + return -ENOMEM; + + /* Elf header */ + size = sizeof(mod->klp_info->hdr); + memcpy(&mod->klp_info->hdr, info->hdr, size); + + /* Elf section header table */ + size = sizeof(*info->sechdrs) * info->hdr->e_shnum; + mod->klp_info->sechdrs = kmemdup(info->sechdrs, size, GFP_KERNEL); + if (!mod->klp_info->sechdrs) { + ret = -ENOMEM; + goto free_info; + } + + /* Elf section name string table */ + size = info->sechdrs[info->hdr->e_shstrndx].sh_size; + mod->klp_info->secstrings = kmemdup(info->secstrings, size, GFP_KERNEL); + if (!mod->klp_info->secstrings) { + ret = -ENOMEM; + goto free_sechdrs; + } + + /* Elf symbol section index */ + symndx = info->index.sym; + mod->klp_info->symndx = symndx; + + /* + * For livepatch modules, core_kallsyms.symtab is a complete + * copy of the original symbol table. Adjust sh_addr to point + * to core_kallsyms.symtab since the copy of the symtab in module + * init memory is freed at the end of do_init_module(). + */ + mod->klp_info->sechdrs[symndx].sh_addr = (unsigned long)mod->core_kallsyms.symtab; + + return 0; + +free_sechdrs: + kfree(mod->klp_info->sechdrs); +free_info: + kfree(mod->klp_info); + return ret; +} + +void free_module_elf(struct module *mod) +{ + kfree(mod->klp_info->sechdrs); + kfree(mod->klp_info->secstrings); + kfree(mod->klp_info); +} diff --git a/kernel/module/main.c b/kernel/module/main.c index 5f5e21f972dd..3596ebf3a6c3 100644 --- a/kernel/module/main.c +++ b/kernel/module/main.c @@ -2043,81 +2043,6 @@ static int module_enforce_rwx_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs, } #endif /* CONFIG_STRICT_MODULE_RWX */ -#ifdef CONFIG_LIVEPATCH -/* - * Persist Elf information about a module. Copy the Elf header, - * section header table, section string table, and symtab section - * index from info to mod->klp_info. - */ -static int copy_module_elf(struct module *mod, struct load_info *info) -{ - unsigned int size, symndx; - int ret; - - size = sizeof(*mod->klp_info); - mod->klp_info = kmalloc(size, GFP_KERNEL); - if (mod->klp_info == NULL) - return -ENOMEM; - - /* Elf header */ - size = sizeof(mod->klp_info->hdr); - memcpy(&mod->klp_info->hdr, info->hdr, size); - - /* Elf section header table */ - size = sizeof(*info->sechdrs) * info->hdr->e_shnum; - mod->klp_info->sechdrs = kmemdup(info->sechdrs, size, GFP_KERNEL); - if (mod->klp_info->sechdrs == NULL) { - ret = -ENOMEM; - goto free_info; - } - - /* Elf section name string table */ - size = info->sechdrs[info->hdr->e_shstrndx].sh_size; - mod->klp_info->secstrings = kmemdup(info->secstrings, size, GFP_KERNEL); - if (mod->klp_info->secstrings == NULL) { - ret = -ENOMEM; - goto free_sechdrs; - } - - /* Elf symbol section index */ - symndx = info->index.sym; - mod->klp_info->symndx = symndx; - - /* - * For livepatch modules, core_kallsyms.symtab is a complete - * copy of the original symbol table. Adjust sh_addr to point - * to core_kallsyms.symtab since the copy of the symtab in module - * init memory is freed at the end of do_init_module(). - */ - mod->klp_info->sechdrs[symndx].sh_addr = \ - (unsigned long) mod->core_kallsyms.symtab; - - return 0; - -free_sechdrs: - kfree(mod->klp_info->sechdrs); -free_info: - kfree(mod->klp_info); - return ret; -} - -static void free_module_elf(struct module *mod) -{ - kfree(mod->klp_info->sechdrs); - kfree(mod->klp_info->secstrings); - kfree(mod->klp_info); -} -#else /* !CONFIG_LIVEPATCH */ -static int copy_module_elf(struct module *mod, struct load_info *info) -{ - return 0; -} - -static void free_module_elf(struct module *mod) -{ -} -#endif /* CONFIG_LIVEPATCH */ - void __weak module_memfree(void *module_region) { /* @@ -3092,30 +3017,23 @@ static int copy_chunked_from_user(void *dst, const void __user *usrc, unsigned l return 0; } -#ifdef CONFIG_LIVEPATCH static int check_modinfo_livepatch(struct module *mod, struct load_info *info) { - if (get_modinfo(info, "livepatch")) { - mod->klp = true; + if (!get_modinfo(info, "livepatch")) + /* Nothing more to do */ + return 0; + + if (set_livepatch_module(mod)) { add_taint_module(mod, TAINT_LIVEPATCH, LOCKDEP_STILL_OK); pr_notice_once("%s: tainting kernel with TAINT_LIVEPATCH\n", - mod->name); - } - - return 0; -} -#else /* !CONFIG_LIVEPATCH */ -static int check_modinfo_livepatch(struct module *mod, struct load_info *info) -{ - if (get_modinfo(info, "livepatch")) { - pr_err("%s: module is marked as livepatch module, but livepatch support is disabled", - mod->name); - return -ENOEXEC; + mod->name); + return 0; } - return 0; + pr_err("%s: module is marked as livepatch module, but livepatch support is disabled", + mod->name); + return -ENOEXEC; } -#endif /* CONFIG_LIVEPATCH */ static void check_modinfo_retpoline(struct module *mod, struct load_info *info) { From patchwork Thu Mar 10 10:24:04 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aaron Tomlin X-Patchwork-Id: 12776126 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6DA52C433F5 for ; Thu, 10 Mar 2022 10:24:52 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S241278AbiCJKZu (ORCPT ); Thu, 10 Mar 2022 05:25:50 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44188 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241212AbiCJKZb (ORCPT ); Thu, 10 Mar 2022 05:25:31 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 909FAEB9 for ; Thu, 10 Mar 2022 02:24:30 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1646907869; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=eMk2ddem3feNmKWVGBt5fQ2XD1104DD2sU5e2PuX3nw=; b=cZkUillmQy6iwDp7t623IIjy9TLKwwCdoh6X6/XvbIvl6JCiBcMn3ySCF8t0rVV4dp3EUs z8wrCHrK4M/HQOAq1uj286Gy28XZX1SLJvaaPQpK4JcrAbRNsXBikz2k6ESrOxOiT1NcvP iNhGJgKlJKSDNcnE4W6CK6ICmTKC11k= Received: from mail-wr1-f71.google.com (mail-wr1-f71.google.com [209.85.221.71]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-58-dwFH2HOoMaeKfXLWngewwQ-1; Thu, 10 Mar 2022 05:24:28 -0500 X-MC-Unique: dwFH2HOoMaeKfXLWngewwQ-1 Received: by mail-wr1-f71.google.com with SMTP id e6-20020a5d4e86000000b001f045d4a962so1523036wru.21 for ; Thu, 10 Mar 2022 02:24:28 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=eMk2ddem3feNmKWVGBt5fQ2XD1104DD2sU5e2PuX3nw=; b=ri5GMXO7g3n3x4JgHJSH7b3tDmXgq4sR3v7zosmfnc0sLHFmIPaHB/d+6fmi28Xiii sCYSRWwtu4QpUO/ygzQuYnx7XN2Xd3TUfC5Wju3bv1HZzVc2a66IojOTjsuBFN3JQBsD peQmWdw/m4iyxD3SpesUJu99hNicotxzPzcyrnO5C5HexQgs95AL2oKPUSKdDd/wRmND fL6g+EapRptJCNESPaN5n/k+l+68tJ4xcKPWNa5VkboJiF7THlpcFEeTjn/1SnhH18Yh nRAkauUdytOfJwGxJ+Cr5LCgc2VZvnytsN/UMFhXl5+W+wWQcxatcKk8s9S08DFBStby P0TQ== X-Gm-Message-State: AOAM531bNDgMKOV0u9gVq0TZnUzXB5e2oY3d2WbfE/eQ9/RI2UFuvXVr m8Q2IsPRNFntZvSlRwrGochdv6Z1EGd9kzwDTk5wp3BNchjPgl6oN8IytHZYDVk9bzAtp6GtVDm TioFhJrbXEqUTIk5cPAbeZCbg X-Received: by 2002:adf:db43:0:b0:1ef:7195:43cd with SMTP id f3-20020adfdb43000000b001ef719543cdmr2971042wrj.495.1646907867110; Thu, 10 Mar 2022 02:24:27 -0800 (PST) X-Google-Smtp-Source: ABdhPJx0Qf8xJUqjh6peNUTRmcf2ljFBQkM3SSKlru3oSRpvFwhXBnz+fNL6u2goEsivMD5l/FKenQ== X-Received: by 2002:adf:db43:0:b0:1ef:7195:43cd with SMTP id f3-20020adfdb43000000b001ef719543cdmr2971022wrj.495.1646907866910; Thu, 10 Mar 2022 02:24:26 -0800 (PST) Received: from localhost (cpc111743-lutn13-2-0-cust979.9-3.cable.virginm.net. [82.17.115.212]) by smtp.gmail.com with ESMTPSA id l13-20020a5d4bcd000000b001f0620ecb3csm3755574wrt.40.2022.03.10.02.24.25 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 10 Mar 2022 02:24:25 -0800 (PST) From: Aaron Tomlin To: mcgrof@kernel.org, christophe.leroy@csgroup.eu Cc: cl@linux.com, mbenes@suse.cz, akpm@linux-foundation.org, jeyu@kernel.org, linux-kernel@vger.kernel.org, linux-modules@vger.kernel.org, void@manifault.com, atomlin@atomlin.com, allen.lkml@gmail.com, joe@perches.com, msuchanek@suse.de, oleksandr@natalenko.name, jason.wessel@windriver.com, pmladek@suse.com, daniel.thompson@linaro.org, hch@infradead.org Subject: [PATCH v11 05/14] module: Move latched RB-tree support to a separate file Date: Thu, 10 Mar 2022 10:24:04 +0000 Message-Id: <20220310102413.3438665-6-atomlin@redhat.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220310102413.3438665-1-atomlin@redhat.com> References: <20220310102413.3438665-1-atomlin@redhat.com> MIME-Version: 1.0 Precedence: bulk List-ID: No functional change. This patch migrates module latched RB-tree support (e.g. see __module_address()) from core module code into kernel/module/tree_lookup.c. Reviewed-by: Christophe Leroy Signed-off-by: Aaron Tomlin --- kernel/module/Makefile | 1 + kernel/module/internal.h | 33 +++++++++ kernel/module/main.c | 130 ++---------------------------------- kernel/module/tree_lookup.c | 109 ++++++++++++++++++++++++++++++ 4 files changed, 147 insertions(+), 126 deletions(-) create mode 100644 kernel/module/tree_lookup.c diff --git a/kernel/module/Makefile b/kernel/module/Makefile index ed3aacb04f17..88774e386276 100644 --- a/kernel/module/Makefile +++ b/kernel/module/Makefile @@ -11,3 +11,4 @@ obj-y += main.o obj-$(CONFIG_MODULE_DECOMPRESS) += decompress.o obj-$(CONFIG_MODULE_SIG) += signing.o obj-$(CONFIG_LIVEPATCH) += livepatch.o +obj-$(CONFIG_MODULES_TREE_LOOKUP) += tree_lookup.o diff --git a/kernel/module/internal.h b/kernel/module/internal.h index ad7a444253ed..f1682e3677be 100644 --- a/kernel/module/internal.h +++ b/kernel/module/internal.h @@ -9,6 +9,7 @@ #include #include #include +#include #ifndef ARCH_SHF_SMALL #define ARCH_SHF_SMALL 0 @@ -93,3 +94,35 @@ static inline void module_decompress_cleanup(struct load_info *info) { } #endif + +#ifdef CONFIG_MODULES_TREE_LOOKUP +struct mod_tree_root { + struct latch_tree_root root; + unsigned long addr_min; + unsigned long addr_max; +}; + +extern struct mod_tree_root mod_tree; + +void mod_tree_insert(struct module *mod); +void mod_tree_remove_init(struct module *mod); +void mod_tree_remove(struct module *mod); +struct module *mod_find(unsigned long addr); +#else /* !CONFIG_MODULES_TREE_LOOKUP */ + +static inline void mod_tree_insert(struct module *mod) { } +static inline void mod_tree_remove_init(struct module *mod) { } +static inline void mod_tree_remove(struct module *mod) { } +static inline struct module *mod_find(unsigned long addr) +{ + struct module *mod; + + list_for_each_entry_rcu(mod, &modules, list, + lockdep_is_held(&module_mutex)) { + if (within_module(addr, mod)) + return mod; + } + + return NULL; +} +#endif /* CONFIG_MODULES_TREE_LOOKUP */ diff --git a/kernel/module/main.c b/kernel/module/main.c index 3596ebf3a6c3..76b53880ad91 100644 --- a/kernel/module/main.c +++ b/kernel/module/main.c @@ -90,138 +90,16 @@ static DECLARE_WORK(init_free_wq, do_free_init); static LLIST_HEAD(init_free_list); #ifdef CONFIG_MODULES_TREE_LOOKUP - -/* - * Use a latched RB-tree for __module_address(); this allows us to use - * RCU-sched lookups of the address from any context. - * - * This is conditional on PERF_EVENTS || TRACING because those can really hit - * __module_address() hard by doing a lot of stack unwinding; potentially from - * NMI context. - */ - -static __always_inline unsigned long __mod_tree_val(struct latch_tree_node *n) -{ - struct module_layout *layout = container_of(n, struct module_layout, mtn.node); - - return (unsigned long)layout->base; -} - -static __always_inline unsigned long __mod_tree_size(struct latch_tree_node *n) -{ - struct module_layout *layout = container_of(n, struct module_layout, mtn.node); - - return (unsigned long)layout->size; -} - -static __always_inline bool -mod_tree_less(struct latch_tree_node *a, struct latch_tree_node *b) -{ - return __mod_tree_val(a) < __mod_tree_val(b); -} - -static __always_inline int -mod_tree_comp(void *key, struct latch_tree_node *n) -{ - unsigned long val = (unsigned long)key; - unsigned long start, end; - - start = __mod_tree_val(n); - if (val < start) - return -1; - - end = start + __mod_tree_size(n); - if (val >= end) - return 1; - - return 0; -} - -static const struct latch_tree_ops mod_tree_ops = { - .less = mod_tree_less, - .comp = mod_tree_comp, -}; - -static struct mod_tree_root { - struct latch_tree_root root; - unsigned long addr_min; - unsigned long addr_max; -} mod_tree __cacheline_aligned = { +struct mod_tree_root mod_tree __cacheline_aligned = { .addr_min = -1UL, }; #define module_addr_min mod_tree.addr_min #define module_addr_max mod_tree.addr_max -static noinline void __mod_tree_insert(struct mod_tree_node *node) -{ - latch_tree_insert(&node->node, &mod_tree.root, &mod_tree_ops); -} - -static void __mod_tree_remove(struct mod_tree_node *node) -{ - latch_tree_erase(&node->node, &mod_tree.root, &mod_tree_ops); -} - -/* - * These modifications: insert, remove_init and remove; are serialized by the - * module_mutex. - */ -static void mod_tree_insert(struct module *mod) -{ - mod->core_layout.mtn.mod = mod; - mod->init_layout.mtn.mod = mod; - - __mod_tree_insert(&mod->core_layout.mtn); - if (mod->init_layout.size) - __mod_tree_insert(&mod->init_layout.mtn); -} - -static void mod_tree_remove_init(struct module *mod) -{ - if (mod->init_layout.size) - __mod_tree_remove(&mod->init_layout.mtn); -} - -static void mod_tree_remove(struct module *mod) -{ - __mod_tree_remove(&mod->core_layout.mtn); - mod_tree_remove_init(mod); -} - -static struct module *mod_find(unsigned long addr) -{ - struct latch_tree_node *ltn; - - ltn = latch_tree_find((void *)addr, &mod_tree.root, &mod_tree_ops); - if (!ltn) - return NULL; - - return container_of(ltn, struct mod_tree_node, node)->mod; -} - -#else /* MODULES_TREE_LOOKUP */ - -static unsigned long module_addr_min = -1UL, module_addr_max = 0; - -static void mod_tree_insert(struct module *mod) { } -static void mod_tree_remove_init(struct module *mod) { } -static void mod_tree_remove(struct module *mod) { } - -static struct module *mod_find(unsigned long addr) -{ - struct module *mod; - - list_for_each_entry_rcu(mod, &modules, list, - lockdep_is_held(&module_mutex)) { - if (within_module(addr, mod)) - return mod; - } - - return NULL; -} - -#endif /* MODULES_TREE_LOOKUP */ +#else /* !CONFIG_MODULES_TREE_LOOKUP */ +static unsigned long module_addr_min = -1UL, module_addr_max; +#endif /* CONFIG_MODULES_TREE_LOOKUP */ /* * Bounds of module text, for speeding up __module_address. diff --git a/kernel/module/tree_lookup.c b/kernel/module/tree_lookup.c new file mode 100644 index 000000000000..0bc4ec3b22ce --- /dev/null +++ b/kernel/module/tree_lookup.c @@ -0,0 +1,109 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Modules tree lookup + * + * Copyright (C) 2015 Peter Zijlstra + * Copyright (C) 2015 Rusty Russell + */ + +#include +#include +#include "internal.h" + +/* + * Use a latched RB-tree for __module_address(); this allows us to use + * RCU-sched lookups of the address from any context. + * + * This is conditional on PERF_EVENTS || TRACING because those can really hit + * __module_address() hard by doing a lot of stack unwinding; potentially from + * NMI context. + */ + +static __always_inline unsigned long __mod_tree_val(struct latch_tree_node *n) +{ + struct module_layout *layout = container_of(n, struct module_layout, mtn.node); + + return (unsigned long)layout->base; +} + +static __always_inline unsigned long __mod_tree_size(struct latch_tree_node *n) +{ + struct module_layout *layout = container_of(n, struct module_layout, mtn.node); + + return (unsigned long)layout->size; +} + +static __always_inline bool +mod_tree_less(struct latch_tree_node *a, struct latch_tree_node *b) +{ + return __mod_tree_val(a) < __mod_tree_val(b); +} + +static __always_inline int +mod_tree_comp(void *key, struct latch_tree_node *n) +{ + unsigned long val = (unsigned long)key; + unsigned long start, end; + + start = __mod_tree_val(n); + if (val < start) + return -1; + + end = start + __mod_tree_size(n); + if (val >= end) + return 1; + + return 0; +} + +static const struct latch_tree_ops mod_tree_ops = { + .less = mod_tree_less, + .comp = mod_tree_comp, +}; + +static noinline void __mod_tree_insert(struct mod_tree_node *node) +{ + latch_tree_insert(&node->node, &mod_tree.root, &mod_tree_ops); +} + +static void __mod_tree_remove(struct mod_tree_node *node) +{ + latch_tree_erase(&node->node, &mod_tree.root, &mod_tree_ops); +} + +/* + * These modifications: insert, remove_init and remove; are serialized by the + * module_mutex. + */ +void mod_tree_insert(struct module *mod) +{ + mod->core_layout.mtn.mod = mod; + mod->init_layout.mtn.mod = mod; + + __mod_tree_insert(&mod->core_layout.mtn); + if (mod->init_layout.size) + __mod_tree_insert(&mod->init_layout.mtn); +} + +void mod_tree_remove_init(struct module *mod) +{ + if (mod->init_layout.size) + __mod_tree_remove(&mod->init_layout.mtn); +} + +void mod_tree_remove(struct module *mod) +{ + __mod_tree_remove(&mod->core_layout.mtn); + mod_tree_remove_init(mod); +} + +struct module *mod_find(unsigned long addr) +{ + struct latch_tree_node *ltn; + + ltn = latch_tree_find((void *)addr, &mod_tree.root, &mod_tree_ops); + if (!ltn) + return NULL; + + return container_of(ltn, struct mod_tree_node, node)->mod; +} From patchwork Thu Mar 10 10:24:05 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aaron Tomlin X-Patchwork-Id: 12776127 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 76C71C433FE for ; Thu, 10 Mar 2022 10:24:54 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S241212AbiCJKZv (ORCPT ); Thu, 10 Mar 2022 05:25:51 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43636 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241255AbiCJKZt (ORCPT ); Thu, 10 Mar 2022 05:25:49 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id E2AA1F8B9A for ; Thu, 10 Mar 2022 02:24:32 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1646907872; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Izr11YJzmvAe+LaxIWKRd054OpBnoHmXtcTT48M4YnE=; b=Lvt7Et3AfZwdDytU8PvbEWhjmiOyO9+/h2WNC5l+VmzqAcNyqx5Rb+DVX/qILshrtDY2ls 5chdZKRwxEr7UJzHyS5HqIexZnQlzZMzVPKqESHdZXm6H3dIcMYqQEQx0YYR9Sz2IjeJg7 fAjSOSRmI4Uv+2fYrn4pVX8jgLFaFsU= Received: from mail-wr1-f69.google.com (mail-wr1-f69.google.com [209.85.221.69]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-605-qNXewmsPMR2p7kZo01cF5Q-1; Thu, 10 Mar 2022 05:24:30 -0500 X-MC-Unique: qNXewmsPMR2p7kZo01cF5Q-1 Received: by mail-wr1-f69.google.com with SMTP id q14-20020adfea0e000000b002036c16c6daso1524391wrm.8 for ; Thu, 10 Mar 2022 02:24:30 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=Izr11YJzmvAe+LaxIWKRd054OpBnoHmXtcTT48M4YnE=; b=EqlTIoMjbmF6300YcO854P3VILgbQtm6jnwqEqgP4chkl5poo8tm2kTMeeBrjraNpW 4FKjsn+mA9qgsQkYaA4SHaURbkETeF1j6/Id6DltdPTyspAyJGycanmzHXQ25zUfk3y4 vZv8j3zTX5CO1jOkJINKiOBabUCVmXoJ8Z0ZniIDuOnu0gCV9ou9w6V0FB11NB3+wlRQ 8U+Jip+ZXiKECbIKG2zxlRO3umLeQrn6zXPnH64VCTqdFQ7aOTCrjbaFEWrmRfRccEPW OKv+xVeuxBhrS+brQRJnHVFYxo/kw1u6oAIFD+OC/TGI/12NVsPANzzqrQBJYMiobVZs EVEQ== X-Gm-Message-State: AOAM530FaC0oI5+2T1KCoSRyCYlNrQcCs9DAWHetv/prVVi3oAuskPLe mKlkHgfnZ3Cu09PaGPz5UKnLGlYs+RY+lzztSnwBYZPy0Y5eOgwdqQqK4cNwaoSKtPDSPm8vjU2 gfwkIoVajrx4z7xqtBYX3NxgA X-Received: by 2002:a05:6000:1449:b0:1fc:a870:4b85 with SMTP id v9-20020a056000144900b001fca8704b85mr2914675wrx.639.1646907869407; Thu, 10 Mar 2022 02:24:29 -0800 (PST) X-Google-Smtp-Source: ABdhPJwRBMIVVLJhX9R+E50iBRq2KGvpTkwmllsbpBSZqK2k7HsejlR5kRb6cTerEDWuAeF4NSDKeg== X-Received: by 2002:a05:6000:1449:b0:1fc:a870:4b85 with SMTP id v9-20020a056000144900b001fca8704b85mr2914648wrx.639.1646907869107; Thu, 10 Mar 2022 02:24:29 -0800 (PST) Received: from localhost (cpc111743-lutn13-2-0-cust979.9-3.cable.virginm.net. [82.17.115.212]) by smtp.gmail.com with ESMTPSA id bi9-20020a05600c3d8900b00389a623c80esm3715887wmb.1.2022.03.10.02.24.27 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 10 Mar 2022 02:24:28 -0800 (PST) From: Aaron Tomlin To: mcgrof@kernel.org, christophe.leroy@csgroup.eu Cc: cl@linux.com, mbenes@suse.cz, akpm@linux-foundation.org, jeyu@kernel.org, linux-kernel@vger.kernel.org, linux-modules@vger.kernel.org, void@manifault.com, atomlin@atomlin.com, allen.lkml@gmail.com, joe@perches.com, msuchanek@suse.de, oleksandr@natalenko.name, jason.wessel@windriver.com, pmladek@suse.com, daniel.thompson@linaro.org, hch@infradead.org Subject: [PATCH v11 06/14] module: Move strict rwx support to a separate file Date: Thu, 10 Mar 2022 10:24:05 +0000 Message-Id: <20220310102413.3438665-7-atomlin@redhat.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220310102413.3438665-1-atomlin@redhat.com> References: <20220310102413.3438665-1-atomlin@redhat.com> MIME-Version: 1.0 Precedence: bulk List-ID: No functional change. This patch migrates code that makes module text and rodata memory read-only and non-text memory non-executable from core module code into kernel/module/strict_rwx.c. Reviewed-by: Christophe Leroy Signed-off-by: Aaron Tomlin --- kernel/module/Makefile | 1 + kernel/module/internal.h | 32 ++++++++++++ kernel/module/main.c | 99 +------------------------------------- kernel/module/strict_rwx.c | 85 ++++++++++++++++++++++++++++++++ 4 files changed, 120 insertions(+), 97 deletions(-) create mode 100644 kernel/module/strict_rwx.c diff --git a/kernel/module/Makefile b/kernel/module/Makefile index 88774e386276..d313c8472cb3 100644 --- a/kernel/module/Makefile +++ b/kernel/module/Makefile @@ -12,3 +12,4 @@ obj-$(CONFIG_MODULE_DECOMPRESS) += decompress.o obj-$(CONFIG_MODULE_SIG) += signing.o obj-$(CONFIG_LIVEPATCH) += livepatch.o obj-$(CONFIG_MODULES_TREE_LOOKUP) += tree_lookup.o +obj-$(CONFIG_STRICT_MODULE_RWX) += strict_rwx.o diff --git a/kernel/module/internal.h b/kernel/module/internal.h index f1682e3677be..a6895bb5598a 100644 --- a/kernel/module/internal.h +++ b/kernel/module/internal.h @@ -20,6 +20,17 @@ /* Maximum number of characters written by module_flags() */ #define MODULE_FLAGS_BUF_SIZE (TAINT_FLAGS_COUNT + 4) +/* + * Modules' sections will be aligned on page boundaries + * to ensure complete separation of code and data, but + * only when CONFIG_ARCH_HAS_STRICT_MODULE_RWX=y + */ +#ifdef CONFIG_ARCH_HAS_STRICT_MODULE_RWX +# define debug_align(X) PAGE_ALIGN(X) +#else +# define debug_align(X) (X) +#endif + extern struct mutex module_mutex; extern struct list_head modules; @@ -126,3 +137,24 @@ static inline struct module *mod_find(unsigned long addr) return NULL; } #endif /* CONFIG_MODULES_TREE_LOOKUP */ + +#ifdef CONFIG_ARCH_HAS_STRICT_MODULE_RWX +void frob_text(const struct module_layout *layout, int (*set_memory)(unsigned long start, + int num_pages)); +#endif /* CONFIG_ARCH_HAS_STRICT_MODULE_RWX */ + +#ifdef CONFIG_STRICT_MODULE_RWX +void module_enable_ro(const struct module *mod, bool after_init); +void module_enable_nx(const struct module *mod); +int module_enforce_rwx_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs, + char *secstrings, struct module *mod); + +#else /* !CONFIG_STRICT_MODULE_RWX */ +static inline void module_enable_nx(const struct module *mod) { } +static inline void module_enable_ro(const struct module *mod, bool after_init) {} +static inline int module_enforce_rwx_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs, + char *secstrings, struct module *mod) +{ + return 0; +} +#endif /* CONFIG_STRICT_MODULE_RWX */ diff --git a/kernel/module/main.c b/kernel/module/main.c index 76b53880ad91..5cd63f14b1ef 100644 --- a/kernel/module/main.c +++ b/kernel/module/main.c @@ -63,17 +63,6 @@ #define CREATE_TRACE_POINTS #include -/* - * Modules' sections will be aligned on page boundaries - * to ensure complete separation of code and data, but - * only when CONFIG_ARCH_HAS_STRICT_MODULE_RWX=y - */ -#ifdef CONFIG_ARCH_HAS_STRICT_MODULE_RWX -# define debug_align(X) ALIGN(X, PAGE_SIZE) -#else -# define debug_align(X) (X) -#endif - /* * Mutex protects: * 1) List of modules (also safely readable with preempt_disable), @@ -1819,8 +1808,8 @@ static void mod_sysfs_teardown(struct module *mod) * whether we are strict. */ #ifdef CONFIG_ARCH_HAS_STRICT_MODULE_RWX -static void frob_text(const struct module_layout *layout, - int (*set_memory)(unsigned long start, int num_pages)) +void frob_text(const struct module_layout *layout, + int (*set_memory)(unsigned long start, int num_pages)) { BUG_ON((unsigned long)layout->base & (PAGE_SIZE-1)); BUG_ON((unsigned long)layout->text_size & (PAGE_SIZE-1)); @@ -1837,90 +1826,6 @@ static void module_enable_x(const struct module *mod) static void module_enable_x(const struct module *mod) { } #endif /* CONFIG_ARCH_HAS_STRICT_MODULE_RWX */ -#ifdef CONFIG_STRICT_MODULE_RWX -static void frob_rodata(const struct module_layout *layout, - int (*set_memory)(unsigned long start, int num_pages)) -{ - BUG_ON((unsigned long)layout->base & (PAGE_SIZE-1)); - BUG_ON((unsigned long)layout->text_size & (PAGE_SIZE-1)); - BUG_ON((unsigned long)layout->ro_size & (PAGE_SIZE-1)); - set_memory((unsigned long)layout->base + layout->text_size, - (layout->ro_size - layout->text_size) >> PAGE_SHIFT); -} - -static void frob_ro_after_init(const struct module_layout *layout, - int (*set_memory)(unsigned long start, int num_pages)) -{ - BUG_ON((unsigned long)layout->base & (PAGE_SIZE-1)); - BUG_ON((unsigned long)layout->ro_size & (PAGE_SIZE-1)); - BUG_ON((unsigned long)layout->ro_after_init_size & (PAGE_SIZE-1)); - set_memory((unsigned long)layout->base + layout->ro_size, - (layout->ro_after_init_size - layout->ro_size) >> PAGE_SHIFT); -} - -static void frob_writable_data(const struct module_layout *layout, - int (*set_memory)(unsigned long start, int num_pages)) -{ - BUG_ON((unsigned long)layout->base & (PAGE_SIZE-1)); - BUG_ON((unsigned long)layout->ro_after_init_size & (PAGE_SIZE-1)); - BUG_ON((unsigned long)layout->size & (PAGE_SIZE-1)); - set_memory((unsigned long)layout->base + layout->ro_after_init_size, - (layout->size - layout->ro_after_init_size) >> PAGE_SHIFT); -} - -static void module_enable_ro(const struct module *mod, bool after_init) -{ - if (!rodata_enabled) - return; - - set_vm_flush_reset_perms(mod->core_layout.base); - set_vm_flush_reset_perms(mod->init_layout.base); - frob_text(&mod->core_layout, set_memory_ro); - - frob_rodata(&mod->core_layout, set_memory_ro); - frob_text(&mod->init_layout, set_memory_ro); - frob_rodata(&mod->init_layout, set_memory_ro); - - if (after_init) - frob_ro_after_init(&mod->core_layout, set_memory_ro); -} - -static void module_enable_nx(const struct module *mod) -{ - frob_rodata(&mod->core_layout, set_memory_nx); - frob_ro_after_init(&mod->core_layout, set_memory_nx); - frob_writable_data(&mod->core_layout, set_memory_nx); - frob_rodata(&mod->init_layout, set_memory_nx); - frob_writable_data(&mod->init_layout, set_memory_nx); -} - -static int module_enforce_rwx_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs, - char *secstrings, struct module *mod) -{ - const unsigned long shf_wx = SHF_WRITE|SHF_EXECINSTR; - int i; - - for (i = 0; i < hdr->e_shnum; i++) { - if ((sechdrs[i].sh_flags & shf_wx) == shf_wx) { - pr_err("%s: section %s (index %d) has invalid WRITE|EXEC flags\n", - mod->name, secstrings + sechdrs[i].sh_name, i); - return -ENOEXEC; - } - } - - return 0; -} - -#else /* !CONFIG_STRICT_MODULE_RWX */ -static void module_enable_nx(const struct module *mod) { } -static void module_enable_ro(const struct module *mod, bool after_init) {} -static int module_enforce_rwx_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs, - char *secstrings, struct module *mod) -{ - return 0; -} -#endif /* CONFIG_STRICT_MODULE_RWX */ - void __weak module_memfree(void *module_region) { /* diff --git a/kernel/module/strict_rwx.c b/kernel/module/strict_rwx.c new file mode 100644 index 000000000000..7949dfd449c2 --- /dev/null +++ b/kernel/module/strict_rwx.c @@ -0,0 +1,85 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Module strict rwx + * + * Copyright (C) 2015 Rusty Russell + */ + +#include +#include +#include +#include +#include "internal.h" + +static void frob_rodata(const struct module_layout *layout, + int (*set_memory)(unsigned long start, int num_pages)) +{ + BUG_ON(!PAGE_ALIGNED(layout->base)); + BUG_ON(!PAGE_ALIGNED(layout->text_size)); + BUG_ON(!PAGE_ALIGNED(layout->ro_size)); + set_memory((unsigned long)layout->base + layout->text_size, + (layout->ro_size - layout->text_size) >> PAGE_SHIFT); +} + +static void frob_ro_after_init(const struct module_layout *layout, + int (*set_memory)(unsigned long start, int num_pages)) +{ + BUG_ON(!PAGE_ALIGNED(layout->base)); + BUG_ON(!PAGE_ALIGNED(layout->ro_size)); + BUG_ON(!PAGE_ALIGNED(layout->ro_after_init_size)); + set_memory((unsigned long)layout->base + layout->ro_size, + (layout->ro_after_init_size - layout->ro_size) >> PAGE_SHIFT); +} + +static void frob_writable_data(const struct module_layout *layout, + int (*set_memory)(unsigned long start, int num_pages)) +{ + BUG_ON(!PAGE_ALIGNED(layout->base)); + BUG_ON(!PAGE_ALIGNED(layout->ro_after_init_size)); + BUG_ON(!PAGE_ALIGNED(layout->size)); + set_memory((unsigned long)layout->base + layout->ro_after_init_size, + (layout->size - layout->ro_after_init_size) >> PAGE_SHIFT); +} + +void module_enable_ro(const struct module *mod, bool after_init) +{ + if (!rodata_enabled) + return; + + set_vm_flush_reset_perms(mod->core_layout.base); + set_vm_flush_reset_perms(mod->init_layout.base); + frob_text(&mod->core_layout, set_memory_ro); + + frob_rodata(&mod->core_layout, set_memory_ro); + frob_text(&mod->init_layout, set_memory_ro); + frob_rodata(&mod->init_layout, set_memory_ro); + + if (after_init) + frob_ro_after_init(&mod->core_layout, set_memory_ro); +} + +void module_enable_nx(const struct module *mod) +{ + frob_rodata(&mod->core_layout, set_memory_nx); + frob_ro_after_init(&mod->core_layout, set_memory_nx); + frob_writable_data(&mod->core_layout, set_memory_nx); + frob_rodata(&mod->init_layout, set_memory_nx); + frob_writable_data(&mod->init_layout, set_memory_nx); +} + +int module_enforce_rwx_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs, + char *secstrings, struct module *mod) +{ + const unsigned long shf_wx = SHF_WRITE | SHF_EXECINSTR; + int i; + + for (i = 0; i < hdr->e_shnum; i++) { + if ((sechdrs[i].sh_flags & shf_wx) == shf_wx) { + pr_err("%s: section %s (index %d) has invalid WRITE|EXEC flags\n", + mod->name, secstrings + sechdrs[i].sh_name, i); + return -ENOEXEC; + } + } + + return 0; +} From patchwork Thu Mar 10 10:24:06 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aaron Tomlin X-Patchwork-Id: 12776128 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 15DC4C433F5 for ; Thu, 10 Mar 2022 10:24:57 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S241295AbiCJKZz (ORCPT ); Thu, 10 Mar 2022 05:25:55 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44920 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241265AbiCJKZu (ORCPT ); Thu, 10 Mar 2022 05:25:50 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id C5F0013DE33 for ; Thu, 10 Mar 2022 02:24:34 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1646907874; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=apZpBB6s8ANx6PnqHZt1W7YrWPlcLByEn5Sm08WSqaI=; b=D1YnKMeDCHdNJvNbB3mjZVWaE0ZirifL+pAAEpT6T8UZDy/txso0JNPWbYENw6zIqBEjW/ co/+1tucV2uyeFvhE5dKWgMNbetpuUM85ru4dK+NJIO37VaoEAOMiQDHoTjvOFLvXP45jZ GJHVUvvNPTXx4AT3KFF6BFUsINyB8Ns= Received: from mail-wr1-f69.google.com (mail-wr1-f69.google.com [209.85.221.69]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-580-kD4WsQsRNGKSsKfbXBb8jw-1; Thu, 10 Mar 2022 05:24:32 -0500 X-MC-Unique: kD4WsQsRNGKSsKfbXBb8jw-1 Received: by mail-wr1-f69.google.com with SMTP id t15-20020adfdc0f000000b001ef93643476so1523829wri.2 for ; Thu, 10 Mar 2022 02:24:32 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=apZpBB6s8ANx6PnqHZt1W7YrWPlcLByEn5Sm08WSqaI=; b=bp5zh/qPUw9HLJx+cyU3WoX7lKxtIKDLUwBXRTTQH6cd1fjxZlEZ/B7kiS8V5JyDpz hbL7uaJetakFbRlbXLsBkIo/9EauUUM9zGCOcKqiBgYYRrWRWCzbPXff90Lfyvm5acV0 4Q2EQnOSOj35MFg3R/59sgrIG1yjzH6ystjkRm4OSuuWRnZJJinn8D93QntWcYpeg9T5 M+QyQfQdaaGKmI+YaDBr4EhizaD1OLdP3ILEkl8S2EHvxpylmFg7BF8uHTcRH8/IPwr0 uEdAJPEzjHLAlbavfShywG5GzzLs8P/zm+sR634rh1lKfg1CkQx4X5oqVqVrD981mlCM 7M6Q== X-Gm-Message-State: AOAM533PDD1F4Dar8xZJSq4mmIOVnv6ELEo/4SDo6mEyw+lJmu5jLY2J orGFqEVkFfWxz4/8ZkVCvXQ1oraRn+ltR06HCS4Rj4Bfi8DetK6gHeScVcCjQhbQFQSOhq4r1tW 1s6CMvfyTtWkfkHkIL4atsZ39 X-Received: by 2002:a7b:cb84:0:b0:382:a9b9:2339 with SMTP id m4-20020a7bcb84000000b00382a9b92339mr11088045wmi.91.1646907871472; Thu, 10 Mar 2022 02:24:31 -0800 (PST) X-Google-Smtp-Source: ABdhPJxhaMRCPpVayh/u4f8iNFSJgrcR3KpRDJZjOm+aVQWm+J1PL+QjqZAjszluPHiuxizdxF3eIg== X-Received: by 2002:a7b:cb84:0:b0:382:a9b9:2339 with SMTP id m4-20020a7bcb84000000b00382a9b92339mr11088014wmi.91.1646907871215; Thu, 10 Mar 2022 02:24:31 -0800 (PST) Received: from localhost (cpc111743-lutn13-2-0-cust979.9-3.cable.virginm.net. [82.17.115.212]) by smtp.gmail.com with ESMTPSA id l25-20020a1c7919000000b0038999b380e9sm4081999wme.38.2022.03.10.02.24.29 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 10 Mar 2022 02:24:30 -0800 (PST) From: Aaron Tomlin To: mcgrof@kernel.org, christophe.leroy@csgroup.eu Cc: cl@linux.com, mbenes@suse.cz, akpm@linux-foundation.org, jeyu@kernel.org, linux-kernel@vger.kernel.org, linux-modules@vger.kernel.org, void@manifault.com, atomlin@atomlin.com, allen.lkml@gmail.com, joe@perches.com, msuchanek@suse.de, oleksandr@natalenko.name, jason.wessel@windriver.com, pmladek@suse.com, daniel.thompson@linaro.org, hch@infradead.org Subject: [PATCH v11 07/14] module: Move extra signature support out of core code Date: Thu, 10 Mar 2022 10:24:06 +0000 Message-Id: <20220310102413.3438665-8-atomlin@redhat.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220310102413.3438665-1-atomlin@redhat.com> References: <20220310102413.3438665-1-atomlin@redhat.com> MIME-Version: 1.0 Precedence: bulk List-ID: No functional change. This patch migrates additional module signature check code from core module code into kernel/module/signing.c. Reviewed-by: Christophe Leroy Signed-off-by: Aaron Tomlin --- include/linux/module.h | 12 +++--- kernel/module/internal.h | 9 +++++ kernel/module/main.c | 87 ---------------------------------------- kernel/module/signing.c | 77 +++++++++++++++++++++++++++++++++++ 4 files changed, 93 insertions(+), 92 deletions(-) diff --git a/include/linux/module.h b/include/linux/module.h index 7ec9715de7dc..5e2059f3afc7 100644 --- a/include/linux/module.h +++ b/include/linux/module.h @@ -672,7 +672,6 @@ static inline bool is_livepatch_module(struct module *mod) #endif } -bool is_module_sig_enforced(void); void set_module_sig_enforced(void); #else /* !CONFIG_MODULES... */ @@ -799,10 +798,6 @@ static inline bool module_requested_async_probing(struct module *module) return false; } -static inline bool is_module_sig_enforced(void) -{ - return false; -} static inline void set_module_sig_enforced(void) { @@ -854,11 +849,18 @@ static inline bool retpoline_module_ok(bool has_retpoline) #endif #ifdef CONFIG_MODULE_SIG +bool is_module_sig_enforced(void); + static inline bool module_sig_ok(struct module *module) { return module->sig_ok; } #else /* !CONFIG_MODULE_SIG */ +static inline bool is_module_sig_enforced(void) +{ + return false; +} + static inline bool module_sig_ok(struct module *module) { return true; diff --git a/kernel/module/internal.h b/kernel/module/internal.h index a6895bb5598a..d6f646a5da41 100644 --- a/kernel/module/internal.h +++ b/kernel/module/internal.h @@ -158,3 +158,12 @@ static inline int module_enforce_rwx_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs, return 0; } #endif /* CONFIG_STRICT_MODULE_RWX */ + +#ifdef CONFIG_MODULE_SIG +int module_sig_check(struct load_info *info, int flags); +#else /* !CONFIG_MODULE_SIG */ +static inline int module_sig_check(struct load_info *info, int flags) +{ + return 0; +} +#endif /* !CONFIG_MODULE_SIG */ diff --git a/kernel/module/main.c b/kernel/module/main.c index 5cd63f14b1ef..c63e10c61694 100644 --- a/kernel/module/main.c +++ b/kernel/module/main.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include @@ -127,28 +126,6 @@ static void module_assert_mutex_or_preempt(void) #endif } -#ifdef CONFIG_MODULE_SIG -static bool sig_enforce = IS_ENABLED(CONFIG_MODULE_SIG_FORCE); -module_param(sig_enforce, bool_enable_only, 0644); - -void set_module_sig_enforced(void) -{ - sig_enforce = true; -} -#else -#define sig_enforce false -#endif - -/* - * Export sig_enforce kernel cmdline parameter to allow other subsystems rely - * on that instead of directly to CONFIG_MODULE_SIG_FORCE config. - */ -bool is_module_sig_enforced(void) -{ - return sig_enforce; -} -EXPORT_SYMBOL(is_module_sig_enforced); - /* Block module loading/unloading? */ int modules_disabled = 0; core_param(nomodule, modules_disabled, bint, 0); @@ -2569,70 +2546,6 @@ static inline void kmemleak_load_module(const struct module *mod, } #endif -#ifdef CONFIG_MODULE_SIG -static int module_sig_check(struct load_info *info, int flags) -{ - int err = -ENODATA; - const unsigned long markerlen = sizeof(MODULE_SIG_STRING) - 1; - const char *reason; - const void *mod = info->hdr; - bool mangled_module = flags & (MODULE_INIT_IGNORE_MODVERSIONS | - MODULE_INIT_IGNORE_VERMAGIC); - /* - * Do not allow mangled modules as a module with version information - * removed is no longer the module that was signed. - */ - if (!mangled_module && - info->len > markerlen && - memcmp(mod + info->len - markerlen, MODULE_SIG_STRING, markerlen) == 0) { - /* We truncate the module to discard the signature */ - info->len -= markerlen; - err = mod_verify_sig(mod, info); - if (!err) { - info->sig_ok = true; - return 0; - } - } - - /* - * We don't permit modules to be loaded into the trusted kernels - * without a valid signature on them, but if we're not enforcing, - * certain errors are non-fatal. - */ - switch (err) { - case -ENODATA: - reason = "unsigned module"; - break; - case -ENOPKG: - reason = "module with unsupported crypto"; - break; - case -ENOKEY: - reason = "module with unavailable key"; - break; - - default: - /* - * All other errors are fatal, including lack of memory, - * unparseable signatures, and signature check failures -- - * even if signatures aren't required. - */ - return err; - } - - if (is_module_sig_enforced()) { - pr_notice("Loading of %s is rejected\n", reason); - return -EKEYREJECTED; - } - - return security_locked_down(LOCKDOWN_MODULE_SIGNATURE); -} -#else /* !CONFIG_MODULE_SIG */ -static int module_sig_check(struct load_info *info, int flags) -{ - return 0; -} -#endif /* !CONFIG_MODULE_SIG */ - static int validate_section_offset(struct load_info *info, Elf_Shdr *shdr) { #if defined(CONFIG_64BIT) diff --git a/kernel/module/signing.c b/kernel/module/signing.c index 8aeb6d2ee94b..85c8999dfecf 100644 --- a/kernel/module/signing.c +++ b/kernel/module/signing.c @@ -11,9 +11,29 @@ #include #include #include +#include #include +#include #include "internal.h" +static bool sig_enforce = IS_ENABLED(CONFIG_MODULE_SIG_FORCE); +module_param(sig_enforce, bool_enable_only, 0644); + +/* + * Export sig_enforce kernel cmdline parameter to allow other subsystems rely + * on that instead of directly to CONFIG_MODULE_SIG_FORCE config. + */ +bool is_module_sig_enforced(void) +{ + return sig_enforce; +} +EXPORT_SYMBOL(is_module_sig_enforced); + +void set_module_sig_enforced(void) +{ + sig_enforce = true; +} + /* * Verify the signature on a module. */ @@ -43,3 +63,60 @@ int mod_verify_sig(const void *mod, struct load_info *info) VERIFYING_MODULE_SIGNATURE, NULL, NULL); } + +int module_sig_check(struct load_info *info, int flags) +{ + int err = -ENODATA; + const unsigned long markerlen = sizeof(MODULE_SIG_STRING) - 1; + const char *reason; + const void *mod = info->hdr; + bool mangled_module = flags & (MODULE_INIT_IGNORE_MODVERSIONS | + MODULE_INIT_IGNORE_VERMAGIC); + /* + * Do not allow mangled modules as a module with version information + * removed is no longer the module that was signed. + */ + if (!mangled_module && + info->len > markerlen && + memcmp(mod + info->len - markerlen, MODULE_SIG_STRING, markerlen) == 0) { + /* We truncate the module to discard the signature */ + info->len -= markerlen; + err = mod_verify_sig(mod, info); + if (!err) { + info->sig_ok = true; + return 0; + } + } + + /* + * We don't permit modules to be loaded into the trusted kernels + * without a valid signature on them, but if we're not enforcing, + * certain errors are non-fatal. + */ + switch (err) { + case -ENODATA: + reason = "unsigned module"; + break; + case -ENOPKG: + reason = "module with unsupported crypto"; + break; + case -ENOKEY: + reason = "module with unavailable key"; + break; + + default: + /* + * All other errors are fatal, including lack of memory, + * unparseable signatures, and signature check failures -- + * even if signatures aren't required. + */ + return err; + } + + if (is_module_sig_enforced()) { + pr_notice("Loading of %s is rejected\n", reason); + return -EKEYREJECTED; + } + + return security_locked_down(LOCKDOWN_MODULE_SIGNATURE); +} From patchwork Thu Mar 10 10:24:07 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aaron Tomlin X-Patchwork-Id: 12776129 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id C7DC8C433F5 for ; Thu, 10 Mar 2022 10:25:01 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S241261AbiCJK0A (ORCPT ); Thu, 10 Mar 2022 05:26:00 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44070 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241272AbiCJKZu (ORCPT ); Thu, 10 Mar 2022 05:25:50 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 774A313EFAE for ; Thu, 10 Mar 2022 02:24:37 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1646907876; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=EwM5m/UKCLcQUodhjTTwfqA0OAG1WbMnIR0FKcI9qsQ=; b=ZkZch8Dd6jn5g+SaDUYd2hB8rrj/dVdQh7FpjJf8FA31cvSRoKVVwWFkEME4NI4f+flV05 MWUv5eM11aClVWFxM+5RTs5J+QJbN+jafC5kCG4rhbneW4vwLEUBz8DcYC0UOsNDzKqzp6 tada2hMUyGf7fyBGc041lVwX0UlYPgQ= Received: from mail-wm1-f72.google.com (mail-wm1-f72.google.com [209.85.128.72]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-604-1-Y-quTcNbeBDX9hurjf5A-1; Thu, 10 Mar 2022 05:24:35 -0500 X-MC-Unique: 1-Y-quTcNbeBDX9hurjf5A-1 Received: by mail-wm1-f72.google.com with SMTP id v67-20020a1cac46000000b00383e71bb26fso1959195wme.1 for ; Thu, 10 Mar 2022 02:24:35 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=EwM5m/UKCLcQUodhjTTwfqA0OAG1WbMnIR0FKcI9qsQ=; b=tae0Ln7BhuFQ3PCciu1U5yCiMmLJl0KU/4s7rWVVJCjJdnfMaZZB/jzVgahca2s7PF 6Glki54HhcXAPmwRfWubXVytE58/vUuYZAeO7g8CRy54BMvK7JNPSo3eZIeoDhIfaPnZ 8qx6Njjv3Fg26nmVh/fRGyLZfL4/CaCk0JCRTdBrKbfrnK5/ACKI5gvg1EhSdOqb4A59 iZXqHSLSL4PI+4q5a+PrBWugqE8IE3ENyRSa5bPoasyo3GVqz01OJKFYrAyYyaSr9/F4 Jur4uY1F3hT7+CLuzk4WKNYYjdwe9lDDd0smTB8vAWx6/XY73RYqXsdDC6MHnWZGa9qb lO/A== X-Gm-Message-State: AOAM531Xvds3+n8o1A9VPdWZyZDmvWMQ8ds9oytpgyGzRFvPn5Wcu2+W nGO+JQGyAON3v21elADOS03zhd1khpPNNT9dz540uCcvp9IJzyVfOjWxvw9jjTAXjnzWDhSnmvi Zhm2VQ4GvDkd3QRxxJH7aBaHw X-Received: by 2002:a05:600c:4142:b0:389:a592:10ce with SMTP id h2-20020a05600c414200b00389a59210cemr3042010wmm.148.1646907873691; Thu, 10 Mar 2022 02:24:33 -0800 (PST) X-Google-Smtp-Source: ABdhPJzdjUYdxCgT86QW3Z7nzJHOo6s64FYEo4BqKE9S3089+9oXnTJ10VUebqj6CUYdWAtQScU9MA== X-Received: by 2002:a05:600c:4142:b0:389:a592:10ce with SMTP id h2-20020a05600c414200b00389a59210cemr3041986wmm.148.1646907873507; Thu, 10 Mar 2022 02:24:33 -0800 (PST) Received: from localhost (cpc111743-lutn13-2-0-cust979.9-3.cable.virginm.net. [82.17.115.212]) by smtp.gmail.com with ESMTPSA id h12-20020a5d548c000000b001f1f99e7792sm3696411wrv.111.2022.03.10.02.24.31 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 10 Mar 2022 02:24:32 -0800 (PST) From: Aaron Tomlin To: mcgrof@kernel.org, christophe.leroy@csgroup.eu Cc: cl@linux.com, mbenes@suse.cz, akpm@linux-foundation.org, jeyu@kernel.org, linux-kernel@vger.kernel.org, linux-modules@vger.kernel.org, void@manifault.com, atomlin@atomlin.com, allen.lkml@gmail.com, joe@perches.com, msuchanek@suse.de, oleksandr@natalenko.name, jason.wessel@windriver.com, pmladek@suse.com, daniel.thompson@linaro.org, hch@infradead.org Subject: [PATCH v11 08/14] module: Move kmemleak support to a separate file Date: Thu, 10 Mar 2022 10:24:07 +0000 Message-Id: <20220310102413.3438665-9-atomlin@redhat.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220310102413.3438665-1-atomlin@redhat.com> References: <20220310102413.3438665-1-atomlin@redhat.com> MIME-Version: 1.0 Precedence: bulk List-ID: No functional change. This patch migrates kmemleak code out of core module code into kernel/module/debug_kmemleak.c Reviewed-by: Christophe Leroy Signed-off-by: Aaron Tomlin --- kernel/module/Makefile | 1 + kernel/module/debug_kmemleak.c | 30 ++++++++++++++++++++++++++++++ kernel/module/internal.h | 7 +++++++ kernel/module/main.c | 27 --------------------------- 4 files changed, 38 insertions(+), 27 deletions(-) create mode 100644 kernel/module/debug_kmemleak.c diff --git a/kernel/module/Makefile b/kernel/module/Makefile index d313c8472cb3..12388627725c 100644 --- a/kernel/module/Makefile +++ b/kernel/module/Makefile @@ -13,3 +13,4 @@ obj-$(CONFIG_MODULE_SIG) += signing.o obj-$(CONFIG_LIVEPATCH) += livepatch.o obj-$(CONFIG_MODULES_TREE_LOOKUP) += tree_lookup.o obj-$(CONFIG_STRICT_MODULE_RWX) += strict_rwx.o +obj-$(CONFIG_DEBUG_KMEMLEAK) += debug_kmemleak.o diff --git a/kernel/module/debug_kmemleak.c b/kernel/module/debug_kmemleak.c new file mode 100644 index 000000000000..12a569d361e8 --- /dev/null +++ b/kernel/module/debug_kmemleak.c @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Module kmemleak support + * + * Copyright (C) 2009 Catalin Marinas + */ + +#include +#include +#include "internal.h" + +void kmemleak_load_module(const struct module *mod, + const struct load_info *info) +{ + unsigned int i; + + /* only scan the sections containing data */ + kmemleak_scan_area(mod, sizeof(struct module), GFP_KERNEL); + + for (i = 1; i < info->hdr->e_shnum; i++) { + /* Scan all writable sections that's not executable */ + if (!(info->sechdrs[i].sh_flags & SHF_ALLOC) || + !(info->sechdrs[i].sh_flags & SHF_WRITE) || + (info->sechdrs[i].sh_flags & SHF_EXECINSTR)) + continue; + + kmemleak_scan_area((void *)info->sechdrs[i].sh_addr, + info->sechdrs[i].sh_size, GFP_KERNEL); + } +} diff --git a/kernel/module/internal.h b/kernel/module/internal.h index d6f646a5da41..b0c360839f63 100644 --- a/kernel/module/internal.h +++ b/kernel/module/internal.h @@ -167,3 +167,10 @@ static inline int module_sig_check(struct load_info *info, int flags) return 0; } #endif /* !CONFIG_MODULE_SIG */ + +#ifdef CONFIG_DEBUG_KMEMLEAK +void kmemleak_load_module(const struct module *mod, const struct load_info *info); +#else /* !CONFIG_DEBUG_KMEMLEAK */ +static inline void kmemleak_load_module(const struct module *mod, + const struct load_info *info) { } +#endif /* CONFIG_DEBUG_KMEMLEAK */ diff --git a/kernel/module/main.c b/kernel/module/main.c index c63e10c61694..7dd283959c5c 100644 --- a/kernel/module/main.c +++ b/kernel/module/main.c @@ -2519,33 +2519,6 @@ bool __weak module_exit_section(const char *name) return strstarts(name, ".exit"); } -#ifdef CONFIG_DEBUG_KMEMLEAK -static void kmemleak_load_module(const struct module *mod, - const struct load_info *info) -{ - unsigned int i; - - /* only scan the sections containing data */ - kmemleak_scan_area(mod, sizeof(struct module), GFP_KERNEL); - - for (i = 1; i < info->hdr->e_shnum; i++) { - /* Scan all writable sections that's not executable */ - if (!(info->sechdrs[i].sh_flags & SHF_ALLOC) || - !(info->sechdrs[i].sh_flags & SHF_WRITE) || - (info->sechdrs[i].sh_flags & SHF_EXECINSTR)) - continue; - - kmemleak_scan_area((void *)info->sechdrs[i].sh_addr, - info->sechdrs[i].sh_size, GFP_KERNEL); - } -} -#else -static inline void kmemleak_load_module(const struct module *mod, - const struct load_info *info) -{ -} -#endif - static int validate_section_offset(struct load_info *info, Elf_Shdr *shdr) { #if defined(CONFIG_64BIT) From patchwork Thu Mar 10 10:24:08 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aaron Tomlin X-Patchwork-Id: 12776130 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5072AC433F5 for ; Thu, 10 Mar 2022 10:25:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S241285AbiCJK0D (ORCPT ); Thu, 10 Mar 2022 05:26:03 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44962 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241264AbiCJKZy (ORCPT ); Thu, 10 Mar 2022 05:25:54 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id D6E4213FACF for ; Thu, 10 Mar 2022 02:24:39 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1646907879; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=cZKsF3V2xKms5rUDdmplrUAEBHoN7M+YOs4uSrMcUTI=; b=Ggk45t4rlh9Wi7fSMubiR67kiRWX8Ro2ZwA5tlEHMi+xjfM3STz2NPpmVKx2iky4ES+cMr mgMjAxPxEhC84z8RgahT2F4NYWQWPZyhlF5WZ7uX6zXXoyJTK5XRB9qFwj94FMQo4hb1Cu SogSlpDA3heNffGw3/tQdwkQ2IPFplg= Received: from mail-wm1-f70.google.com (mail-wm1-f70.google.com [209.85.128.70]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-121-M4_IacqkOoS96EsuagMbrw-1; Thu, 10 Mar 2022 05:24:37 -0500 X-MC-Unique: M4_IacqkOoS96EsuagMbrw-1 Received: by mail-wm1-f70.google.com with SMTP id v67-20020a1cac46000000b00383e71bb26fso1959245wme.1 for ; Thu, 10 Mar 2022 02:24:37 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=cZKsF3V2xKms5rUDdmplrUAEBHoN7M+YOs4uSrMcUTI=; b=hs1G4zA0lWSxlqr8jW3JUNcDkvgXKOF5p+6fGsMAQOoXIwMv9y+nXsq9tB/hHZkQr6 aVGMVUJwSld+/G1P83xUiVMtdZdgXqbe1t2NDJp+QxZ/oUpn7IdsFJMudGGi2DXCU0r2 IVGKK8O3dFNZGekwqNE9+CR/02AbjXPslIqPQ8vETVIhbrHZJial4kklUMEJBsa33ZJZ nGjCgMQRugasUtQu+krwGo0Xa8ylZuRUqJfQ4WQ3O06uyU+9HBwxo3cAUzE7CcbSYgOc KnFcxE81YsJdQNfH7ihIBW/y0Tbm4H/yQh07kGmridOvAqiZeL54amkT7Yl6FlzTk2gN TFZA== X-Gm-Message-State: AOAM530/g7UqZ3LcuTsUCSkPg9DiauZzXZOggP5jJ14JZSMRtm/Q78XB 73RQ6nFNLCYT1qXMiUJblP584t6+MvXlJ1ojEovE/FuP/xBc5tPr5hM18EY54mce3nR/hwJaB0f 4atF+bDpTLslHgMLB29d2sOMb X-Received: by 2002:a05:6000:11c8:b0:1f0:d64:fb0c with SMTP id i8-20020a05600011c800b001f00d64fb0cmr3037764wrx.279.1646907875948; Thu, 10 Mar 2022 02:24:35 -0800 (PST) X-Google-Smtp-Source: ABdhPJx33vrGgk2jBqaBLMuFbLfwrH8kR8jGJc5vI8A91vI/7JGaKC6erWcFz19V+CbNLDI7MMMr7w== X-Received: by 2002:a05:6000:11c8:b0:1f0:d64:fb0c with SMTP id i8-20020a05600011c800b001f00d64fb0cmr3037740wrx.279.1646907875497; Thu, 10 Mar 2022 02:24:35 -0800 (PST) Received: from localhost (cpc111743-lutn13-2-0-cust979.9-3.cable.virginm.net. [82.17.115.212]) by smtp.gmail.com with ESMTPSA id k12-20020adfb34c000000b001f1e13df54dsm3798853wrd.89.2022.03.10.02.24.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 10 Mar 2022 02:24:34 -0800 (PST) From: Aaron Tomlin To: mcgrof@kernel.org, christophe.leroy@csgroup.eu Cc: cl@linux.com, mbenes@suse.cz, akpm@linux-foundation.org, jeyu@kernel.org, linux-kernel@vger.kernel.org, linux-modules@vger.kernel.org, void@manifault.com, atomlin@atomlin.com, allen.lkml@gmail.com, joe@perches.com, msuchanek@suse.de, oleksandr@natalenko.name, jason.wessel@windriver.com, pmladek@suse.com, daniel.thompson@linaro.org, hch@infradead.org Subject: [PATCH v11 09/14] module: Move kallsyms support into a separate file Date: Thu, 10 Mar 2022 10:24:08 +0000 Message-Id: <20220310102413.3438665-10-atomlin@redhat.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220310102413.3438665-1-atomlin@redhat.com> References: <20220310102413.3438665-1-atomlin@redhat.com> MIME-Version: 1.0 Precedence: bulk List-ID: No functional change. This patch migrates kallsyms code out of core module code kernel/module/kallsyms.c Signed-off-by: Aaron Tomlin Reported-by: Chuck Lever III --- kernel/module/Makefile | 1 + kernel/module/internal.h | 29 +++ kernel/module/kallsyms.c | 502 ++++++++++++++++++++++++++++++++++++ kernel/module/main.c | 531 +-------------------------------------- 4 files changed, 538 insertions(+), 525 deletions(-) create mode 100644 kernel/module/kallsyms.c diff --git a/kernel/module/Makefile b/kernel/module/Makefile index 12388627725c..9901bed3ab5b 100644 --- a/kernel/module/Makefile +++ b/kernel/module/Makefile @@ -14,3 +14,4 @@ obj-$(CONFIG_LIVEPATCH) += livepatch.o obj-$(CONFIG_MODULES_TREE_LOOKUP) += tree_lookup.o obj-$(CONFIG_STRICT_MODULE_RWX) += strict_rwx.o obj-$(CONFIG_DEBUG_KMEMLEAK) += debug_kmemleak.o +obj-$(CONFIG_KALLSYMS) += kallsyms.o diff --git a/kernel/module/internal.h b/kernel/module/internal.h index b0c360839f63..44ca05b9eb8f 100644 --- a/kernel/module/internal.h +++ b/kernel/module/internal.h @@ -68,6 +68,19 @@ struct load_info { }; int mod_verify_sig(const void *mod, struct load_info *info); +struct module *find_module_all(const char *name, size_t len, bool even_unformed); +int cmp_name(const void *name, const void *sym); +long module_get_offset(struct module *mod, unsigned int *size, Elf_Shdr *sechdr, + unsigned int section); + +static inline unsigned long kernel_symbol_value(const struct kernel_symbol *sym) +{ +#ifdef CONFIG_HAVE_ARCH_PREL32_RELOCATIONS + return (unsigned long)offset_to_ptr(&sym->value_offset); +#else + return sym->value; +#endif +} #ifdef CONFIG_LIVEPATCH int copy_module_elf(struct module *mod, struct load_info *info); @@ -174,3 +187,19 @@ void kmemleak_load_module(const struct module *mod, const struct load_info *info static inline void kmemleak_load_module(const struct module *mod, const struct load_info *info) { } #endif /* CONFIG_DEBUG_KMEMLEAK */ + +#ifdef CONFIG_KALLSYMS +void init_build_id(struct module *mod, const struct load_info *info); +void layout_symtab(struct module *mod, struct load_info *info); +void add_kallsyms(struct module *mod, const struct load_info *info); +unsigned long find_kallsyms_symbol_value(struct module *mod, const char *name); + +static inline bool sect_empty(const Elf_Shdr *sect) +{ + return !(sect->sh_flags & SHF_ALLOC) || sect->sh_size == 0; +} +#else /* !CONFIG_KALLSYMS */ +static inline void init_build_id(struct module *mod, const struct load_info *info) { } +static inline void layout_symtab(struct module *mod, struct load_info *info) { } +static inline void add_kallsyms(struct module *mod, const struct load_info *info) { } +#endif /* CONFIG_KALLSYMS */ diff --git a/kernel/module/kallsyms.c b/kernel/module/kallsyms.c new file mode 100644 index 000000000000..1b0780e20aab --- /dev/null +++ b/kernel/module/kallsyms.c @@ -0,0 +1,502 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Module kallsyms support + * + * Copyright (C) 2010 Rusty Russell + */ + +#include +#include +#include +#include +#include "internal.h" + +/* Lookup exported symbol in given range of kernel_symbols */ +static const struct kernel_symbol *lookup_exported_symbol(const char *name, + const struct kernel_symbol *start, + const struct kernel_symbol *stop) +{ + return bsearch(name, start, stop - start, + sizeof(struct kernel_symbol), cmp_name); +} + +static int is_exported(const char *name, unsigned long value, + const struct module *mod) +{ + const struct kernel_symbol *ks; + + if (!mod) + ks = lookup_exported_symbol(name, __start___ksymtab, __stop___ksymtab); + else + ks = lookup_exported_symbol(name, mod->syms, mod->syms + mod->num_syms); + + return ks && kernel_symbol_value(ks) == value; +} + +/* As per nm */ +static char elf_type(const Elf_Sym *sym, const struct load_info *info) +{ + const Elf_Shdr *sechdrs = info->sechdrs; + + if (ELF_ST_BIND(sym->st_info) == STB_WEAK) { + if (ELF_ST_TYPE(sym->st_info) == STT_OBJECT) + return 'v'; + else + return 'w'; + } + if (sym->st_shndx == SHN_UNDEF) + return 'U'; + if (sym->st_shndx == SHN_ABS || sym->st_shndx == info->index.pcpu) + return 'a'; + if (sym->st_shndx >= SHN_LORESERVE) + return '?'; + if (sechdrs[sym->st_shndx].sh_flags & SHF_EXECINSTR) + return 't'; + if (sechdrs[sym->st_shndx].sh_flags & SHF_ALLOC && + sechdrs[sym->st_shndx].sh_type != SHT_NOBITS) { + if (!(sechdrs[sym->st_shndx].sh_flags & SHF_WRITE)) + return 'r'; + else if (sechdrs[sym->st_shndx].sh_flags & ARCH_SHF_SMALL) + return 'g'; + else + return 'd'; + } + if (sechdrs[sym->st_shndx].sh_type == SHT_NOBITS) { + if (sechdrs[sym->st_shndx].sh_flags & ARCH_SHF_SMALL) + return 's'; + else + return 'b'; + } + if (strstarts(info->secstrings + sechdrs[sym->st_shndx].sh_name, + ".debug")) { + return 'n'; + } + return '?'; +} + +static bool is_core_symbol(const Elf_Sym *src, const Elf_Shdr *sechdrs, + unsigned int shnum, unsigned int pcpundx) +{ + const Elf_Shdr *sec; + + if (src->st_shndx == SHN_UNDEF || + src->st_shndx >= shnum || + !src->st_name) + return false; + +#ifdef CONFIG_KALLSYMS_ALL + if (src->st_shndx == pcpundx) + return true; +#endif + + sec = sechdrs + src->st_shndx; + if (!(sec->sh_flags & SHF_ALLOC) +#ifndef CONFIG_KALLSYMS_ALL + || !(sec->sh_flags & SHF_EXECINSTR) +#endif + || (sec->sh_entsize & INIT_OFFSET_MASK)) + return false; + + return true; +} + +/* + * We only allocate and copy the strings needed by the parts of symtab + * we keep. This is simple, but has the effect of making multiple + * copies of duplicates. We could be more sophisticated, see + * linux-kernel thread starting with + * <73defb5e4bca04a6431392cc341112b1@localhost>. + */ +void layout_symtab(struct module *mod, struct load_info *info) +{ + Elf_Shdr *symsect = info->sechdrs + info->index.sym; + Elf_Shdr *strsect = info->sechdrs + info->index.str; + const Elf_Sym *src; + unsigned int i, nsrc, ndst, strtab_size = 0; + + /* Put symbol section at end of init part of module. */ + symsect->sh_flags |= SHF_ALLOC; + symsect->sh_entsize = module_get_offset(mod, &mod->init_layout.size, symsect, + info->index.sym) | INIT_OFFSET_MASK; + pr_debug("\t%s\n", info->secstrings + symsect->sh_name); + + src = (void *)info->hdr + symsect->sh_offset; + nsrc = symsect->sh_size / sizeof(*src); + + /* Compute total space required for the core symbols' strtab. */ + for (ndst = i = 0; i < nsrc; i++) { + if (i == 0 || is_livepatch_module(mod) || + is_core_symbol(src + i, info->sechdrs, info->hdr->e_shnum, + info->index.pcpu)) { + strtab_size += strlen(&info->strtab[src[i].st_name]) + 1; + ndst++; + } + } + + /* Append room for core symbols at end of core part. */ + info->symoffs = ALIGN(mod->core_layout.size, symsect->sh_addralign ?: 1); + info->stroffs = mod->core_layout.size = info->symoffs + ndst * sizeof(Elf_Sym); + mod->core_layout.size += strtab_size; + info->core_typeoffs = mod->core_layout.size; + mod->core_layout.size += ndst * sizeof(char); + mod->core_layout.size = debug_align(mod->core_layout.size); + + /* Put string table section at end of init part of module. */ + strsect->sh_flags |= SHF_ALLOC; + strsect->sh_entsize = module_get_offset(mod, &mod->init_layout.size, strsect, + info->index.str) | INIT_OFFSET_MASK; + pr_debug("\t%s\n", info->secstrings + strsect->sh_name); + + /* We'll tack temporary mod_kallsyms on the end. */ + mod->init_layout.size = ALIGN(mod->init_layout.size, + __alignof__(struct mod_kallsyms)); + info->mod_kallsyms_init_off = mod->init_layout.size; + mod->init_layout.size += sizeof(struct mod_kallsyms); + info->init_typeoffs = mod->init_layout.size; + mod->init_layout.size += nsrc * sizeof(char); + mod->init_layout.size = debug_align(mod->init_layout.size); +} + +/* + * 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 + * core-only ones. + */ +void add_kallsyms(struct module *mod, const struct load_info *info) +{ + unsigned int i, ndst; + const Elf_Sym *src; + Elf_Sym *dst; + char *s; + Elf_Shdr *symsec = &info->sechdrs[info->index.sym]; + + /* Set up to point into init section. */ + mod->kallsyms = mod->init_layout.base + info->mod_kallsyms_init_off; + + /* The following is safe since this pointer cannot change */ + mod->kallsyms->symtab = (void *)symsec->sh_addr; + mod->kallsyms->num_symtab = symsec->sh_size / sizeof(Elf_Sym); + /* Make sure we get permanent strtab: don't use info->strtab. */ + mod->kallsyms->strtab = (void *)info->sechdrs[info->index.str].sh_addr; + mod->kallsyms->typetab = mod->init_layout.base + info->init_typeoffs; + + /* + * Now populate the cut down core kallsyms for after init + * and set types up while we still have access to sections. + */ + mod->core_kallsyms.symtab = dst = mod->core_layout.base + info->symoffs; + mod->core_kallsyms.strtab = s = mod->core_layout.base + info->stroffs; + mod->core_kallsyms.typetab = mod->core_layout.base + info->core_typeoffs; + src = mod->kallsyms->symtab; + for (ndst = i = 0; i < mod->kallsyms->num_symtab; i++) { + mod->kallsyms->typetab[i] = elf_type(src + i, info); + if (i == 0 || is_livepatch_module(mod) || + is_core_symbol(src + i, info->sechdrs, info->hdr->e_shnum, + info->index.pcpu)) { + mod->core_kallsyms.typetab[ndst] = + mod->kallsyms->typetab[i]; + dst[ndst] = src[i]; + dst[ndst++].st_name = s - mod->core_kallsyms.strtab; + s += strscpy(s, &mod->kallsyms->strtab[src[i].st_name], + KSYM_NAME_LEN) + 1; + } + } + mod->core_kallsyms.num_symtab = ndst; +} + +#if IS_ENABLED(CONFIG_STACKTRACE_BUILD_ID) +void init_build_id(struct module *mod, const struct load_info *info) +{ + const Elf_Shdr *sechdr; + unsigned int i; + + for (i = 0; i < info->hdr->e_shnum; i++) { + sechdr = &info->sechdrs[i]; + if (!sect_empty(sechdr) && sechdr->sh_type == SHT_NOTE && + !build_id_parse_buf((void *)sechdr->sh_addr, mod->build_id, + sechdr->sh_size)) + break; + } +} +#else +void init_build_id(struct module *mod, const struct load_info *info) +{ +} +#endif + +/* + * This ignores the intensely annoying "mapping symbols" found + * in ARM ELF files: $a, $t and $d. + */ +static inline int is_arm_mapping_symbol(const char *str) +{ + if (str[0] == '.' && str[1] == 'L') + return true; + return str[0] == '$' && strchr("axtd", str[1]) && + (str[2] == '\0' || str[2] == '.'); +} + +static const char *kallsyms_symbol_name(struct mod_kallsyms *kallsyms, unsigned int symnum) +{ + return kallsyms->strtab + kallsyms->symtab[symnum].st_name; +} + +/* + * Given a module and address, find the corresponding symbol and return its name + * while providing its size and offset if needed. + */ +static const char *find_kallsyms_symbol(struct module *mod, + unsigned long addr, + unsigned long *size, + unsigned long *offset) +{ + unsigned int i, best = 0; + unsigned long nextval, bestval; + struct mod_kallsyms *kallsyms = rcu_dereference_sched(mod->kallsyms); + + /* At worse, next value is at end of module */ + if (within_module_init(addr, mod)) + nextval = (unsigned long)mod->init_layout.base + mod->init_layout.text_size; + else + nextval = (unsigned long)mod->core_layout.base + mod->core_layout.text_size; + + bestval = kallsyms_symbol_value(&kallsyms->symtab[best]); + + /* + * Scan for closest preceding symbol, and next symbol. (ELF + * starts real symbols at 1). + */ + for (i = 1; i < kallsyms->num_symtab; i++) { + const Elf_Sym *sym = &kallsyms->symtab[i]; + unsigned long thisval = kallsyms_symbol_value(sym); + + if (sym->st_shndx == SHN_UNDEF) + continue; + + /* + * We ignore unnamed symbols: they're uninformative + * and inserted at a whim. + */ + if (*kallsyms_symbol_name(kallsyms, i) == '\0' || + is_arm_mapping_symbol(kallsyms_symbol_name(kallsyms, i))) + continue; + + if (thisval <= addr && thisval > bestval) { + best = i; + bestval = thisval; + } + if (thisval > addr && thisval < nextval) + nextval = thisval; + } + + if (!best) + return NULL; + + if (size) + *size = nextval - bestval; + if (offset) + *offset = addr - bestval; + + return kallsyms_symbol_name(kallsyms, best); +} + +void * __weak dereference_module_function_descriptor(struct module *mod, + void *ptr) +{ + return ptr; +} + +/* + * For kallsyms to ask for address resolution. NULL means not found. Careful + * not to lock to avoid deadlock on oopses, simply disable preemption. + */ +const char *module_address_lookup(unsigned long addr, + unsigned long *size, + unsigned long *offset, + char **modname, + const unsigned char **modbuildid, + char *namebuf) +{ + const char *ret = NULL; + struct module *mod; + + preempt_disable(); + mod = __module_address(addr); + if (mod) { + if (modname) + *modname = mod->name; + if (modbuildid) { +#if IS_ENABLED(CONFIG_STACKTRACE_BUILD_ID) + *modbuildid = mod->build_id; +#else + *modbuildid = NULL; +#endif + } + + ret = find_kallsyms_symbol(mod, addr, size, offset); + } + /* Make a copy in here where it's safe */ + if (ret) { + strncpy(namebuf, ret, KSYM_NAME_LEN - 1); + ret = namebuf; + } + preempt_enable(); + + return ret; +} + +int lookup_module_symbol_name(unsigned long addr, char *symname) +{ + struct module *mod; + + preempt_disable(); + list_for_each_entry_rcu(mod, &modules, list) { + if (mod->state == MODULE_STATE_UNFORMED) + continue; + if (within_module(addr, mod)) { + const char *sym; + + sym = find_kallsyms_symbol(mod, addr, NULL, NULL); + if (!sym) + goto out; + + strscpy(symname, sym, KSYM_NAME_LEN); + preempt_enable(); + return 0; + } + } +out: + preempt_enable(); + return -ERANGE; +} + +int lookup_module_symbol_attrs(unsigned long addr, unsigned long *size, + unsigned long *offset, char *modname, char *name) +{ + struct module *mod; + + preempt_disable(); + list_for_each_entry_rcu(mod, &modules, list) { + if (mod->state == MODULE_STATE_UNFORMED) + continue; + if (within_module(addr, mod)) { + const char *sym; + + sym = find_kallsyms_symbol(mod, addr, size, offset); + if (!sym) + goto out; + if (modname) + strscpy(modname, mod->name, MODULE_NAME_LEN); + if (name) + strscpy(name, sym, KSYM_NAME_LEN); + preempt_enable(); + return 0; + } + } +out: + preempt_enable(); + return -ERANGE; +} + +int module_get_kallsym(unsigned int symnum, unsigned long *value, char *type, + char *name, char *module_name, int *exported) +{ + struct module *mod; + + preempt_disable(); + list_for_each_entry_rcu(mod, &modules, list) { + struct mod_kallsyms *kallsyms; + + if (mod->state == MODULE_STATE_UNFORMED) + continue; + kallsyms = rcu_dereference_sched(mod->kallsyms); + if (symnum < kallsyms->num_symtab) { + const Elf_Sym *sym = &kallsyms->symtab[symnum]; + + *value = kallsyms_symbol_value(sym); + *type = kallsyms->typetab[symnum]; + strscpy(name, kallsyms_symbol_name(kallsyms, symnum), KSYM_NAME_LEN); + strscpy(module_name, mod->name, MODULE_NAME_LEN); + *exported = is_exported(name, *value, mod); + preempt_enable(); + return 0; + } + symnum -= kallsyms->num_symtab; + } + preempt_enable(); + return -ERANGE; +} + +/* Given a module and name of symbol, find and return the symbol's value */ +unsigned long find_kallsyms_symbol_value(struct module *mod, const char *name) +{ + unsigned int i; + struct mod_kallsyms *kallsyms = rcu_dereference_sched(mod->kallsyms); + + for (i = 0; i < kallsyms->num_symtab; i++) { + const Elf_Sym *sym = &kallsyms->symtab[i]; + + if (strcmp(name, kallsyms_symbol_name(kallsyms, i)) == 0 && + sym->st_shndx != SHN_UNDEF) + return kallsyms_symbol_value(sym); + } + return 0; +} + +/* Look for this name: can be of form module:name. */ +unsigned long module_kallsyms_lookup_name(const char *name) +{ + struct module *mod; + char *colon; + unsigned long ret = 0; + + /* Don't lock: we're in enough trouble already. */ + preempt_disable(); + if ((colon = strnchr(name, MODULE_NAME_LEN, ':')) != NULL) { + if ((mod = find_module_all(name, colon - name, false)) != NULL) + ret = find_kallsyms_symbol_value(mod, colon + 1); + } else { + list_for_each_entry_rcu(mod, &modules, list) { + if (mod->state == MODULE_STATE_UNFORMED) + continue; + if ((ret = find_kallsyms_symbol_value(mod, name)) != 0) + break; + } + } + preempt_enable(); + return ret; +} + +#ifdef CONFIG_LIVEPATCH +int module_kallsyms_on_each_symbol(int (*fn)(void *, const char *, + struct module *, unsigned long), + void *data) +{ + struct module *mod; + unsigned int i; + int ret = 0; + + mutex_lock(&module_mutex); + list_for_each_entry(mod, &modules, list) { + /* We hold module_mutex: no need for rcu_dereference_sched */ + struct mod_kallsyms *kallsyms = mod->kallsyms; + + if (mod->state == MODULE_STATE_UNFORMED) + continue; + for (i = 0; i < kallsyms->num_symtab; i++) { + const Elf_Sym *sym = &kallsyms->symtab[i]; + + if (sym->st_shndx == SHN_UNDEF) + continue; + + ret = fn(data, kallsyms_symbol_name(kallsyms, i), + mod, kallsyms_symbol_value(sym)); + if (ret != 0) + goto out; + } + } +out: + mutex_unlock(&module_mutex); + return ret; +} +#endif /* CONFIG_LIVEPATCH */ diff --git a/kernel/module/main.c b/kernel/module/main.c index 7dd283959c5c..952079987ea4 100644 --- a/kernel/module/main.c +++ b/kernel/module/main.c @@ -288,15 +288,6 @@ static bool check_exported_symbol(const struct symsearch *syms, return true; } -static unsigned long kernel_symbol_value(const struct kernel_symbol *sym) -{ -#ifdef CONFIG_HAVE_ARCH_PREL32_RELOCATIONS - return (unsigned long)offset_to_ptr(&sym->value_offset); -#else - return sym->value; -#endif -} - static const char *kernel_symbol_name(const struct kernel_symbol *sym) { #ifdef CONFIG_HAVE_ARCH_PREL32_RELOCATIONS @@ -317,7 +308,7 @@ static const char *kernel_symbol_namespace(const struct kernel_symbol *sym) #endif } -static int cmp_name(const void *name, const void *sym) +int cmp_name(const void *name, const void *sym) { return strcmp(name, kernel_symbol_name(sym)); } @@ -387,8 +378,8 @@ static bool find_symbol(struct find_symbol_arg *fsa) * Search for module by name: must hold module_mutex (or preempt disabled * for read-only access). */ -static struct module *find_module_all(const char *name, size_t len, - bool even_unformed) +struct module *find_module_all(const char *name, size_t len, + bool even_unformed) { struct module *mod; @@ -1294,13 +1285,6 @@ resolve_symbol_wait(struct module *mod, return ksym; } -#ifdef CONFIG_KALLSYMS -static inline bool sect_empty(const Elf_Shdr *sect) -{ - return !(sect->sh_flags & SHF_ALLOC) || sect->sh_size == 0; -} -#endif - /* * /sys/module/foo/sections stuff * J. Corbet @@ -2065,7 +2049,7 @@ unsigned int __weak arch_mod_section_prepend(struct module *mod, } /* Update size with this section: return offset. */ -static long get_offset(struct module *mod, unsigned int *size, +long module_get_offset(struct module *mod, unsigned int *size, Elf_Shdr *sechdr, unsigned int section) { long ret; @@ -2121,7 +2105,7 @@ static void layout_sections(struct module *mod, struct load_info *info) || s->sh_entsize != ~0UL || module_init_layout_section(sname)) continue; - s->sh_entsize = get_offset(mod, &mod->core_layout.size, s, i); + s->sh_entsize = module_get_offset(mod, &mod->core_layout.size, s, i); pr_debug("\t%s\n", sname); } switch (m) { @@ -2154,7 +2138,7 @@ static void layout_sections(struct module *mod, struct load_info *info) || s->sh_entsize != ~0UL || !module_init_layout_section(sname)) continue; - s->sh_entsize = (get_offset(mod, &mod->init_layout.size, s, i) + s->sh_entsize = (module_get_offset(mod, &mod->init_layout.size, s, i) | INIT_OFFSET_MASK); pr_debug("\t%s\n", sname); } @@ -2267,228 +2251,6 @@ static void free_modinfo(struct module *mod) } } -#ifdef CONFIG_KALLSYMS - -/* Lookup exported symbol in given range of kernel_symbols */ -static const struct kernel_symbol *lookup_exported_symbol(const char *name, - const struct kernel_symbol *start, - const struct kernel_symbol *stop) -{ - return bsearch(name, start, stop - start, - sizeof(struct kernel_symbol), cmp_name); -} - -static int is_exported(const char *name, unsigned long value, - const struct module *mod) -{ - const struct kernel_symbol *ks; - if (!mod) - ks = lookup_exported_symbol(name, __start___ksymtab, __stop___ksymtab); - else - ks = lookup_exported_symbol(name, mod->syms, mod->syms + mod->num_syms); - - return ks != NULL && kernel_symbol_value(ks) == value; -} - -/* As per nm */ -static char elf_type(const Elf_Sym *sym, const struct load_info *info) -{ - const Elf_Shdr *sechdrs = info->sechdrs; - - if (ELF_ST_BIND(sym->st_info) == STB_WEAK) { - if (ELF_ST_TYPE(sym->st_info) == STT_OBJECT) - return 'v'; - else - return 'w'; - } - if (sym->st_shndx == SHN_UNDEF) - return 'U'; - if (sym->st_shndx == SHN_ABS || sym->st_shndx == info->index.pcpu) - return 'a'; - if (sym->st_shndx >= SHN_LORESERVE) - return '?'; - if (sechdrs[sym->st_shndx].sh_flags & SHF_EXECINSTR) - return 't'; - if (sechdrs[sym->st_shndx].sh_flags & SHF_ALLOC - && sechdrs[sym->st_shndx].sh_type != SHT_NOBITS) { - if (!(sechdrs[sym->st_shndx].sh_flags & SHF_WRITE)) - return 'r'; - else if (sechdrs[sym->st_shndx].sh_flags & ARCH_SHF_SMALL) - return 'g'; - else - return 'd'; - } - if (sechdrs[sym->st_shndx].sh_type == SHT_NOBITS) { - if (sechdrs[sym->st_shndx].sh_flags & ARCH_SHF_SMALL) - return 's'; - else - return 'b'; - } - if (strstarts(info->secstrings + sechdrs[sym->st_shndx].sh_name, - ".debug")) { - return 'n'; - } - return '?'; -} - -static bool is_core_symbol(const Elf_Sym *src, const Elf_Shdr *sechdrs, - unsigned int shnum, unsigned int pcpundx) -{ - const Elf_Shdr *sec; - - if (src->st_shndx == SHN_UNDEF - || src->st_shndx >= shnum - || !src->st_name) - return false; - -#ifdef CONFIG_KALLSYMS_ALL - if (src->st_shndx == pcpundx) - return true; -#endif - - sec = sechdrs + src->st_shndx; - if (!(sec->sh_flags & SHF_ALLOC) -#ifndef CONFIG_KALLSYMS_ALL - || !(sec->sh_flags & SHF_EXECINSTR) -#endif - || (sec->sh_entsize & INIT_OFFSET_MASK)) - return false; - - return true; -} - -/* - * We only allocate and copy the strings needed by the parts of symtab - * we keep. This is simple, but has the effect of making multiple - * copies of duplicates. We could be more sophisticated, see - * linux-kernel thread starting with - * <73defb5e4bca04a6431392cc341112b1@localhost>. - */ -static void layout_symtab(struct module *mod, struct load_info *info) -{ - Elf_Shdr *symsect = info->sechdrs + info->index.sym; - Elf_Shdr *strsect = info->sechdrs + info->index.str; - const Elf_Sym *src; - unsigned int i, nsrc, ndst, strtab_size = 0; - - /* Put symbol section at end of init part of module. */ - symsect->sh_flags |= SHF_ALLOC; - symsect->sh_entsize = get_offset(mod, &mod->init_layout.size, symsect, - info->index.sym) | INIT_OFFSET_MASK; - pr_debug("\t%s\n", info->secstrings + symsect->sh_name); - - src = (void *)info->hdr + symsect->sh_offset; - nsrc = symsect->sh_size / sizeof(*src); - - /* Compute total space required for the core symbols' strtab. */ - for (ndst = i = 0; i < nsrc; i++) { - if (i == 0 || is_livepatch_module(mod) || - is_core_symbol(src+i, info->sechdrs, info->hdr->e_shnum, - info->index.pcpu)) { - strtab_size += strlen(&info->strtab[src[i].st_name])+1; - ndst++; - } - } - - /* Append room for core symbols at end of core part. */ - info->symoffs = ALIGN(mod->core_layout.size, symsect->sh_addralign ?: 1); - info->stroffs = mod->core_layout.size = info->symoffs + ndst * sizeof(Elf_Sym); - mod->core_layout.size += strtab_size; - info->core_typeoffs = mod->core_layout.size; - mod->core_layout.size += ndst * sizeof(char); - mod->core_layout.size = debug_align(mod->core_layout.size); - - /* Put string table section at end of init part of module. */ - strsect->sh_flags |= SHF_ALLOC; - strsect->sh_entsize = get_offset(mod, &mod->init_layout.size, strsect, - info->index.str) | INIT_OFFSET_MASK; - pr_debug("\t%s\n", info->secstrings + strsect->sh_name); - - /* We'll tack temporary mod_kallsyms on the end. */ - mod->init_layout.size = ALIGN(mod->init_layout.size, - __alignof__(struct mod_kallsyms)); - info->mod_kallsyms_init_off = mod->init_layout.size; - mod->init_layout.size += sizeof(struct mod_kallsyms); - info->init_typeoffs = mod->init_layout.size; - mod->init_layout.size += nsrc * sizeof(char); - mod->init_layout.size = debug_align(mod->init_layout.size); -} - -/* - * 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 - * core-only ones. - */ -static void add_kallsyms(struct module *mod, const struct load_info *info) -{ - unsigned int i, ndst; - const Elf_Sym *src; - Elf_Sym *dst; - char *s; - Elf_Shdr *symsec = &info->sechdrs[info->index.sym]; - - /* Set up to point into init section. */ - mod->kallsyms = mod->init_layout.base + info->mod_kallsyms_init_off; - - mod->kallsyms->symtab = (void *)symsec->sh_addr; - mod->kallsyms->num_symtab = symsec->sh_size / sizeof(Elf_Sym); - /* Make sure we get permanent strtab: don't use info->strtab. */ - mod->kallsyms->strtab = (void *)info->sechdrs[info->index.str].sh_addr; - mod->kallsyms->typetab = mod->init_layout.base + info->init_typeoffs; - - /* - * Now populate the cut down core kallsyms for after init - * and set types up while we still have access to sections. - */ - mod->core_kallsyms.symtab = dst = mod->core_layout.base + info->symoffs; - mod->core_kallsyms.strtab = s = mod->core_layout.base + info->stroffs; - mod->core_kallsyms.typetab = mod->core_layout.base + info->core_typeoffs; - src = mod->kallsyms->symtab; - for (ndst = i = 0; i < mod->kallsyms->num_symtab; i++) { - mod->kallsyms->typetab[i] = elf_type(src + i, info); - if (i == 0 || is_livepatch_module(mod) || - is_core_symbol(src+i, info->sechdrs, info->hdr->e_shnum, - info->index.pcpu)) { - mod->core_kallsyms.typetab[ndst] = - mod->kallsyms->typetab[i]; - dst[ndst] = src[i]; - dst[ndst++].st_name = s - mod->core_kallsyms.strtab; - s += strlcpy(s, &mod->kallsyms->strtab[src[i].st_name], - KSYM_NAME_LEN) + 1; - } - } - mod->core_kallsyms.num_symtab = ndst; -} -#else -static inline void layout_symtab(struct module *mod, struct load_info *info) -{ -} - -static void add_kallsyms(struct module *mod, const struct load_info *info) -{ -} -#endif /* CONFIG_KALLSYMS */ - -#if IS_ENABLED(CONFIG_KALLSYMS) && IS_ENABLED(CONFIG_STACKTRACE_BUILD_ID) -static void init_build_id(struct module *mod, const struct load_info *info) -{ - const Elf_Shdr *sechdr; - unsigned int i; - - for (i = 0; i < info->hdr->e_shnum; i++) { - sechdr = &info->sechdrs[i]; - if (!sect_empty(sechdr) && sechdr->sh_type == SHT_NOTE && - !build_id_parse_buf((void *)sechdr->sh_addr, mod->build_id, - sechdr->sh_size)) - break; - } -} -#else -static void init_build_id(struct module *mod, const struct load_info *info) -{ -} -#endif - static void dynamic_debug_setup(struct module *mod, struct _ddebug *debug, unsigned int num) { if (!debug) @@ -3799,287 +3561,6 @@ static inline int within(unsigned long addr, void *start, unsigned long size) return ((void *)addr >= start && (void *)addr < start + size); } -#ifdef CONFIG_KALLSYMS -/* - * This ignores the intensely annoying "mapping symbols" found - * in ARM ELF files: $a, $t and $d. - */ -static inline int is_arm_mapping_symbol(const char *str) -{ - if (str[0] == '.' && str[1] == 'L') - return true; - return str[0] == '$' && strchr("axtd", str[1]) - && (str[2] == '\0' || str[2] == '.'); -} - -static const char *kallsyms_symbol_name(struct mod_kallsyms *kallsyms, unsigned int symnum) -{ - return kallsyms->strtab + kallsyms->symtab[symnum].st_name; -} - -/* - * Given a module and address, find the corresponding symbol and return its name - * while providing its size and offset if needed. - */ -static const char *find_kallsyms_symbol(struct module *mod, - unsigned long addr, - unsigned long *size, - unsigned long *offset) -{ - unsigned int i, best = 0; - unsigned long nextval, bestval; - struct mod_kallsyms *kallsyms = rcu_dereference_sched(mod->kallsyms); - - /* At worse, next value is at end of module */ - if (within_module_init(addr, mod)) - nextval = (unsigned long)mod->init_layout.base+mod->init_layout.text_size; - else - nextval = (unsigned long)mod->core_layout.base+mod->core_layout.text_size; - - bestval = kallsyms_symbol_value(&kallsyms->symtab[best]); - - /* - * Scan for closest preceding symbol, and next symbol. (ELF - * starts real symbols at 1). - */ - for (i = 1; i < kallsyms->num_symtab; i++) { - const Elf_Sym *sym = &kallsyms->symtab[i]; - unsigned long thisval = kallsyms_symbol_value(sym); - - if (sym->st_shndx == SHN_UNDEF) - continue; - - /* - * We ignore unnamed symbols: they're uninformative - * and inserted at a whim. - */ - if (*kallsyms_symbol_name(kallsyms, i) == '\0' - || is_arm_mapping_symbol(kallsyms_symbol_name(kallsyms, i))) - continue; - - if (thisval <= addr && thisval > bestval) { - best = i; - bestval = thisval; - } - if (thisval > addr && thisval < nextval) - nextval = thisval; - } - - if (!best) - return NULL; - - if (size) - *size = nextval - bestval; - if (offset) - *offset = addr - bestval; - - return kallsyms_symbol_name(kallsyms, best); -} - -void * __weak dereference_module_function_descriptor(struct module *mod, - void *ptr) -{ - return ptr; -} - -/* - * For kallsyms to ask for address resolution. NULL means not found. Careful - * not to lock to avoid deadlock on oopses, simply disable preemption. - */ -const char *module_address_lookup(unsigned long addr, - unsigned long *size, - unsigned long *offset, - char **modname, - const unsigned char **modbuildid, - char *namebuf) -{ - const char *ret = NULL; - struct module *mod; - - preempt_disable(); - mod = __module_address(addr); - if (mod) { - if (modname) - *modname = mod->name; - if (modbuildid) { -#if IS_ENABLED(CONFIG_STACKTRACE_BUILD_ID) - *modbuildid = mod->build_id; -#else - *modbuildid = NULL; -#endif - } - - ret = find_kallsyms_symbol(mod, addr, size, offset); - } - /* Make a copy in here where it's safe */ - if (ret) { - strncpy(namebuf, ret, KSYM_NAME_LEN - 1); - ret = namebuf; - } - preempt_enable(); - - return ret; -} - -int lookup_module_symbol_name(unsigned long addr, char *symname) -{ - struct module *mod; - - preempt_disable(); - list_for_each_entry_rcu(mod, &modules, list) { - if (mod->state == MODULE_STATE_UNFORMED) - continue; - if (within_module(addr, mod)) { - const char *sym; - - sym = find_kallsyms_symbol(mod, addr, NULL, NULL); - if (!sym) - goto out; - - strlcpy(symname, sym, KSYM_NAME_LEN); - preempt_enable(); - return 0; - } - } -out: - preempt_enable(); - return -ERANGE; -} - -int lookup_module_symbol_attrs(unsigned long addr, unsigned long *size, - unsigned long *offset, char *modname, char *name) -{ - struct module *mod; - - preempt_disable(); - list_for_each_entry_rcu(mod, &modules, list) { - if (mod->state == MODULE_STATE_UNFORMED) - continue; - if (within_module(addr, mod)) { - const char *sym; - - sym = find_kallsyms_symbol(mod, addr, size, offset); - if (!sym) - goto out; - if (modname) - strlcpy(modname, mod->name, MODULE_NAME_LEN); - if (name) - strlcpy(name, sym, KSYM_NAME_LEN); - preempt_enable(); - return 0; - } - } -out: - preempt_enable(); - return -ERANGE; -} - -int module_get_kallsym(unsigned int symnum, unsigned long *value, char *type, - char *name, char *module_name, int *exported) -{ - struct module *mod; - - preempt_disable(); - list_for_each_entry_rcu(mod, &modules, list) { - struct mod_kallsyms *kallsyms; - - if (mod->state == MODULE_STATE_UNFORMED) - continue; - kallsyms = rcu_dereference_sched(mod->kallsyms); - if (symnum < kallsyms->num_symtab) { - const Elf_Sym *sym = &kallsyms->symtab[symnum]; - - *value = kallsyms_symbol_value(sym); - *type = kallsyms->typetab[symnum]; - strlcpy(name, kallsyms_symbol_name(kallsyms, symnum), KSYM_NAME_LEN); - strlcpy(module_name, mod->name, MODULE_NAME_LEN); - *exported = is_exported(name, *value, mod); - preempt_enable(); - return 0; - } - symnum -= kallsyms->num_symtab; - } - preempt_enable(); - return -ERANGE; -} - -/* Given a module and name of symbol, find and return the symbol's value */ -static unsigned long find_kallsyms_symbol_value(struct module *mod, const char *name) -{ - unsigned int i; - struct mod_kallsyms *kallsyms = rcu_dereference_sched(mod->kallsyms); - - for (i = 0; i < kallsyms->num_symtab; i++) { - const Elf_Sym *sym = &kallsyms->symtab[i]; - - if (strcmp(name, kallsyms_symbol_name(kallsyms, i)) == 0 && - sym->st_shndx != SHN_UNDEF) - return kallsyms_symbol_value(sym); - } - return 0; -} - -/* Look for this name: can be of form module:name. */ -unsigned long module_kallsyms_lookup_name(const char *name) -{ - struct module *mod; - char *colon; - unsigned long ret = 0; - - /* Don't lock: we're in enough trouble already. */ - preempt_disable(); - if ((colon = strnchr(name, MODULE_NAME_LEN, ':')) != NULL) { - if ((mod = find_module_all(name, colon - name, false)) != NULL) - ret = find_kallsyms_symbol_value(mod, colon+1); - } else { - list_for_each_entry_rcu(mod, &modules, list) { - if (mod->state == MODULE_STATE_UNFORMED) - continue; - if ((ret = find_kallsyms_symbol_value(mod, name)) != 0) - break; - } - } - preempt_enable(); - return ret; -} - -#ifdef CONFIG_LIVEPATCH -int module_kallsyms_on_each_symbol(int (*fn)(void *, const char *, - struct module *, unsigned long), - void *data) -{ - struct module *mod; - unsigned int i; - int ret = 0; - - mutex_lock(&module_mutex); - list_for_each_entry(mod, &modules, list) { - /* We hold module_mutex: no need for rcu_dereference_sched */ - struct mod_kallsyms *kallsyms = mod->kallsyms; - - if (mod->state == MODULE_STATE_UNFORMED) - continue; - for (i = 0; i < kallsyms->num_symtab; i++) { - const Elf_Sym *sym = &kallsyms->symtab[i]; - - if (sym->st_shndx == SHN_UNDEF) - continue; - - ret = fn(data, kallsyms_symbol_name(kallsyms, i), - mod, kallsyms_symbol_value(sym)); - if (ret != 0) - goto out; - - cond_resched(); - } - } -out: - mutex_unlock(&module_mutex); - return ret; -} -#endif /* CONFIG_LIVEPATCH */ -#endif /* CONFIG_KALLSYMS */ - static void cfi_init(struct module *mod) { #ifdef CONFIG_CFI_CLANG From patchwork Thu Mar 10 10:24:09 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aaron Tomlin X-Patchwork-Id: 12776131 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9E718C433EF for ; Thu, 10 Mar 2022 10:25:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S241264AbiCJK0F (ORCPT ); Thu, 10 Mar 2022 05:26:05 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44960 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241205AbiCJKZy (ORCPT ); Thu, 10 Mar 2022 05:25:54 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 6DA8813FAD0 for ; Thu, 10 Mar 2022 02:24:40 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1646907879; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=nlcVw0WJ8YWnydchI7778Sj1W6AqsxSBROpPSypOfl0=; b=Ol+dx7PX/Y5UP36sbIGIy64bGW4Cmc92MVFxbItJJqZHwCNWXlsSVxzmsm4jYqvDrrMIuZ 6oZQ1zNwLCdt3gp3saD2Z/ED6sKRyThMO3eETPyTY9bNPQtHJf67GkiEqNi5g9LWwQvHh1 Nd6MEOP1bKaPW7BXSKdtbxlPffpmHhM= Received: from mail-wr1-f71.google.com (mail-wr1-f71.google.com [209.85.221.71]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-226-7_6m_TsWMfWvMSC7Mqtlmg-1; Thu, 10 Mar 2022 05:24:38 -0500 X-MC-Unique: 7_6m_TsWMfWvMSC7Mqtlmg-1 Received: by mail-wr1-f71.google.com with SMTP id p18-20020adfba92000000b001e8f7697cc7so1520297wrg.20 for ; Thu, 10 Mar 2022 02:24:38 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=nlcVw0WJ8YWnydchI7778Sj1W6AqsxSBROpPSypOfl0=; b=ZZtGS6uGuWb5ne7Uo4vvrdsK2w8UBH+TdB672dYvXU1zCUFt9NaZbImC0blT/5Ch1C uZqxZVMMtN3qvMOwl2LOtuYt89iW+jPsPxUbpIVQeKg8gd56dh37kflhlDUtWGLLYH6s lzP09a8EFOCW9l6FGBRguq+XUZluu4xITTaP4LVnA29m1u1+fmbCYtVxqzKAhWxf53a5 VqY77dlfjEYHlw5Drd8ABiUzCATug5LQBX+sokbImAdvvfFhxcEttNnyaBxzxjS7FBua WnB2CGTwKMHrmcZcBv57/ok+ptRkp1m0F7ssgDFHkan0Q896mQeHQbS/vTPzPtmJQ6El v+SA== X-Gm-Message-State: AOAM533X6nPdzN8Gu7jlNu9FfCx9Pwk5n/beynlPSmk+pgCH9jiwdG8M FMjSl5V0VuVNTLgMtHR8n0dz9MsVYWKszPWQMTCTGQvZi1dWEhQgLinq0e4ODZnz2m76J+8aKTe AsJo/0nWpkPDimgG5On2LCV+I X-Received: by 2002:a7b:c042:0:b0:389:7336:158b with SMTP id u2-20020a7bc042000000b003897336158bmr3045324wmc.15.1646907877387; Thu, 10 Mar 2022 02:24:37 -0800 (PST) X-Google-Smtp-Source: ABdhPJx01aIrs4KFuIC/5aueOsdBG7PjrtS7tvpyYmay+Iosl72wx4vqlYpsXiaj3n029JTvSNP8Yw== X-Received: by 2002:a7b:c042:0:b0:389:7336:158b with SMTP id u2-20020a7bc042000000b003897336158bmr3045306wmc.15.1646907877206; Thu, 10 Mar 2022 02:24:37 -0800 (PST) Received: from localhost (cpc111743-lutn13-2-0-cust979.9-3.cable.virginm.net. [82.17.115.212]) by smtp.gmail.com with ESMTPSA id t9-20020a05600c198900b0037bd5fabd10sm4850329wmq.48.2022.03.10.02.24.36 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 10 Mar 2022 02:24:36 -0800 (PST) From: Aaron Tomlin To: mcgrof@kernel.org, christophe.leroy@csgroup.eu Cc: cl@linux.com, mbenes@suse.cz, akpm@linux-foundation.org, jeyu@kernel.org, linux-kernel@vger.kernel.org, linux-modules@vger.kernel.org, void@manifault.com, atomlin@atomlin.com, allen.lkml@gmail.com, joe@perches.com, msuchanek@suse.de, oleksandr@natalenko.name, jason.wessel@windriver.com, pmladek@suse.com, daniel.thompson@linaro.org, hch@infradead.org Subject: [PATCH v11 10/14] module: kallsyms: Fix suspicious rcu usage Date: Thu, 10 Mar 2022 10:24:09 +0000 Message-Id: <20220310102413.3438665-11-atomlin@redhat.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220310102413.3438665-1-atomlin@redhat.com> References: <20220310102413.3438665-1-atomlin@redhat.com> MIME-Version: 1.0 Precedence: bulk List-ID: No functional change. The purpose of this patch is to address the various Sparse warnings due to the incorrect dereference/or access of an __rcu pointer. Signed-off-by: Aaron Tomlin --- kernel/module/kallsyms.c | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/kernel/module/kallsyms.c b/kernel/module/kallsyms.c index 1b0780e20aab..a3da0686a2a6 100644 --- a/kernel/module/kallsyms.c +++ b/kernel/module/kallsyms.c @@ -171,14 +171,17 @@ void add_kallsyms(struct module *mod, const struct load_info *info) Elf_Shdr *symsec = &info->sechdrs[info->index.sym]; /* Set up to point into init section. */ - mod->kallsyms = mod->init_layout.base + info->mod_kallsyms_init_off; + mod->kallsyms = (void __rcu *)mod->init_layout.base + + info->mod_kallsyms_init_off; + preempt_disable(); /* The following is safe since this pointer cannot change */ - mod->kallsyms->symtab = (void *)symsec->sh_addr; - mod->kallsyms->num_symtab = symsec->sh_size / sizeof(Elf_Sym); + rcu_dereference_sched(mod->kallsyms)->symtab = (void *)symsec->sh_addr; + rcu_dereference_sched(mod->kallsyms)->num_symtab = symsec->sh_size / sizeof(Elf_Sym); /* Make sure we get permanent strtab: don't use info->strtab. */ - mod->kallsyms->strtab = (void *)info->sechdrs[info->index.str].sh_addr; - mod->kallsyms->typetab = mod->init_layout.base + info->init_typeoffs; + rcu_dereference_sched(mod->kallsyms)->strtab = + (void *)info->sechdrs[info->index.str].sh_addr; + rcu_dereference_sched(mod->kallsyms)->typetab = mod->init_layout.base + info->init_typeoffs; /* * Now populate the cut down core kallsyms for after init @@ -187,20 +190,22 @@ void add_kallsyms(struct module *mod, const struct load_info *info) mod->core_kallsyms.symtab = dst = mod->core_layout.base + info->symoffs; mod->core_kallsyms.strtab = s = mod->core_layout.base + info->stroffs; mod->core_kallsyms.typetab = mod->core_layout.base + info->core_typeoffs; - src = mod->kallsyms->symtab; - for (ndst = i = 0; i < mod->kallsyms->num_symtab; i++) { - mod->kallsyms->typetab[i] = elf_type(src + i, info); + src = rcu_dereference_sched(mod->kallsyms)->symtab; + for (ndst = i = 0; i < rcu_dereference_sched(mod->kallsyms)->num_symtab; i++) { + rcu_dereference_sched(mod->kallsyms)->typetab[i] = elf_type(src + i, info); if (i == 0 || is_livepatch_module(mod) || is_core_symbol(src + i, info->sechdrs, info->hdr->e_shnum, info->index.pcpu)) { mod->core_kallsyms.typetab[ndst] = - mod->kallsyms->typetab[i]; + rcu_dereference_sched(mod->kallsyms)->typetab[i]; dst[ndst] = src[i]; dst[ndst++].st_name = s - mod->core_kallsyms.strtab; - s += strscpy(s, &mod->kallsyms->strtab[src[i].st_name], + s += strscpy(s, + &rcu_dereference_sched(mod->kallsyms)->strtab[src[i].st_name], KSYM_NAME_LEN) + 1; } } + preempt_enable(); mod->core_kallsyms.num_symtab = ndst; } @@ -478,11 +483,16 @@ int module_kallsyms_on_each_symbol(int (*fn)(void *, const char *, mutex_lock(&module_mutex); list_for_each_entry(mod, &modules, list) { - /* We hold module_mutex: no need for rcu_dereference_sched */ - struct mod_kallsyms *kallsyms = mod->kallsyms; + struct mod_kallsyms *kallsyms; if (mod->state == MODULE_STATE_UNFORMED) continue; + + /* Use rcu_dereference_sched() to remain compliant with the sparse tool */ + preempt_disable(); + kallsyms = rcu_dereference_sched(mod->kallsyms); + preempt_enable(); + for (i = 0; i < kallsyms->num_symtab; i++) { const Elf_Sym *sym = &kallsyms->symtab[i]; From patchwork Thu Mar 10 10:24:10 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aaron Tomlin X-Patchwork-Id: 12776132 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id E0C69C433F5 for ; Thu, 10 Mar 2022 10:25:34 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S241365AbiCJK0c (ORCPT ); Thu, 10 Mar 2022 05:26:32 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44950 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241310AbiCJKZ6 (ORCPT ); Thu, 10 Mar 2022 05:25:58 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id DD2F913FAC8 for ; Thu, 10 Mar 2022 02:24:43 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1646907882; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=t51dSs9d9mDJR5zHj4NgMBJ6gQxLMRrjvZ9uJ9INxC4=; b=Pm8jl1osJWkNprsr/FBFzReQ54Dai/4oFJaG4EIC7FI4PNrxypFsEYH15B6LwRDDRGRD1T +12deGM/fCmuNjVJqmhXMV5Ue4BnzX/qdxrbvapYI3T3aDnPRY3gdAKYqXUTwn+qffI+CR C0WdZ5RISnMb4OXGoDwwJVptIHuQnHQ= Received: from mail-wm1-f69.google.com (mail-wm1-f69.google.com [209.85.128.69]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-393-fYsHt1ljMbCCFuDlrdFImQ-1; Thu, 10 Mar 2022 05:24:41 -0500 X-MC-Unique: fYsHt1ljMbCCFuDlrdFImQ-1 Received: by mail-wm1-f69.google.com with SMTP id 7-20020a1c1907000000b003471d9bbe8dso2681851wmz.0 for ; Thu, 10 Mar 2022 02:24:41 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=t51dSs9d9mDJR5zHj4NgMBJ6gQxLMRrjvZ9uJ9INxC4=; b=AfqDkuuVw7Du5a1K4kSaG7DZlWE2P6ar9rbIS3DMO9s/YOu+z03Fwtwmtw+olZ5g1T u7COLsPc2JiBWf6ejntIarWE4DIbzmGptUvMDoskydZp0JHBSX+wmz3tcRS3gyw374Ow b4FN29/iYEl8bzubQ7Wl6CedGo2XAJ+dMlVxRkS08augpyg4C7Hv3cX2wTW6d/CWLhoD YJ8gRcvpkVgnUHijK74zuhq0qGLlop2CgpuLRtlPcgq5e4sNTGvU8zGkf+C2ER17ceUO CCA9S/V8+KmNJI03542Dy5Va3aNK6+ixGdDEhnBNPwiNG1eMKc4borEprV72Ui97NQqz jPPA== X-Gm-Message-State: AOAM5301ybAN6sTvY/sl7yrg+0ce1n1dSCdyWb3B1csIhTaZTFu5ZyzT WC8XvpkHVllCp3Gs0oZEvFy5tcnad1+HkafzUO2mhGW/mmLxxTxxo/7itZ29lwCY04s+kXs2Cm5 21C8FiUGh0Zhj+GnoBbJ8lwM9 X-Received: by 2002:a7b:cb83:0:b0:37e:bc50:3c6b with SMTP id m3-20020a7bcb83000000b0037ebc503c6bmr11087156wmi.67.1646907879466; Thu, 10 Mar 2022 02:24:39 -0800 (PST) X-Google-Smtp-Source: ABdhPJzsaicc8sbo0ZEdi5jWqAvDM+KOtcJCgfHB0sHzDPi/mgG7YHiqo8z4ZXe/l8H2xj073Z9FCA== X-Received: by 2002:a7b:cb83:0:b0:37e:bc50:3c6b with SMTP id m3-20020a7bcb83000000b0037ebc503c6bmr11087131wmi.67.1646907879144; Thu, 10 Mar 2022 02:24:39 -0800 (PST) Received: from localhost (cpc111743-lutn13-2-0-cust979.9-3.cable.virginm.net. [82.17.115.212]) by smtp.gmail.com with ESMTPSA id e1-20020a05600c108100b00389cdb3372csm4086854wmd.26.2022.03.10.02.24.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 10 Mar 2022 02:24:38 -0800 (PST) From: Aaron Tomlin To: mcgrof@kernel.org, christophe.leroy@csgroup.eu Cc: cl@linux.com, mbenes@suse.cz, akpm@linux-foundation.org, jeyu@kernel.org, linux-kernel@vger.kernel.org, linux-modules@vger.kernel.org, void@manifault.com, atomlin@atomlin.com, allen.lkml@gmail.com, joe@perches.com, msuchanek@suse.de, oleksandr@natalenko.name, jason.wessel@windriver.com, pmladek@suse.com, daniel.thompson@linaro.org, hch@infradead.org Subject: [PATCH v11 11/14] module: Move procfs support into a separate file Date: Thu, 10 Mar 2022 10:24:10 +0000 Message-Id: <20220310102413.3438665-12-atomlin@redhat.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220310102413.3438665-1-atomlin@redhat.com> References: <20220310102413.3438665-1-atomlin@redhat.com> MIME-Version: 1.0 Precedence: bulk List-ID: No functional change. This patch migrates code that allows one to generate a list of loaded/or linked modules via /proc when procfs support is enabled into kernel/module/procfs.c. Reviewed-by: Christophe Leroy Signed-off-by: Aaron Tomlin --- kernel/module/Makefile | 1 + kernel/module/internal.h | 1 + kernel/module/main.c | 131 +----------------------------------- kernel/module/procfs.c | 142 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 145 insertions(+), 130 deletions(-) create mode 100644 kernel/module/procfs.c diff --git a/kernel/module/Makefile b/kernel/module/Makefile index 9901bed3ab5b..94296c98a67f 100644 --- a/kernel/module/Makefile +++ b/kernel/module/Makefile @@ -15,3 +15,4 @@ obj-$(CONFIG_MODULES_TREE_LOOKUP) += tree_lookup.o obj-$(CONFIG_STRICT_MODULE_RWX) += strict_rwx.o obj-$(CONFIG_DEBUG_KMEMLEAK) += debug_kmemleak.o obj-$(CONFIG_KALLSYMS) += kallsyms.o +obj-$(CONFIG_PROC_FS) += procfs.o diff --git a/kernel/module/internal.h b/kernel/module/internal.h index 44ca05b9eb8f..6af40c2d145f 100644 --- a/kernel/module/internal.h +++ b/kernel/module/internal.h @@ -72,6 +72,7 @@ struct module *find_module_all(const char *name, size_t len, bool even_unformed) int cmp_name(const void *name, const void *sym); long module_get_offset(struct module *mod, unsigned int *size, Elf_Shdr *sechdr, unsigned int section); +char *module_flags(struct module *mod, char *buf); static inline unsigned long kernel_symbol_value(const struct kernel_symbol *sym) { diff --git a/kernel/module/main.c b/kernel/module/main.c index 952079987ea4..44b6fd1acc44 100644 --- a/kernel/module/main.c +++ b/kernel/module/main.c @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include @@ -805,31 +804,6 @@ SYSCALL_DEFINE2(delete_module, const char __user *, name_user, return ret; } -static inline void print_unload_info(struct seq_file *m, struct module *mod) -{ - struct module_use *use; - int printed_something = 0; - - seq_printf(m, " %i ", module_refcount(mod)); - - /* - * Always include a trailing , so userspace can differentiate - * between this and the old multi-field proc format. - */ - list_for_each_entry(use, &mod->source_list, source_list) { - printed_something = 1; - seq_printf(m, "%s,", use->source->name); - } - - if (mod->init != NULL && mod->exit == NULL) { - printed_something = 1; - seq_puts(m, "[permanent],"); - } - - if (!printed_something) - seq_puts(m, "-"); -} - void __symbol_put(const char *symbol) { struct find_symbol_arg fsa = { @@ -919,12 +893,6 @@ void module_put(struct module *module) EXPORT_SYMBOL(module_put); #else /* !CONFIG_MODULE_UNLOAD */ -static inline void print_unload_info(struct seq_file *m, struct module *mod) -{ - /* We don't know the usage count, or what modules are using. */ - seq_puts(m, " - -"); -} - static inline void module_unload_free(struct module *mod) { } @@ -3596,7 +3564,7 @@ static void cfi_cleanup(struct module *mod) } /* Keep in sync with MODULE_FLAGS_BUF_SIZE !!! */ -static char *module_flags(struct module *mod, char *buf) +char *module_flags(struct module *mod, char *buf) { int bx = 0; @@ -3619,103 +3587,6 @@ static char *module_flags(struct module *mod, char *buf) return buf; } -#ifdef CONFIG_PROC_FS -/* Called by the /proc file system to return a list of modules. */ -static void *m_start(struct seq_file *m, loff_t *pos) -{ - mutex_lock(&module_mutex); - return seq_list_start(&modules, *pos); -} - -static void *m_next(struct seq_file *m, void *p, loff_t *pos) -{ - return seq_list_next(p, &modules, pos); -} - -static void m_stop(struct seq_file *m, void *p) -{ - mutex_unlock(&module_mutex); -} - -static int m_show(struct seq_file *m, void *p) -{ - struct module *mod = list_entry(p, struct module, list); - char buf[MODULE_FLAGS_BUF_SIZE]; - void *value; - - /* We always ignore unformed modules. */ - if (mod->state == MODULE_STATE_UNFORMED) - return 0; - - seq_printf(m, "%s %u", - mod->name, mod->init_layout.size + mod->core_layout.size); - print_unload_info(m, mod); - - /* Informative for users. */ - seq_printf(m, " %s", - mod->state == MODULE_STATE_GOING ? "Unloading" : - mod->state == MODULE_STATE_COMING ? "Loading" : - "Live"); - /* Used by oprofile and other similar tools. */ - value = m->private ? NULL : mod->core_layout.base; - seq_printf(m, " 0x%px", value); - - /* Taints info */ - if (mod->taints) - seq_printf(m, " %s", module_flags(mod, buf)); - - seq_puts(m, "\n"); - return 0; -} - -/* - * Format: modulename size refcount deps address - * - * Where refcount is a number or -, and deps is a comma-separated list - * of depends or -. - */ -static const struct seq_operations modules_op = { - .start = m_start, - .next = m_next, - .stop = m_stop, - .show = m_show -}; - -/* - * This also sets the "private" pointer to non-NULL if the - * kernel pointers should be hidden (so you can just test - * "m->private" to see if you should keep the values private). - * - * We use the same logic as for /proc/kallsyms. - */ -static int modules_open(struct inode *inode, struct file *file) -{ - int err = seq_open(file, &modules_op); - - if (!err) { - struct seq_file *m = file->private_data; - m->private = kallsyms_show_value(file->f_cred) ? NULL : (void *)8ul; - } - - return err; -} - -static const struct proc_ops modules_proc_ops = { - .proc_flags = PROC_ENTRY_PERMANENT, - .proc_open = modules_open, - .proc_read = seq_read, - .proc_lseek = seq_lseek, - .proc_release = seq_release, -}; - -static int __init proc_modules_init(void) -{ - proc_create("modules", 0, NULL, &modules_proc_ops); - return 0; -} -module_init(proc_modules_init); -#endif - /* Given an address, look for it in the module exception tables. */ const struct exception_table_entry *search_module_extables(unsigned long addr) { diff --git a/kernel/module/procfs.c b/kernel/module/procfs.c new file mode 100644 index 000000000000..2717e130788e --- /dev/null +++ b/kernel/module/procfs.c @@ -0,0 +1,142 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Module proc support + * + * Copyright (C) 2008 Alexey Dobriyan + */ + +#include +#include +#include +#include +#include +#include "internal.h" + +#ifdef CONFIG_MODULE_UNLOAD +static inline void print_unload_info(struct seq_file *m, struct module *mod) +{ + struct module_use *use; + int printed_something = 0; + + seq_printf(m, " %i ", module_refcount(mod)); + + /* + * Always include a trailing , so userspace can differentiate + * between this and the old multi-field proc format. + */ + list_for_each_entry(use, &mod->source_list, source_list) { + printed_something = 1; + seq_printf(m, "%s,", use->source->name); + } + + if (mod->init && !mod->exit) { + printed_something = 1; + seq_puts(m, "[permanent],"); + } + + if (!printed_something) + seq_puts(m, "-"); +} +#else /* !CONFIG_MODULE_UNLOAD */ +static inline void print_unload_info(struct seq_file *m, struct module *mod) +{ + /* We don't know the usage count, or what modules are using. */ + seq_puts(m, " - -"); +} +#endif /* CONFIG_MODULE_UNLOAD */ + +/* Called by the /proc file system to return a list of modules. */ +static void *m_start(struct seq_file *m, loff_t *pos) +{ + mutex_lock(&module_mutex); + return seq_list_start(&modules, *pos); +} + +static void *m_next(struct seq_file *m, void *p, loff_t *pos) +{ + return seq_list_next(p, &modules, pos); +} + +static void m_stop(struct seq_file *m, void *p) +{ + mutex_unlock(&module_mutex); +} + +static int m_show(struct seq_file *m, void *p) +{ + struct module *mod = list_entry(p, struct module, list); + char buf[MODULE_FLAGS_BUF_SIZE]; + void *value; + + /* We always ignore unformed modules. */ + if (mod->state == MODULE_STATE_UNFORMED) + return 0; + + seq_printf(m, "%s %u", + mod->name, mod->init_layout.size + mod->core_layout.size); + print_unload_info(m, mod); + + /* Informative for users. */ + seq_printf(m, " %s", + mod->state == MODULE_STATE_GOING ? "Unloading" : + mod->state == MODULE_STATE_COMING ? "Loading" : + "Live"); + /* Used by oprofile and other similar tools. */ + value = m->private ? NULL : mod->core_layout.base; + seq_printf(m, " 0x%px", value); + + /* Taints info */ + if (mod->taints) + seq_printf(m, " %s", module_flags(mod, buf)); + + seq_puts(m, "\n"); + return 0; +} + +/* + * Format: modulename size refcount deps address + * + * Where refcount is a number or -, and deps is a comma-separated list + * of depends or -. + */ +static const struct seq_operations modules_op = { + .start = m_start, + .next = m_next, + .stop = m_stop, + .show = m_show +}; + +/* + * This also sets the "private" pointer to non-NULL if the + * kernel pointers should be hidden (so you can just test + * "m->private" to see if you should keep the values private). + * + * We use the same logic as for /proc/kallsyms. + */ +static int modules_open(struct inode *inode, struct file *file) +{ + int err = seq_open(file, &modules_op); + + if (!err) { + struct seq_file *m = file->private_data; + + m->private = kallsyms_show_value(file->f_cred) ? NULL : (void *)8ul; + } + + return err; +} + +static const struct proc_ops modules_proc_ops = { + .proc_flags = PROC_ENTRY_PERMANENT, + .proc_open = modules_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_release = seq_release, +}; + +static int __init proc_modules_init(void) +{ + proc_create("modules", 0, NULL, &modules_proc_ops); + return 0; +} +module_init(proc_modules_init); From patchwork Thu Mar 10 10:26:23 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aaron Tomlin X-Patchwork-Id: 12776134 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 837EFC433F5 for ; Thu, 10 Mar 2022 10:27:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S241374AbiCJK2E (ORCPT ); Thu, 10 Mar 2022 05:28:04 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47414 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236886AbiCJK1g (ORCPT ); Thu, 10 Mar 2022 05:27:36 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 7CB03EB9 for ; Thu, 10 Mar 2022 02:26:34 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1646907993; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=/nFeCEHT4VAKjxsShgIS9T0wVwh0OwhbuhCqF5a+FHk=; b=h3e/K8Yqx57rGGpgtSADwzJd5qPETGLWVoPR+Dv0jWApr/oDM6tuI4ahls/JYNaOY2N+B5 uq9ZEcGjdBa/7bX4p93MZDf47NrbPZt4/Fr3clKuL7JQJbkAy1cECJ4qRWgeHhHnJkiwNY MWgsjLUx3rODSOqRdOQaCjCXeu01MBY= Received: from mail-wr1-f69.google.com (mail-wr1-f69.google.com [209.85.221.69]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-21-u8CzP4xVMF629hE9clxvtg-1; Thu, 10 Mar 2022 05:26:32 -0500 X-MC-Unique: u8CzP4xVMF629hE9clxvtg-1 Received: by mail-wr1-f69.google.com with SMTP id y13-20020adfee0d000000b001f1fa450a3dso1535462wrn.11 for ; Thu, 10 Mar 2022 02:26:32 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=/nFeCEHT4VAKjxsShgIS9T0wVwh0OwhbuhCqF5a+FHk=; b=1h6kdRDQvPssH7Qhjm9DgYivvucPK4q+7pR50JPaHsr4hCoXJjuuzWpNAJDkpvRl4i ippifVMF4OSGoB2S2uyd2Z0zc7bSJMjmPkMZMHUk3b7erHkYkIOfCAHsJY5TeicuxIoF hJ1jmWdeUu3/yLUDUHL1gYug06EMMmeaHoqnGwcKfx8nS8gIN7/UB+Eb7hnEIF4c+54m rQx0mcmnSiUl+yJhVZlEeel/L1eNzPUwaFuOWBTD8z3la5AzOy9mzJUwg/Ip+Vr6VO0a /oi7yEbTwTJGgPosR79p4Ie8gocp5jIu1JGgON22eoh2Xv+HMd29WPZJ6eVNi6ZLCgn+ nyBw== X-Gm-Message-State: AOAM532VlPeO/efI9OEpTvO1BlCd99+kxmRpbIpv5HlH1xzSbu2NxtVG 4vMzlc+iXoWzWIQ/tgGPlHhKQbH3OlY7FBgZ1M1Nm2AdvG+K45x4pDWbfBSV6vkKXBPrqFqvfCC +mSRc1d4PSAwuYQhA5mi9dSQB X-Received: by 2002:a5d:6dad:0:b0:203:84b4:da13 with SMTP id u13-20020a5d6dad000000b0020384b4da13mr2639847wrs.162.1646907987886; Thu, 10 Mar 2022 02:26:27 -0800 (PST) X-Google-Smtp-Source: ABdhPJxJm7e5iMCou9cUnYHF2+atlhwqQv2t/sHuW29BuJS27q41pLAQji+v8ify6JSL7WC9fGeCOw== X-Received: by 2002:a5d:6dad:0:b0:203:84b4:da13 with SMTP id u13-20020a5d6dad000000b0020384b4da13mr2639808wrs.162.1646907987449; Thu, 10 Mar 2022 02:26:27 -0800 (PST) Received: from localhost (cpc111743-lutn13-2-0-cust979.9-3.cable.virginm.net. [82.17.115.212]) by smtp.gmail.com with ESMTPSA id l7-20020adfe9c7000000b001f06f8ec92dsm3815498wrn.30.2022.03.10.02.26.26 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 10 Mar 2022 02:26:26 -0800 (PST) From: Aaron Tomlin To: mcgrof@kernel.org, christophe.leroy@csgroup.eu Cc: cl@linux.com, mbenes@suse.cz, akpm@linux-foundation.org, jeyu@kernel.org, linux-kernel@vger.kernel.org, linux-modules@vger.kernel.org, void@manifault.com, atomlin@atomlin.com, allen.lkml@gmail.com, joe@perches.com, msuchanek@suse.de, oleksandr@natalenko.name, jason.wessel@windriver.com, pmladek@suse.com, daniel.thompson@linaro.org, hch@infradead.org Subject: [PATCH v11 12/14] module: Move sysfs support into a separate file Date: Thu, 10 Mar 2022 10:26:23 +0000 Message-Id: <20220310102625.3441888-1-atomlin@redhat.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220310102413.3438665-1-atomlin@redhat.com> References: <20220310102413.3438665-1-atomlin@redhat.com> MIME-Version: 1.0 Precedence: bulk List-ID: No functional change. This patch migrates module sysfs support out of core code into kernel/module/sysfs.c. In addition simple code refactoring to make this possible. Reviewed-by: Christophe Leroy Signed-off-by: Aaron Tomlin --- kernel/module/Makefile | 1 + kernel/module/internal.h | 21 ++ kernel/module/main.c | 469 +-------------------------------------- kernel/module/sysfs.c | 436 ++++++++++++++++++++++++++++++++++++ 4 files changed, 461 insertions(+), 466 deletions(-) create mode 100644 kernel/module/sysfs.c diff --git a/kernel/module/Makefile b/kernel/module/Makefile index 94296c98a67f..cf8dcdc6b55f 100644 --- a/kernel/module/Makefile +++ b/kernel/module/Makefile @@ -16,3 +16,4 @@ obj-$(CONFIG_STRICT_MODULE_RWX) += strict_rwx.o obj-$(CONFIG_DEBUG_KMEMLEAK) += debug_kmemleak.o obj-$(CONFIG_KALLSYMS) += kallsyms.o obj-$(CONFIG_PROC_FS) += procfs.o +obj-$(CONFIG_SYSFS) += sysfs.o diff --git a/kernel/module/internal.h b/kernel/module/internal.h index 6af40c2d145f..62d749ef695e 100644 --- a/kernel/module/internal.h +++ b/kernel/module/internal.h @@ -34,6 +34,9 @@ extern struct mutex module_mutex; extern struct list_head modules; +extern struct module_attribute *modinfo_attrs[]; +extern size_t modinfo_attrs_count; + /* Provided by the linker */ extern const struct kernel_symbol __start___ksymtab[]; extern const struct kernel_symbol __stop___ksymtab[]; @@ -204,3 +207,21 @@ static inline void init_build_id(struct module *mod, const struct load_info *inf static inline void layout_symtab(struct module *mod, struct load_info *info) { } static inline void add_kallsyms(struct module *mod, const struct load_info *info) { } #endif /* CONFIG_KALLSYMS */ + +#ifdef CONFIG_SYSFS +int mod_sysfs_setup(struct module *mod, const struct load_info *info, + struct kernel_param *kparam, unsigned int num_params); +void mod_sysfs_teardown(struct module *mod); +void init_param_lock(struct module *mod); +#else /* !CONFIG_SYSFS */ +static inline int mod_sysfs_setup(struct module *mod, + const struct load_info *info, + struct kernel_param *kparam, + unsigned int num_params) +{ + return 0; +} + +static inline void mod_sysfs_teardown(struct module *mod) { } +static inline void init_param_lock(struct module *mod) { } +#endif /* CONFIG_SYSFS */ diff --git a/kernel/module/main.c b/kernel/module/main.c index 44b6fd1acc44..b8a59b5c3e3a 100644 --- a/kernel/module/main.c +++ b/kernel/module/main.c @@ -14,9 +14,7 @@ #include #include #include -#include #include -#include #include #include #include @@ -989,7 +987,7 @@ static ssize_t show_taint(struct module_attribute *mattr, static struct module_attribute modinfo_taint = __ATTR(taint, 0444, show_taint, NULL); -static struct module_attribute *modinfo_attrs[] = { +struct module_attribute *modinfo_attrs[] = { &module_uevent, &modinfo_version, &modinfo_srcversion, @@ -1003,6 +1001,8 @@ static struct module_attribute *modinfo_attrs[] = { NULL, }; +size_t modinfo_attrs_count = ARRAY_SIZE(modinfo_attrs); + static const char vermagic[] = VERMAGIC_STRING; static int try_to_force_load(struct module *mod, const char *reason) @@ -1253,469 +1253,6 @@ resolve_symbol_wait(struct module *mod, return ksym; } -/* - * /sys/module/foo/sections stuff - * J. Corbet - */ -#ifdef CONFIG_SYSFS - -#ifdef CONFIG_KALLSYMS -struct module_sect_attr { - struct bin_attribute battr; - unsigned long address; -}; - -struct module_sect_attrs { - struct attribute_group grp; - unsigned int nsections; - struct module_sect_attr attrs[]; -}; - -#define MODULE_SECT_READ_SIZE (3 /* "0x", "\n" */ + (BITS_PER_LONG / 4)) -static ssize_t module_sect_read(struct file *file, struct kobject *kobj, - struct bin_attribute *battr, - char *buf, loff_t pos, size_t count) -{ - struct module_sect_attr *sattr = - container_of(battr, struct module_sect_attr, battr); - char bounce[MODULE_SECT_READ_SIZE + 1]; - size_t wrote; - - if (pos != 0) - return -EINVAL; - - /* - * Since we're a binary read handler, we must account for the - * trailing NUL byte that sprintf will write: if "buf" is - * too small to hold the NUL, or the NUL is exactly the last - * byte, the read will look like it got truncated by one byte. - * Since there is no way to ask sprintf nicely to not write - * the NUL, we have to use a bounce buffer. - */ - wrote = scnprintf(bounce, sizeof(bounce), "0x%px\n", - kallsyms_show_value(file->f_cred) - ? (void *)sattr->address : NULL); - count = min(count, wrote); - memcpy(buf, bounce, count); - - return count; -} - -static void free_sect_attrs(struct module_sect_attrs *sect_attrs) -{ - unsigned int section; - - for (section = 0; section < sect_attrs->nsections; section++) - kfree(sect_attrs->attrs[section].battr.attr.name); - kfree(sect_attrs); -} - -static void add_sect_attrs(struct module *mod, const struct load_info *info) -{ - unsigned int nloaded = 0, i, size[2]; - struct module_sect_attrs *sect_attrs; - struct module_sect_attr *sattr; - struct bin_attribute **gattr; - - /* Count loaded sections and allocate structures */ - for (i = 0; i < info->hdr->e_shnum; i++) - if (!sect_empty(&info->sechdrs[i])) - nloaded++; - size[0] = ALIGN(struct_size(sect_attrs, attrs, nloaded), - sizeof(sect_attrs->grp.bin_attrs[0])); - size[1] = (nloaded + 1) * sizeof(sect_attrs->grp.bin_attrs[0]); - sect_attrs = kzalloc(size[0] + size[1], GFP_KERNEL); - if (sect_attrs == NULL) - return; - - /* Setup section attributes. */ - sect_attrs->grp.name = "sections"; - sect_attrs->grp.bin_attrs = (void *)sect_attrs + size[0]; - - sect_attrs->nsections = 0; - sattr = §_attrs->attrs[0]; - gattr = §_attrs->grp.bin_attrs[0]; - for (i = 0; i < info->hdr->e_shnum; i++) { - Elf_Shdr *sec = &info->sechdrs[i]; - if (sect_empty(sec)) - continue; - sysfs_bin_attr_init(&sattr->battr); - sattr->address = sec->sh_addr; - sattr->battr.attr.name = - kstrdup(info->secstrings + sec->sh_name, GFP_KERNEL); - if (sattr->battr.attr.name == NULL) - goto out; - sect_attrs->nsections++; - sattr->battr.read = module_sect_read; - sattr->battr.size = MODULE_SECT_READ_SIZE; - sattr->battr.attr.mode = 0400; - *(gattr++) = &(sattr++)->battr; - } - *gattr = NULL; - - if (sysfs_create_group(&mod->mkobj.kobj, §_attrs->grp)) - goto out; - - mod->sect_attrs = sect_attrs; - return; - out: - free_sect_attrs(sect_attrs); -} - -static void remove_sect_attrs(struct module *mod) -{ - if (mod->sect_attrs) { - sysfs_remove_group(&mod->mkobj.kobj, - &mod->sect_attrs->grp); - /* - * We are positive that no one is using any sect attrs - * at this point. Deallocate immediately. - */ - free_sect_attrs(mod->sect_attrs); - mod->sect_attrs = NULL; - } -} - -/* - * /sys/module/foo/notes/.section.name gives contents of SHT_NOTE sections. - */ - -struct module_notes_attrs { - struct kobject *dir; - unsigned int notes; - struct bin_attribute attrs[]; -}; - -static ssize_t module_notes_read(struct file *filp, struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buf, loff_t pos, size_t count) -{ - /* - * The caller checked the pos and count against our size. - */ - memcpy(buf, bin_attr->private + pos, count); - return count; -} - -static void free_notes_attrs(struct module_notes_attrs *notes_attrs, - unsigned int i) -{ - if (notes_attrs->dir) { - while (i-- > 0) - sysfs_remove_bin_file(notes_attrs->dir, - ¬es_attrs->attrs[i]); - kobject_put(notes_attrs->dir); - } - kfree(notes_attrs); -} - -static void add_notes_attrs(struct module *mod, const struct load_info *info) -{ - unsigned int notes, loaded, i; - struct module_notes_attrs *notes_attrs; - struct bin_attribute *nattr; - - /* failed to create section attributes, so can't create notes */ - if (!mod->sect_attrs) - return; - - /* Count notes sections and allocate structures. */ - notes = 0; - for (i = 0; i < info->hdr->e_shnum; i++) - if (!sect_empty(&info->sechdrs[i]) && - (info->sechdrs[i].sh_type == SHT_NOTE)) - ++notes; - - if (notes == 0) - return; - - notes_attrs = kzalloc(struct_size(notes_attrs, attrs, notes), - GFP_KERNEL); - if (notes_attrs == NULL) - return; - - notes_attrs->notes = notes; - nattr = ¬es_attrs->attrs[0]; - for (loaded = i = 0; i < info->hdr->e_shnum; ++i) { - if (sect_empty(&info->sechdrs[i])) - continue; - if (info->sechdrs[i].sh_type == SHT_NOTE) { - sysfs_bin_attr_init(nattr); - nattr->attr.name = mod->sect_attrs->attrs[loaded].battr.attr.name; - nattr->attr.mode = S_IRUGO; - nattr->size = info->sechdrs[i].sh_size; - nattr->private = (void *) info->sechdrs[i].sh_addr; - nattr->read = module_notes_read; - ++nattr; - } - ++loaded; - } - - notes_attrs->dir = kobject_create_and_add("notes", &mod->mkobj.kobj); - if (!notes_attrs->dir) - goto out; - - for (i = 0; i < notes; ++i) - if (sysfs_create_bin_file(notes_attrs->dir, - ¬es_attrs->attrs[i])) - goto out; - - mod->notes_attrs = notes_attrs; - return; - - out: - free_notes_attrs(notes_attrs, i); -} - -static void remove_notes_attrs(struct module *mod) -{ - if (mod->notes_attrs) - free_notes_attrs(mod->notes_attrs, mod->notes_attrs->notes); -} - -#else - -static inline void add_sect_attrs(struct module *mod, - const struct load_info *info) -{ -} - -static inline void remove_sect_attrs(struct module *mod) -{ -} - -static inline void add_notes_attrs(struct module *mod, - const struct load_info *info) -{ -} - -static inline void remove_notes_attrs(struct module *mod) -{ -} -#endif /* CONFIG_KALLSYMS */ - -static void del_usage_links(struct module *mod) -{ -#ifdef CONFIG_MODULE_UNLOAD - struct module_use *use; - - mutex_lock(&module_mutex); - list_for_each_entry(use, &mod->target_list, target_list) - sysfs_remove_link(use->target->holders_dir, mod->name); - mutex_unlock(&module_mutex); -#endif -} - -static int add_usage_links(struct module *mod) -{ - int ret = 0; -#ifdef CONFIG_MODULE_UNLOAD - struct module_use *use; - - mutex_lock(&module_mutex); - list_for_each_entry(use, &mod->target_list, target_list) { - ret = sysfs_create_link(use->target->holders_dir, - &mod->mkobj.kobj, mod->name); - if (ret) - break; - } - mutex_unlock(&module_mutex); - if (ret) - del_usage_links(mod); -#endif - return ret; -} - -static void module_remove_modinfo_attrs(struct module *mod, int end); - -static int module_add_modinfo_attrs(struct module *mod) -{ - struct module_attribute *attr; - struct module_attribute *temp_attr; - int error = 0; - int i; - - mod->modinfo_attrs = kzalloc((sizeof(struct module_attribute) * - (ARRAY_SIZE(modinfo_attrs) + 1)), - GFP_KERNEL); - if (!mod->modinfo_attrs) - return -ENOMEM; - - temp_attr = mod->modinfo_attrs; - for (i = 0; (attr = modinfo_attrs[i]); i++) { - if (!attr->test || attr->test(mod)) { - memcpy(temp_attr, attr, sizeof(*temp_attr)); - sysfs_attr_init(&temp_attr->attr); - error = sysfs_create_file(&mod->mkobj.kobj, - &temp_attr->attr); - if (error) - goto error_out; - ++temp_attr; - } - } - - return 0; - -error_out: - if (i > 0) - module_remove_modinfo_attrs(mod, --i); - else - kfree(mod->modinfo_attrs); - return error; -} - -static void module_remove_modinfo_attrs(struct module *mod, int end) -{ - struct module_attribute *attr; - int i; - - for (i = 0; (attr = &mod->modinfo_attrs[i]); i++) { - if (end >= 0 && i > end) - break; - /* pick a field to test for end of list */ - if (!attr->attr.name) - break; - sysfs_remove_file(&mod->mkobj.kobj, &attr->attr); - if (attr->free) - attr->free(mod); - } - kfree(mod->modinfo_attrs); -} - -static void mod_kobject_put(struct module *mod) -{ - DECLARE_COMPLETION_ONSTACK(c); - mod->mkobj.kobj_completion = &c; - kobject_put(&mod->mkobj.kobj); - wait_for_completion(&c); -} - -static int mod_sysfs_init(struct module *mod) -{ - int err; - struct kobject *kobj; - - if (!module_sysfs_initialized) { - pr_err("%s: module sysfs not initialized\n", mod->name); - err = -EINVAL; - goto out; - } - - kobj = kset_find_obj(module_kset, mod->name); - if (kobj) { - pr_err("%s: module is already loaded\n", mod->name); - kobject_put(kobj); - err = -EINVAL; - goto out; - } - - mod->mkobj.mod = mod; - - memset(&mod->mkobj.kobj, 0, sizeof(mod->mkobj.kobj)); - mod->mkobj.kobj.kset = module_kset; - err = kobject_init_and_add(&mod->mkobj.kobj, &module_ktype, NULL, - "%s", mod->name); - if (err) - mod_kobject_put(mod); - -out: - return err; -} - -static int mod_sysfs_setup(struct module *mod, - const struct load_info *info, - struct kernel_param *kparam, - unsigned int num_params) -{ - int err; - - err = mod_sysfs_init(mod); - if (err) - goto out; - - mod->holders_dir = kobject_create_and_add("holders", &mod->mkobj.kobj); - if (!mod->holders_dir) { - err = -ENOMEM; - goto out_unreg; - } - - err = module_param_sysfs_setup(mod, kparam, num_params); - if (err) - goto out_unreg_holders; - - err = module_add_modinfo_attrs(mod); - if (err) - goto out_unreg_param; - - err = add_usage_links(mod); - if (err) - goto out_unreg_modinfo_attrs; - - add_sect_attrs(mod, info); - add_notes_attrs(mod, info); - - return 0; - -out_unreg_modinfo_attrs: - module_remove_modinfo_attrs(mod, -1); -out_unreg_param: - module_param_sysfs_remove(mod); -out_unreg_holders: - kobject_put(mod->holders_dir); -out_unreg: - mod_kobject_put(mod); -out: - return err; -} - -static void mod_sysfs_fini(struct module *mod) -{ - remove_notes_attrs(mod); - remove_sect_attrs(mod); - mod_kobject_put(mod); -} - -static void init_param_lock(struct module *mod) -{ - mutex_init(&mod->param_lock); -} -#else /* !CONFIG_SYSFS */ - -static int mod_sysfs_setup(struct module *mod, - const struct load_info *info, - struct kernel_param *kparam, - unsigned int num_params) -{ - return 0; -} - -static void mod_sysfs_fini(struct module *mod) -{ -} - -static void module_remove_modinfo_attrs(struct module *mod, int end) -{ -} - -static void del_usage_links(struct module *mod) -{ -} - -static void init_param_lock(struct module *mod) -{ -} -#endif /* CONFIG_SYSFS */ - -static void mod_sysfs_teardown(struct module *mod) -{ - del_usage_links(mod); - module_remove_modinfo_attrs(mod, -1); - module_param_sysfs_remove(mod); - kobject_put(mod->mkobj.drivers_dir); - kobject_put(mod->holders_dir); - mod_sysfs_fini(mod); -} - /* * LKM RO/NX protection: protect module's text/ro-data * from modification and any data from execution. diff --git a/kernel/module/sysfs.c b/kernel/module/sysfs.c new file mode 100644 index 000000000000..ce68f821dcd1 --- /dev/null +++ b/kernel/module/sysfs.c @@ -0,0 +1,436 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Module sysfs support + * + * Copyright (C) 2008 Rusty Russell + */ + +#include +#include +#include +#include +#include +#include +#include +#include "internal.h" + +/* + * /sys/module/foo/sections stuff + * J. Corbet + */ +#ifdef CONFIG_KALLSYMS +struct module_sect_attr { + struct bin_attribute battr; + unsigned long address; +}; + +struct module_sect_attrs { + struct attribute_group grp; + unsigned int nsections; + struct module_sect_attr attrs[]; +}; + +#define MODULE_SECT_READ_SIZE (3 /* "0x", "\n" */ + (BITS_PER_LONG / 4)) +static ssize_t module_sect_read(struct file *file, struct kobject *kobj, + struct bin_attribute *battr, + char *buf, loff_t pos, size_t count) +{ + struct module_sect_attr *sattr = + container_of(battr, struct module_sect_attr, battr); + char bounce[MODULE_SECT_READ_SIZE + 1]; + size_t wrote; + + if (pos != 0) + return -EINVAL; + + /* + * Since we're a binary read handler, we must account for the + * trailing NUL byte that sprintf will write: if "buf" is + * too small to hold the NUL, or the NUL is exactly the last + * byte, the read will look like it got truncated by one byte. + * Since there is no way to ask sprintf nicely to not write + * the NUL, we have to use a bounce buffer. + */ + wrote = scnprintf(bounce, sizeof(bounce), "0x%px\n", + kallsyms_show_value(file->f_cred) + ? (void *)sattr->address : NULL); + count = min(count, wrote); + memcpy(buf, bounce, count); + + return count; +} + +static void free_sect_attrs(struct module_sect_attrs *sect_attrs) +{ + unsigned int section; + + for (section = 0; section < sect_attrs->nsections; section++) + kfree(sect_attrs->attrs[section].battr.attr.name); + kfree(sect_attrs); +} + +static void add_sect_attrs(struct module *mod, const struct load_info *info) +{ + unsigned int nloaded = 0, i, size[2]; + struct module_sect_attrs *sect_attrs; + struct module_sect_attr *sattr; + struct bin_attribute **gattr; + + /* Count loaded sections and allocate structures */ + for (i = 0; i < info->hdr->e_shnum; i++) + if (!sect_empty(&info->sechdrs[i])) + nloaded++; + size[0] = ALIGN(struct_size(sect_attrs, attrs, nloaded), + sizeof(sect_attrs->grp.bin_attrs[0])); + size[1] = (nloaded + 1) * sizeof(sect_attrs->grp.bin_attrs[0]); + sect_attrs = kzalloc(size[0] + size[1], GFP_KERNEL); + if (!sect_attrs) + return; + + /* Setup section attributes. */ + sect_attrs->grp.name = "sections"; + sect_attrs->grp.bin_attrs = (void *)sect_attrs + size[0]; + + sect_attrs->nsections = 0; + sattr = §_attrs->attrs[0]; + gattr = §_attrs->grp.bin_attrs[0]; + for (i = 0; i < info->hdr->e_shnum; i++) { + Elf_Shdr *sec = &info->sechdrs[i]; + + if (sect_empty(sec)) + continue; + sysfs_bin_attr_init(&sattr->battr); + sattr->address = sec->sh_addr; + sattr->battr.attr.name = + kstrdup(info->secstrings + sec->sh_name, GFP_KERNEL); + if (!sattr->battr.attr.name) + goto out; + sect_attrs->nsections++; + sattr->battr.read = module_sect_read; + sattr->battr.size = MODULE_SECT_READ_SIZE; + sattr->battr.attr.mode = 0400; + *(gattr++) = &(sattr++)->battr; + } + *gattr = NULL; + + if (sysfs_create_group(&mod->mkobj.kobj, §_attrs->grp)) + goto out; + + mod->sect_attrs = sect_attrs; + return; +out: + free_sect_attrs(sect_attrs); +} + +static void remove_sect_attrs(struct module *mod) +{ + if (mod->sect_attrs) { + sysfs_remove_group(&mod->mkobj.kobj, + &mod->sect_attrs->grp); + /* + * We are positive that no one is using any sect attrs + * at this point. Deallocate immediately. + */ + free_sect_attrs(mod->sect_attrs); + mod->sect_attrs = NULL; + } +} + +/* + * /sys/module/foo/notes/.section.name gives contents of SHT_NOTE sections. + */ + +struct module_notes_attrs { + struct kobject *dir; + unsigned int notes; + struct bin_attribute attrs[]; +}; + +static ssize_t module_notes_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t pos, size_t count) +{ + /* + * The caller checked the pos and count against our size. + */ + memcpy(buf, bin_attr->private + pos, count); + return count; +} + +static void free_notes_attrs(struct module_notes_attrs *notes_attrs, + unsigned int i) +{ + if (notes_attrs->dir) { + while (i-- > 0) + sysfs_remove_bin_file(notes_attrs->dir, + ¬es_attrs->attrs[i]); + kobject_put(notes_attrs->dir); + } + kfree(notes_attrs); +} + +static void add_notes_attrs(struct module *mod, const struct load_info *info) +{ + unsigned int notes, loaded, i; + struct module_notes_attrs *notes_attrs; + struct bin_attribute *nattr; + + /* failed to create section attributes, so can't create notes */ + if (!mod->sect_attrs) + return; + + /* Count notes sections and allocate structures. */ + notes = 0; + for (i = 0; i < info->hdr->e_shnum; i++) + if (!sect_empty(&info->sechdrs[i]) && + info->sechdrs[i].sh_type == SHT_NOTE) + ++notes; + + if (notes == 0) + return; + + notes_attrs = kzalloc(struct_size(notes_attrs, attrs, notes), + GFP_KERNEL); + if (!notes_attrs) + return; + + notes_attrs->notes = notes; + nattr = ¬es_attrs->attrs[0]; + for (loaded = i = 0; i < info->hdr->e_shnum; ++i) { + if (sect_empty(&info->sechdrs[i])) + continue; + if (info->sechdrs[i].sh_type == SHT_NOTE) { + sysfs_bin_attr_init(nattr); + nattr->attr.name = mod->sect_attrs->attrs[loaded].battr.attr.name; + nattr->attr.mode = 0444; + nattr->size = info->sechdrs[i].sh_size; + nattr->private = (void *)info->sechdrs[i].sh_addr; + nattr->read = module_notes_read; + ++nattr; + } + ++loaded; + } + + notes_attrs->dir = kobject_create_and_add("notes", &mod->mkobj.kobj); + if (!notes_attrs->dir) + goto out; + + for (i = 0; i < notes; ++i) + if (sysfs_create_bin_file(notes_attrs->dir, + ¬es_attrs->attrs[i])) + goto out; + + mod->notes_attrs = notes_attrs; + return; + +out: + free_notes_attrs(notes_attrs, i); +} + +static void remove_notes_attrs(struct module *mod) +{ + if (mod->notes_attrs) + free_notes_attrs(mod->notes_attrs, mod->notes_attrs->notes); +} + +#else /* !CONFIG_KALLSYMS */ +static inline void add_sect_attrs(struct module *mod, const struct load_info *info) { } +static inline void remove_sect_attrs(struct module *mod) { } +static inline void add_notes_attrs(struct module *mod, const struct load_info *info) { } +static inline void remove_notes_attrs(struct module *mod) { } +#endif /* CONFIG_KALLSYMS */ + +static void del_usage_links(struct module *mod) +{ +#ifdef CONFIG_MODULE_UNLOAD + struct module_use *use; + + mutex_lock(&module_mutex); + list_for_each_entry(use, &mod->target_list, target_list) + sysfs_remove_link(use->target->holders_dir, mod->name); + mutex_unlock(&module_mutex); +#endif +} + +static int add_usage_links(struct module *mod) +{ + int ret = 0; +#ifdef CONFIG_MODULE_UNLOAD + struct module_use *use; + + mutex_lock(&module_mutex); + list_for_each_entry(use, &mod->target_list, target_list) { + ret = sysfs_create_link(use->target->holders_dir, + &mod->mkobj.kobj, mod->name); + if (ret) + break; + } + mutex_unlock(&module_mutex); + if (ret) + del_usage_links(mod); +#endif + return ret; +} + +static void module_remove_modinfo_attrs(struct module *mod, int end) +{ + struct module_attribute *attr; + int i; + + for (i = 0; (attr = &mod->modinfo_attrs[i]); i++) { + if (end >= 0 && i > end) + break; + /* pick a field to test for end of list */ + if (!attr->attr.name) + break; + sysfs_remove_file(&mod->mkobj.kobj, &attr->attr); + if (attr->free) + attr->free(mod); + } + kfree(mod->modinfo_attrs); +} + +static int module_add_modinfo_attrs(struct module *mod) +{ + struct module_attribute *attr; + struct module_attribute *temp_attr; + int error = 0; + int i; + + mod->modinfo_attrs = kzalloc((sizeof(struct module_attribute) * + (modinfo_attrs_count + 1)), + GFP_KERNEL); + if (!mod->modinfo_attrs) + return -ENOMEM; + + temp_attr = mod->modinfo_attrs; + for (i = 0; (attr = modinfo_attrs[i]); i++) { + if (!attr->test || attr->test(mod)) { + memcpy(temp_attr, attr, sizeof(*temp_attr)); + sysfs_attr_init(&temp_attr->attr); + error = sysfs_create_file(&mod->mkobj.kobj, + &temp_attr->attr); + if (error) + goto error_out; + ++temp_attr; + } + } + + return 0; + +error_out: + if (i > 0) + module_remove_modinfo_attrs(mod, --i); + else + kfree(mod->modinfo_attrs); + return error; +} + +static void mod_kobject_put(struct module *mod) +{ + DECLARE_COMPLETION_ONSTACK(c); + + mod->mkobj.kobj_completion = &c; + kobject_put(&mod->mkobj.kobj); + wait_for_completion(&c); +} + +static int mod_sysfs_init(struct module *mod) +{ + int err; + struct kobject *kobj; + + if (!module_sysfs_initialized) { + pr_err("%s: module sysfs not initialized\n", mod->name); + err = -EINVAL; + goto out; + } + + kobj = kset_find_obj(module_kset, mod->name); + if (kobj) { + pr_err("%s: module is already loaded\n", mod->name); + kobject_put(kobj); + err = -EINVAL; + goto out; + } + + mod->mkobj.mod = mod; + + memset(&mod->mkobj.kobj, 0, sizeof(mod->mkobj.kobj)); + mod->mkobj.kobj.kset = module_kset; + err = kobject_init_and_add(&mod->mkobj.kobj, &module_ktype, NULL, + "%s", mod->name); + if (err) + mod_kobject_put(mod); + +out: + return err; +} + +int mod_sysfs_setup(struct module *mod, + const struct load_info *info, + struct kernel_param *kparam, + unsigned int num_params) +{ + int err; + + err = mod_sysfs_init(mod); + if (err) + goto out; + + mod->holders_dir = kobject_create_and_add("holders", &mod->mkobj.kobj); + if (!mod->holders_dir) { + err = -ENOMEM; + goto out_unreg; + } + + err = module_param_sysfs_setup(mod, kparam, num_params); + if (err) + goto out_unreg_holders; + + err = module_add_modinfo_attrs(mod); + if (err) + goto out_unreg_param; + + err = add_usage_links(mod); + if (err) + goto out_unreg_modinfo_attrs; + + add_sect_attrs(mod, info); + add_notes_attrs(mod, info); + + return 0; + +out_unreg_modinfo_attrs: + module_remove_modinfo_attrs(mod, -1); +out_unreg_param: + module_param_sysfs_remove(mod); +out_unreg_holders: + kobject_put(mod->holders_dir); +out_unreg: + mod_kobject_put(mod); +out: + return err; +} + +static void mod_sysfs_fini(struct module *mod) +{ + remove_notes_attrs(mod); + remove_sect_attrs(mod); + mod_kobject_put(mod); +} + +void mod_sysfs_teardown(struct module *mod) +{ + del_usage_links(mod); + module_remove_modinfo_attrs(mod, -1); + module_param_sysfs_remove(mod); + kobject_put(mod->mkobj.drivers_dir); + kobject_put(mod->holders_dir); + mod_sysfs_fini(mod); +} + +void init_param_lock(struct module *mod) +{ + mutex_init(&mod->param_lock); +} From patchwork Thu Mar 10 10:26:24 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aaron Tomlin X-Patchwork-Id: 12776133 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8F5F6C433EF for ; Thu, 10 Mar 2022 10:26:35 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233409AbiCJK1e (ORCPT ); Thu, 10 Mar 2022 05:27:34 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47386 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232740AbiCJK1e (ORCPT ); Thu, 10 Mar 2022 05:27:34 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id EF2EB12E778 for ; Thu, 10 Mar 2022 02:26:32 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1646907992; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=5NMs3KnPEzp7T5GTU2fcwESnZ9O2vamkfw2Pjzynyr8=; b=ieCpBYU7QI6t7+cCT/CEyo+RMmsrTHgCPb+7ETPqoH8OVL6ugFW1AHVIjHLsqPLSemVEhU 7UlH/Zvl32/ou01/wvR/tn2cZIO0fIO4Rc2YHE53w5VjjZmtqwlqjlxWf0sslKozgcWZKa kshRymZmo0CsmRL4kfrpY3oLXxZZIC0= Received: from mail-wm1-f72.google.com (mail-wm1-f72.google.com [209.85.128.72]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-28-_mvj6N0fNWilwjLqllZL6A-1; Thu, 10 Mar 2022 05:26:30 -0500 X-MC-Unique: _mvj6N0fNWilwjLqllZL6A-1 Received: by mail-wm1-f72.google.com with SMTP id v67-20020a1cac46000000b00383e71bb26fso1961192wme.1 for ; Thu, 10 Mar 2022 02:26:30 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=5NMs3KnPEzp7T5GTU2fcwESnZ9O2vamkfw2Pjzynyr8=; b=WzKnuW0c/8wHQWez486Rlwa2EXrq58q/0AJkYG6/7o8bVQY/YocWmmzeStkWjYFX3M X/uVCKaaqsqBj2He+riUVPcl8MrbJ/upMv3gNc8FUlTFne7/Alc7S9cx1qS6HdXv+l3N sYt1hqgfRBShT0e0beRe5GFC+trZzTKb/BZIS9iAYKlY8HADDslU6o5H6oUzB84gh1v2 Z8R/mCqF+huyRJfrDRvwRrrSaXk52FcgXRv7rtsgj2LmKcWML4oukLqsyKV/H3Lra11L l8e7SoFj6f62A99lxBxxSyHlhEQ/gohnns91Rsy7xes1aXdBqizL6qqdqNwu00musZ0s Gm5g== X-Gm-Message-State: AOAM533ayoKlyfSThTBbQAeJO6GfteXIgBgbzFoDommudbKHxZ2ukCwg qphsga7PDIhPsgSQqX82K7WvFvLcG6n1fxxZ7+/3SyAAR/j8QGaPkRyAR03d2aqwDddnQ+cSVsZ YcZey/Ckw/yurzG3ZF8d44h0I X-Received: by 2002:a1c:f018:0:b0:37b:c13c:3128 with SMTP id a24-20020a1cf018000000b0037bc13c3128mr10989080wmb.157.1646907989592; Thu, 10 Mar 2022 02:26:29 -0800 (PST) X-Google-Smtp-Source: ABdhPJwaeToA92CQDbwh6JfKe+NhTPTu7XxJSxzS89UvvNgP2J/UVk8xZdg4tNggtD0D1buIuJL3vw== X-Received: by 2002:a1c:f018:0:b0:37b:c13c:3128 with SMTP id a24-20020a1cf018000000b0037bc13c3128mr10989059wmb.157.1646907989362; Thu, 10 Mar 2022 02:26:29 -0800 (PST) Received: from localhost (cpc111743-lutn13-2-0-cust979.9-3.cable.virginm.net. [82.17.115.212]) by smtp.gmail.com with ESMTPSA id v124-20020a1cac82000000b0037c3d08e0e7sm7259171wme.29.2022.03.10.02.26.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 10 Mar 2022 02:26:28 -0800 (PST) From: Aaron Tomlin To: mcgrof@kernel.org, christophe.leroy@csgroup.eu Cc: cl@linux.com, mbenes@suse.cz, akpm@linux-foundation.org, jeyu@kernel.org, linux-kernel@vger.kernel.org, linux-modules@vger.kernel.org, void@manifault.com, atomlin@atomlin.com, allen.lkml@gmail.com, joe@perches.com, msuchanek@suse.de, oleksandr@natalenko.name, jason.wessel@windriver.com, pmladek@suse.com, daniel.thompson@linaro.org, hch@infradead.org Subject: [PATCH v11 13/14] module: Move kdb module related code out of main kdb code Date: Thu, 10 Mar 2022 10:26:24 +0000 Message-Id: <20220310102625.3441888-2-atomlin@redhat.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220310102625.3441888-1-atomlin@redhat.com> References: <20220310102413.3438665-1-atomlin@redhat.com> <20220310102625.3441888-1-atomlin@redhat.com> MIME-Version: 1.0 Precedence: bulk List-ID: No functional change. This patch migrates the kdb 'lsmod' command support out of main kdb code into its own file under kernel/module. In addition to the above, a minor style warning i.e. missing a blank line after declarations, was resolved too. The new file was added to MAINTAINERS. Finally we remove linux/module.h as it is entirely redundant. Signed-off-by: Aaron Tomlin Reviewed-by: Daniel Thompson Acked-by: Daniel Thompson --- MAINTAINERS | 1 + include/linux/kdb.h | 1 + kernel/debug/kdb/kdb_io.c | 1 - kernel/debug/kdb/kdb_keyboard.c | 1 - kernel/debug/kdb/kdb_main.c | 49 ----------------------------- kernel/debug/kdb/kdb_private.h | 4 --- kernel/debug/kdb/kdb_support.c | 1 - kernel/module/Makefile | 1 + kernel/module/kdb.c | 56 +++++++++++++++++++++++++++++++++ kernel/module/main.c | 4 --- 10 files changed, 59 insertions(+), 60 deletions(-) create mode 100644 kernel/module/kdb.c diff --git a/MAINTAINERS b/MAINTAINERS index 195cf1ac2ee8..40c717f93c1a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -10689,6 +10689,7 @@ F: drivers/tty/serial/kgdboc.c F: include/linux/kdb.h F: include/linux/kgdb.h F: kernel/debug/ +F: kernel/module/kdb.c KHADAS MCU MFD DRIVER M: Neil Armstrong diff --git a/include/linux/kdb.h b/include/linux/kdb.h index ea0f5e580fac..07dfb6a20a1c 100644 --- a/include/linux/kdb.h +++ b/include/linux/kdb.h @@ -222,5 +222,6 @@ enum { extern int kdbgetintenv(const char *, int *); extern int kdb_set(int, const char **); +int kdb_lsmod(int argc, const char **argv); #endif /* !_KDB_H */ diff --git a/kernel/debug/kdb/kdb_io.c b/kernel/debug/kdb/kdb_io.c index 6735ac36b718..67d3c48a1522 100644 --- a/kernel/debug/kdb/kdb_io.c +++ b/kernel/debug/kdb/kdb_io.c @@ -9,7 +9,6 @@ * Copyright (c) 2009 Wind River Systems, Inc. All Rights Reserved. */ -#include #include #include #include diff --git a/kernel/debug/kdb/kdb_keyboard.c b/kernel/debug/kdb/kdb_keyboard.c index f877a0a0d7cf..f87c750d3eb3 100644 --- a/kernel/debug/kdb/kdb_keyboard.c +++ b/kernel/debug/kdb/kdb_keyboard.c @@ -11,7 +11,6 @@ #include #include #include -#include #include /* Keyboard Controller Registers on normal PCs. */ diff --git a/kernel/debug/kdb/kdb_main.c b/kernel/debug/kdb/kdb_main.c index 0852a537dad4..f3a30cd5037f 100644 --- a/kernel/debug/kdb/kdb_main.c +++ b/kernel/debug/kdb/kdb_main.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include #include @@ -2004,54 +2003,6 @@ static int kdb_ef(int argc, const char **argv) return 0; } -#if defined(CONFIG_MODULES) -/* - * kdb_lsmod - This function implements the 'lsmod' command. Lists - * currently loaded kernel modules. - * Mostly taken from userland lsmod. - */ -static int kdb_lsmod(int argc, const char **argv) -{ - struct module *mod; - - if (argc != 0) - return KDB_ARGCOUNT; - - kdb_printf("Module Size modstruct Used by\n"); - list_for_each_entry(mod, kdb_modules, list) { - if (mod->state == MODULE_STATE_UNFORMED) - continue; - - kdb_printf("%-20s%8u 0x%px ", mod->name, - mod->core_layout.size, (void *)mod); -#ifdef CONFIG_MODULE_UNLOAD - kdb_printf("%4d ", module_refcount(mod)); -#endif - if (mod->state == MODULE_STATE_GOING) - kdb_printf(" (Unloading)"); - else if (mod->state == MODULE_STATE_COMING) - kdb_printf(" (Loading)"); - else - kdb_printf(" (Live)"); - kdb_printf(" 0x%px", mod->core_layout.base); - -#ifdef CONFIG_MODULE_UNLOAD - { - struct module_use *use; - kdb_printf(" [ "); - list_for_each_entry(use, &mod->source_list, - source_list) - kdb_printf("%s ", use->target->name); - kdb_printf("]\n"); - } -#endif - } - - return 0; -} - -#endif /* CONFIG_MODULES */ - /* * kdb_env - This function implements the 'env' command. Display the * current environment variables. diff --git a/kernel/debug/kdb/kdb_private.h b/kernel/debug/kdb/kdb_private.h index 0d2f9feea0a4..1f8c519a5f81 100644 --- a/kernel/debug/kdb/kdb_private.h +++ b/kernel/debug/kdb/kdb_private.h @@ -226,10 +226,6 @@ extern void kdb_kbd_cleanup_state(void); #define kdb_kbd_cleanup_state() #endif /* ! CONFIG_KDB_KEYBOARD */ -#ifdef CONFIG_MODULES -extern struct list_head *kdb_modules; -#endif /* CONFIG_MODULES */ - extern char kdb_prompt_str[]; #define KDB_WORD_SIZE ((int)sizeof(unsigned long)) diff --git a/kernel/debug/kdb/kdb_support.c b/kernel/debug/kdb/kdb_support.c index df2bface866e..08229ffb6b5e 100644 --- a/kernel/debug/kdb/kdb_support.c +++ b/kernel/debug/kdb/kdb_support.c @@ -17,7 +17,6 @@ #include #include #include -#include #include #include #include diff --git a/kernel/module/Makefile b/kernel/module/Makefile index cf8dcdc6b55f..88f5cdcdb067 100644 --- a/kernel/module/Makefile +++ b/kernel/module/Makefile @@ -17,3 +17,4 @@ obj-$(CONFIG_DEBUG_KMEMLEAK) += debug_kmemleak.o obj-$(CONFIG_KALLSYMS) += kallsyms.o obj-$(CONFIG_PROC_FS) += procfs.o obj-$(CONFIG_SYSFS) += sysfs.o +obj-$(CONFIG_KGDB_KDB) += kdb.o diff --git a/kernel/module/kdb.c b/kernel/module/kdb.c new file mode 100644 index 000000000000..a446c699db0a --- /dev/null +++ b/kernel/module/kdb.c @@ -0,0 +1,56 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Module kdb support + * + * Copyright (C) 2010 Jason Wessel + */ + +#include +#include +#include "internal.h" + +/* + * kdb_lsmod - This function implements the 'lsmod' command. Lists + * currently loaded kernel modules. + * Mostly taken from userland lsmod. + */ +int kdb_lsmod(int argc, const char **argv) +{ + struct module *mod; + + if (argc != 0) + return KDB_ARGCOUNT; + + kdb_printf("Module Size modstruct Used by\n"); + list_for_each_entry(mod, &modules, list) { + if (mod->state == MODULE_STATE_UNFORMED) + continue; + + kdb_printf("%-20s%8u 0x%px ", mod->name, + mod->core_layout.size, (void *)mod); +#ifdef CONFIG_MODULE_UNLOAD + kdb_printf("%4d ", module_refcount(mod)); +#endif + if (mod->state == MODULE_STATE_GOING) + kdb_printf(" (Unloading)"); + else if (mod->state == MODULE_STATE_COMING) + kdb_printf(" (Loading)"); + else + kdb_printf(" (Live)"); + kdb_printf(" 0x%px", mod->core_layout.base); + +#ifdef CONFIG_MODULE_UNLOAD + { + struct module_use *use; + + kdb_printf(" [ "); + list_for_each_entry(use, &mod->source_list, + source_list) + kdb_printf("%s ", use->target->name); + kdb_printf("]\n"); + } +#endif + } + + return 0; +} diff --git a/kernel/module/main.c b/kernel/module/main.c index b8a59b5c3e3a..bcc4f7a82649 100644 --- a/kernel/module/main.c +++ b/kernel/module/main.c @@ -108,10 +108,6 @@ static void mod_update_bounds(struct module *mod) __mod_update_bounds(mod->init_layout.base, mod->init_layout.size); } -#ifdef CONFIG_KGDB_KDB -struct list_head *kdb_modules = &modules; /* kdb needs the list of modules */ -#endif /* CONFIG_KGDB_KDB */ - static void module_assert_mutex_or_preempt(void) { #ifdef CONFIG_LOCKDEP From patchwork Thu Mar 10 10:26:25 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aaron Tomlin X-Patchwork-Id: 12776135 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id ABCCEC433EF for ; Thu, 10 Mar 2022 10:27:07 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236886AbiCJK2G (ORCPT ); Thu, 10 Mar 2022 05:28:06 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47438 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237904AbiCJK1i (ORCPT ); Thu, 10 Mar 2022 05:27:38 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id C0E9413DE3C for ; Thu, 10 Mar 2022 02:26:35 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1646907995; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=SiYMP4DA9TozF4xuyhOCEQgRS/pjqscFIVWb9t8F7R4=; b=Nz/j69XdzGRzuOboaHcr6VYZ573JYht+81VvNLMUvs8BcHignIdFidnKdQngmzcXuzB0D1 qpAd1LyPDBxpvrH1FtWpKguXdX8QLmSgvqvge/NQHf8Q/3Dpruw16ahPg+jPlCO0g4EJOU +6/1Gu80XwoRkbsBm9jRNw7R7ebxIQY= Received: from mail-wm1-f71.google.com (mail-wm1-f71.google.com [209.85.128.71]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-644-pnrIY9ocOPiGi_sGLfVGiQ-1; Thu, 10 Mar 2022 05:26:34 -0500 X-MC-Unique: pnrIY9ocOPiGi_sGLfVGiQ-1 Received: by mail-wm1-f71.google.com with SMTP id t2-20020a7bc3c2000000b003528fe59cb9so2110519wmj.5 for ; Thu, 10 Mar 2022 02:26:33 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=SiYMP4DA9TozF4xuyhOCEQgRS/pjqscFIVWb9t8F7R4=; b=ERIZKqOulFIiEl6I75xpw9mhk4XLl420Hm1lVRnGgvgC6JOKznZK+PSnB9FYkO39zp 7zbEBBYXhzXxJ2cCPJm5lVO+sHtn3Kei2yK7tMzXCxGq4VXnDepb+73hW69/6mqgDLLY 3oYd+Iejf2gPlMoaT1ZOBNT54+QxkZzQpNlynA5HIncRq7bpMkIjB9tvNIASSRxhej/y BIH3ONET5jSzGjvDHyuqjeijQLZbvFb4XwLSmQOBXkIxtc6ZiIkNo8FCctiJcr1Npbzb GPLtr9i4aLNdOP/5tsQ+rTeV7Cri3RM3C8vucSKZiByli6ML3YtU1XeRrzz5TR+wHIty HPTg== X-Gm-Message-State: AOAM530Ohf+zSsBe7a+XhkuTXbVt3fACxRN5WCNVUfPwfDD9lAzQyE2+ 2EJIAXu/AF9yz8NdY9Ldp6kmYkITQlCCbSntWCBTmpeUuwlK8yMQfmVLGIMc27OBsMAp5QfosGq mayPPTdIdONaDq2ABRgUzBxE4 X-Received: by 2002:a05:6000:1449:b0:1fc:a870:4b85 with SMTP id v9-20020a056000144900b001fca8704b85mr2921185wrx.639.1646907992542; Thu, 10 Mar 2022 02:26:32 -0800 (PST) X-Google-Smtp-Source: ABdhPJx8AyaX1c3nqNbd1JC/xs70TfJRRJmJwKa6/Gw6WGEaralc3eMV0ipJ3kU7lYRUpiamxwzjgQ== X-Received: by 2002:a05:6000:1449:b0:1fc:a870:4b85 with SMTP id v9-20020a056000144900b001fca8704b85mr2921172wrx.639.1646907992275; Thu, 10 Mar 2022 02:26:32 -0800 (PST) Received: from localhost (cpc111743-lutn13-2-0-cust979.9-3.cable.virginm.net. [82.17.115.212]) by smtp.gmail.com with ESMTPSA id o7-20020a5d6707000000b001f067c7b47fsm6110460wru.27.2022.03.10.02.26.30 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 10 Mar 2022 02:26:31 -0800 (PST) From: Aaron Tomlin To: mcgrof@kernel.org, christophe.leroy@csgroup.eu Cc: cl@linux.com, mbenes@suse.cz, akpm@linux-foundation.org, jeyu@kernel.org, linux-kernel@vger.kernel.org, linux-modules@vger.kernel.org, void@manifault.com, atomlin@atomlin.com, allen.lkml@gmail.com, joe@perches.com, msuchanek@suse.de, oleksandr@natalenko.name, jason.wessel@windriver.com, pmladek@suse.com, daniel.thompson@linaro.org, hch@infradead.org Subject: [PATCH v11 14/14] module: Move version support into a separate file Date: Thu, 10 Mar 2022 10:26:25 +0000 Message-Id: <20220310102625.3441888-3-atomlin@redhat.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220310102625.3441888-1-atomlin@redhat.com> References: <20220310102413.3438665-1-atomlin@redhat.com> <20220310102625.3441888-1-atomlin@redhat.com> MIME-Version: 1.0 Precedence: bulk List-ID: No functional change. This patch migrates module version support out of core code into kernel/module/version.c. In addition simple code refactoring to make this possible. Reviewed-by: Christophe Leroy Signed-off-by: Aaron Tomlin --- kernel/module/Makefile | 1 + kernel/module/internal.h | 48 ++++++++++++ kernel/module/main.c | 156 ++------------------------------------- kernel/module/version.c | 109 +++++++++++++++++++++++++++ 4 files changed, 166 insertions(+), 148 deletions(-) create mode 100644 kernel/module/version.c diff --git a/kernel/module/Makefile b/kernel/module/Makefile index 88f5cdcdb067..e2eff9853a28 100644 --- a/kernel/module/Makefile +++ b/kernel/module/Makefile @@ -18,3 +18,4 @@ obj-$(CONFIG_KALLSYMS) += kallsyms.o obj-$(CONFIG_PROC_FS) += procfs.o obj-$(CONFIG_SYSFS) += sysfs.o obj-$(CONFIG_KGDB_KDB) += kdb.o +obj-$(CONFIG_MODVERSIONS) += version.o diff --git a/kernel/module/internal.h b/kernel/module/internal.h index 62d749ef695e..3fc139d5074b 100644 --- a/kernel/module/internal.h +++ b/kernel/module/internal.h @@ -70,7 +70,27 @@ struct load_info { } index; }; +enum mod_license { + NOT_GPL_ONLY, + GPL_ONLY, +}; + +struct find_symbol_arg { + /* Input */ + const char *name; + bool gplok; + bool warn; + + /* Output */ + struct module *owner; + const s32 *crc; + const struct kernel_symbol *sym; + enum mod_license license; +}; + int mod_verify_sig(const void *mod, struct load_info *info); +int try_to_force_load(struct module *mod, const char *reason); +bool find_symbol(struct find_symbol_arg *fsa); struct module *find_module_all(const char *name, size_t len, bool even_unformed); int cmp_name(const void *name, const void *sym); long module_get_offset(struct module *mod, unsigned int *size, Elf_Shdr *sechdr, @@ -225,3 +245,31 @@ static inline int mod_sysfs_setup(struct module *mod, static inline void mod_sysfs_teardown(struct module *mod) { } static inline void init_param_lock(struct module *mod) { } #endif /* CONFIG_SYSFS */ + +#ifdef CONFIG_MODVERSIONS +int check_version(const struct load_info *info, + const char *symname, struct module *mod, const s32 *crc); +void module_layout(struct module *mod, struct modversion_info *ver, struct kernel_param *kp, + struct kernel_symbol *ks, struct tracepoint * const *tp); +int check_modstruct_version(const struct load_info *info, struct module *mod); +int same_magic(const char *amagic, const char *bmagic, bool has_crcs); +#else /* !CONFIG_MODVERSIONS */ +static inline int check_version(const struct load_info *info, + const char *symname, + struct module *mod, + const s32 *crc) +{ + return 1; +} + +static inline int check_modstruct_version(const struct load_info *info, + struct module *mod) +{ + return 1; +} + +static inline int same_magic(const char *amagic, const char *bmagic, bool has_crcs) +{ + return strcmp(amagic, bmagic) == 0; +} +#endif /* CONFIG_MODVERSIONS */ diff --git a/kernel/module/main.c b/kernel/module/main.c index bcc4f7a82649..0749afdc34b5 100644 --- a/kernel/module/main.c +++ b/kernel/module/main.c @@ -86,6 +86,12 @@ struct mod_tree_root mod_tree __cacheline_aligned = { static unsigned long module_addr_min = -1UL, module_addr_max; #endif /* CONFIG_MODULES_TREE_LOOKUP */ +struct symsearch { + const struct kernel_symbol *start, *stop; + const s32 *crcs; + enum mod_license license; +}; + /* * Bounds of module text, for speeding up __module_address. * Protected by module_mutex. @@ -244,28 +250,6 @@ static __maybe_unused void *any_section_objs(const struct load_info *info, #define symversion(base, idx) ((base != NULL) ? ((base) + (idx)) : NULL) #endif -struct symsearch { - const struct kernel_symbol *start, *stop; - const s32 *crcs; - enum mod_license { - NOT_GPL_ONLY, - GPL_ONLY, - } license; -}; - -struct find_symbol_arg { - /* Input */ - const char *name; - bool gplok; - bool warn; - - /* Output */ - struct module *owner; - const s32 *crc; - const struct kernel_symbol *sym; - enum mod_license license; -}; - static bool check_exported_symbol(const struct symsearch *syms, struct module *owner, unsigned int symnum, void *data) @@ -327,7 +311,7 @@ static bool find_exported_symbol_in_section(const struct symsearch *syms, * Find an exported symbol and return it, along with, (optional) crc and * (optional) module which owns it. Needs preempt disabled or module_mutex. */ -static bool find_symbol(struct find_symbol_arg *fsa) +bool find_symbol(struct find_symbol_arg *fsa) { static const struct symsearch arr[] = { { __start___ksymtab, __stop___ksymtab, __start___kcrctab, @@ -1001,7 +985,7 @@ size_t modinfo_attrs_count = ARRAY_SIZE(modinfo_attrs); static const char vermagic[] = VERMAGIC_STRING; -static int try_to_force_load(struct module *mod, const char *reason) +int try_to_force_load(struct module *mod, const char *reason) { #ifdef CONFIG_MODULE_FORCE_LOAD if (!test_taint(TAINT_FORCED_MODULE)) @@ -1013,115 +997,6 @@ static int try_to_force_load(struct module *mod, const char *reason) #endif } -#ifdef CONFIG_MODVERSIONS - -static u32 resolve_rel_crc(const s32 *crc) -{ - return *(u32 *)((void *)crc + *crc); -} - -static int check_version(const struct load_info *info, - const char *symname, - struct module *mod, - const s32 *crc) -{ - Elf_Shdr *sechdrs = info->sechdrs; - unsigned int versindex = info->index.vers; - unsigned int i, num_versions; - struct modversion_info *versions; - - /* Exporting module didn't supply crcs? OK, we're already tainted. */ - if (!crc) - return 1; - - /* No versions at all? modprobe --force does this. */ - if (versindex == 0) - return try_to_force_load(mod, symname) == 0; - - versions = (void *) sechdrs[versindex].sh_addr; - num_versions = sechdrs[versindex].sh_size - / sizeof(struct modversion_info); - - for (i = 0; i < num_versions; i++) { - u32 crcval; - - if (strcmp(versions[i].name, symname) != 0) - continue; - - if (IS_ENABLED(CONFIG_MODULE_REL_CRCS)) - crcval = resolve_rel_crc(crc); - else - crcval = *crc; - if (versions[i].crc == crcval) - return 1; - pr_debug("Found checksum %X vs module %lX\n", - crcval, versions[i].crc); - goto bad_version; - } - - /* Broken toolchain. Warn once, then let it go.. */ - pr_warn_once("%s: no symbol version for %s\n", info->name, symname); - return 1; - -bad_version: - pr_warn("%s: disagrees about version of symbol %s\n", - info->name, symname); - return 0; -} - -static inline int check_modstruct_version(const struct load_info *info, - struct module *mod) -{ - struct find_symbol_arg fsa = { - .name = "module_layout", - .gplok = true, - }; - - /* - * Since this should be found in kernel (which can't be removed), no - * locking is necessary -- use preempt_disable() to placate lockdep. - */ - preempt_disable(); - if (!find_symbol(&fsa)) { - preempt_enable(); - BUG(); - } - preempt_enable(); - return check_version(info, "module_layout", mod, fsa.crc); -} - -/* First part is kernel version, which we ignore if module has crcs. */ -static inline int same_magic(const char *amagic, const char *bmagic, - bool has_crcs) -{ - if (has_crcs) { - amagic += strcspn(amagic, " "); - bmagic += strcspn(bmagic, " "); - } - return strcmp(amagic, bmagic) == 0; -} -#else -static inline int check_version(const struct load_info *info, - const char *symname, - struct module *mod, - const s32 *crc) -{ - return 1; -} - -static inline int check_modstruct_version(const struct load_info *info, - struct module *mod) -{ - return 1; -} - -static inline int same_magic(const char *amagic, const char *bmagic, - bool has_crcs) -{ - return strcmp(amagic, bmagic) == 0; -} -#endif /* CONFIG_MODVERSIONS */ - static char *get_modinfo(const struct load_info *info, const char *tag); static char *get_next_modinfo(const struct load_info *info, const char *tag, char *prev); @@ -3247,18 +3122,3 @@ void print_modules(void) pr_cont(" [last unloaded: %s]", last_unloaded_module); pr_cont("\n"); } - -#ifdef CONFIG_MODVERSIONS -/* - * Generate the signature for all relevant module structures here. - * If these change, we don't want to try to parse the module. - */ -void module_layout(struct module *mod, - struct modversion_info *ver, - struct kernel_param *kp, - struct kernel_symbol *ks, - struct tracepoint * const *tp) -{ -} -EXPORT_SYMBOL(module_layout); -#endif diff --git a/kernel/module/version.c b/kernel/module/version.c new file mode 100644 index 000000000000..adaedce1dc97 --- /dev/null +++ b/kernel/module/version.c @@ -0,0 +1,109 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Module version support + * + * Copyright (C) 2008 Rusty Russell + */ + +#include +#include +#include +#include "internal.h" + +static u32 resolve_rel_crc(const s32 *crc) +{ + return *(u32 *)((void *)crc + *crc); +} + +int check_version(const struct load_info *info, + const char *symname, + struct module *mod, + const s32 *crc) +{ + Elf_Shdr *sechdrs = info->sechdrs; + unsigned int versindex = info->index.vers; + unsigned int i, num_versions; + struct modversion_info *versions; + + /* Exporting module didn't supply crcs? OK, we're already tainted. */ + if (!crc) + return 1; + + /* No versions at all? modprobe --force does this. */ + if (versindex == 0) + return try_to_force_load(mod, symname) == 0; + + versions = (void *)sechdrs[versindex].sh_addr; + num_versions = sechdrs[versindex].sh_size + / sizeof(struct modversion_info); + + for (i = 0; i < num_versions; i++) { + u32 crcval; + + if (strcmp(versions[i].name, symname) != 0) + continue; + + if (IS_ENABLED(CONFIG_MODULE_REL_CRCS)) + crcval = resolve_rel_crc(crc); + else + crcval = *crc; + if (versions[i].crc == crcval) + return 1; + pr_debug("Found checksum %X vs module %lX\n", + crcval, versions[i].crc); + goto bad_version; + } + + /* Broken toolchain. Warn once, then let it go.. */ + pr_warn_once("%s: no symbol version for %s\n", info->name, symname); + return 1; + +bad_version: + pr_warn("%s: disagrees about version of symbol %s\n", info->name, symname); + return 0; +} + +int check_modstruct_version(const struct load_info *info, + struct module *mod) +{ + struct find_symbol_arg fsa = { + .name = "module_layout", + .gplok = true, + }; + + /* + * Since this should be found in kernel (which can't be removed), no + * locking is necessary -- use preempt_disable() to placate lockdep. + */ + preempt_disable(); + if (!find_symbol(&fsa)) { + preempt_enable(); + BUG(); + } + preempt_enable(); + return check_version(info, "module_layout", mod, fsa.crc); +} + +/* First part is kernel version, which we ignore if module has crcs. */ +int same_magic(const char *amagic, const char *bmagic, + bool has_crcs) +{ + if (has_crcs) { + amagic += strcspn(amagic, " "); + bmagic += strcspn(bmagic, " "); + } + return strcmp(amagic, bmagic) == 0; +} + +/* + * Generate the signature for all relevant module structures here. + * If these change, we don't want to try to parse the module. + */ +void module_layout(struct module *mod, + struct modversion_info *ver, + struct kernel_param *kp, + struct kernel_symbol *ks, + struct tracepoint * const *tp) +{ +} +EXPORT_SYMBOL(module_layout);