Received: by 2002:a05:6a10:1a4d:0:0:0:0 with SMTP id nk13csp2033817pxb; Wed, 9 Feb 2022 09:29:33 -0800 (PST) X-Google-Smtp-Source: ABdhPJy4Db6ebc0drzYtkTDAszEBd87jURS9Dn9YhasWo61gvwAktMyBWxpgdyi/3BtZMp5X4Yke X-Received: by 2002:a05:6402:42d4:: with SMTP id i20mr3732780edc.306.1644427773357; Wed, 09 Feb 2022 09:29:33 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1644427773; cv=none; d=google.com; s=arc-20160816; b=RHZSWWxoK7KX02oijqUq1SAAmGvYVb0EsIIbDFfHPViD5tWN4BI+OY4mSl5aiXqeGR yQlpcEKaj1uQMN/uqLKxjx/4+rSg4BMjSvZ4WRZ7M9hxesnjKmkuUCGqzc0jy3XQYMU1 /lvkXl4+evkPobq0IygYvg88aB66xAtDTyZyhbs4VX4XBq6vWpKhx/RKJIdKQq6CTVOZ Wv6ElL0TamkhfHcryj1ELonrIREjvOiUUpBh8KSRsW/IeIT6rFYTGXZ8SHPTc3DoS8PV qGaoNYJlRWJpC0NaL2zawHNMU91465/Ek06cPR3vFDSxnm2twPbZzDLeExqOEY+FUoOb +uxg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version:reply-to :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=kkXl+3Le8t36ks8/Z+YqaA7sB3u+HWYgsDZLTvpdTOo=; b=QSERH6/nKyXokjl0iUlLKfVf5FKKHm6mlzdhNxo7sNnqSeqFeWKb36WN6KoUyrYwpi QbD1ewp3rvmaevg6APaVtULM3dbmsL3uNdqaj1N+d8li16KzOTynygHmKjbu3qbWsfvR JNedNC2BssovP+qpqnvT8MuG26qZpEHzrooaKBaheTpJtsXgpozVM9tD7HXYoY5OY7Aw AhvdY5jlGHgHZOyVZtf5jsCw30mRY74yHHFQ9DApV5deZBAVqCbMiVzSNNC2jAxFe8fV cnus0YOaHWP8BDCOLWQXfw9VdvAm0T3idrA9JpfKOAp9KorphEk2/KwpFHUfwlbjhN7O QJiQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=B6cj4q4z; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id i10si12349151ejd.885.2022.02.09.09.29.04; Wed, 09 Feb 2022 09:29:33 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=B6cj4q4z; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237887AbiBIRL2 (ORCPT + 99 others); Wed, 9 Feb 2022 12:11:28 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45376 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237770AbiBIRLX (ORCPT ); Wed, 9 Feb 2022 12:11:23 -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 D9CADC05CB8C for ; Wed, 9 Feb 2022 09:11:25 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1644426685; h=from:from:reply-to: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=kkXl+3Le8t36ks8/Z+YqaA7sB3u+HWYgsDZLTvpdTOo=; b=B6cj4q4zFoRVhshlSUjIz1VvytHTiKO2su0+am/76DpmUlbHmhHvacAlEW1/uyiDZauqvX t9zXN6sToO7qOimJNOMLbA+EEqjz2VazYkJ4Fni+RvEM3fYqCk7t5dKnU9sebEMDloE0Hd blN8F3N8TDf0RUnBZ3NmhUuIlUoROEo= 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-377-mca5ajLRPtepZFoJs5m8tg-1; Wed, 09 Feb 2022 12:11:23 -0500 X-MC-Unique: mca5ajLRPtepZFoJs5m8tg-1 Received: by mail-wm1-f72.google.com with SMTP id m20-20020a05600c3b1400b003539593ea39so294472wms.0 for ; Wed, 09 Feb 2022 09:11: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:reply-to:mime-version:content-transfer-encoding; bh=kkXl+3Le8t36ks8/Z+YqaA7sB3u+HWYgsDZLTvpdTOo=; b=rtrAcyLG2XRCBdtfnCy0IBQA87PmaPsnpCrvgQ4NlC5FC8nwuUGuOuRJPLevm8kr+f dqA2z18jTgeBE35IaAHmj7V1d2xLSbowjc1a0DpajBolPxetJR/UvBAaGGdMVTNWfwv3 RT3Ve4JBOYanRSILywwkU1uUyHCUe5qzixIkV7TyBxRg1AB/6SfEe41lfEngSwA0GmA4 fzFJluzU6W8JJ9ZRq+6n+YvLWEvuYSpGoGRP7fnt8Cf+Z+Xmgu1ptJJsoLJA/uZdMOPE CcJ3OcbWzKjaXAWGcijThneU4/I5fQUjVenkiCNz3sxDWkMTrrPiPw5wHjjOakHaTJwd 7wlw== X-Gm-Message-State: AOAM5334Gkwm8dYtSDk77VGQgmvGyiLypFIxTzjbZCYOOPn+Ew0/aTBL ZcZh4GEP86SQ9QgSex1Hv+D3k2V03YzzXoR/8vQFuA88BmqYJ9Ps7Pnn0YPIZ08ETa/P6dHxZ/X ICQLmamC8DrPo/lHymwrXrH0= X-Received: by 2002:a7b:cbd7:: with SMTP id n23mr3534224wmi.76.1644426682504; Wed, 09 Feb 2022 09:11:22 -0800 (PST) X-Received: by 2002:a7b:cbd7:: with SMTP id n23mr3534206wmi.76.1644426682204; Wed, 09 Feb 2022 09:11: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 e15sm1494238wrg.6.2022.02.09.09.11.21 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 09 Feb 2022 09:11:21 -0800 (PST) From: Aaron Tomlin To: mcgrof@kernel.org Cc: cl@linux.com, pmladek@suse.com, mbenes@suse.cz, akpm@linux-foundation.org, jeyu@kernel.org, linux-kernel@vger.kernel.org, linux-modules@vger.kernel.org, live-patching@vger.kernel.org, atomlin@atomlin.com, ghalat@redhat.com, allen.lkml@gmail.com, void@manifault.com, joe@perches.com, christophe.leroy@csgroup.eu, msuchanek@suse.de, oleksandr@natalenko.name Subject: [PATCH v5 13/13] module: Move version support into a separate file Date: Wed, 9 Feb 2022 17:11:18 +0000 Message-Id: <20220209171118.3269581-3-atomlin@redhat.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220209171118.3269581-1-atomlin@redhat.com> References: <20220209171118.3269581-1-atomlin@redhat.com> Reply-To: 20220209170358.3266629-1-atomlin@redhat.com MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-2.8 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_LOW, SPF_HELO_NONE,SPF_NONE,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 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. Signed-off-by: Aaron Tomlin --- kernel/module/Makefile | 1 + kernel/module/internal.h | 50 +++++++++++++ kernel/module/main.c | 150 +-------------------------------------- kernel/module/version.c | 110 ++++++++++++++++++++++++++++ 4 files changed, 163 insertions(+), 148 deletions(-) create mode 100644 kernel/module/version.c diff --git a/kernel/module/Makefile b/kernel/module/Makefile index c30141c37eb3..1f111aa47e88 100644 --- a/kernel/module/Makefile +++ b/kernel/module/Makefile @@ -15,4 +15,5 @@ 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_MODVERSIONS) += version.o endif diff --git a/kernel/module/internal.h b/kernel/module/internal.h index c49b4900b30b..475a66aa42f2 100644 --- a/kernel/module/internal.h +++ b/kernel/module/internal.h @@ -71,7 +71,31 @@ struct load_info { } index; }; +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; +}; + 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); unsigned long kernel_symbol_value(const struct kernel_symbol *sym); int cmp_name(const void *name, const void *sym); @@ -231,3 +255,29 @@ static inline void module_remove_modinfo_attrs(struct module *mod, int end) { } static inline void del_usage_links(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); +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 519c5335f7a6..b65bf5f7d474 100644 --- a/kernel/module/main.c +++ b/kernel/module/main.c @@ -241,28 +241,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) @@ -333,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, @@ -1007,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)) @@ -1019,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); @@ -3263,18 +3132,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..10a1490d1b9e --- /dev/null +++ b/kernel/module/version.c @@ -0,0 +1,110 @@ +// 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; +} + +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. */ +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; +} + +/* + * 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); -- 2.34.1