Received: by 2002:a25:4158:0:0:0:0:0 with SMTP id o85csp4787701yba; Tue, 30 Apr 2019 04:30:41 -0700 (PDT) X-Google-Smtp-Source: APXvYqxrLZ7+2nUJMAvAbc230xsQ6PK8NIPq1+RMWTHz+zX5OJVzmy5mVSydE9ESrzQ5KeFP3dDQ X-Received: by 2002:a62:5185:: with SMTP id f127mr70284993pfb.199.1556623840917; Tue, 30 Apr 2019 04:30:40 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1556623840; cv=none; d=google.com; s=arc-20160816; b=UpCm4I+7tiHvmuvPRv6DZz80Y4jLv+8MBO8/bX8C5hiLq0n5u0nl0zJX1x0rHLo25C YhsGndqiZlRB3tAxONdxdxGx0CbgWiUoPm8CFIvzMDhYbEiby6HKRsQmT16Wl/CMyXN8 mSd+B5x26esivZp+K8uZ1FDGIlMor732qoNh/xCxAHa8qS8gsN9++JCZPUtFV0fUVHed HkVTCOsjfA7pXEo2rZouVYdTTiijxhEQHbFvp5zYT9ByD35vMR6UkZzlVp+DLSlbDIWq NJfVOA2sSH76GzgeAr9oqeDuotnHb1Jb0ld4XXBqupN+wz8EmHD+MotVUQ0I28OT+4Cr R9RQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-disposition :content-transfer-encoding:mime-version:robot-unsubscribe:robot-id :git-commit-id:subject:to:references:in-reply-to:reply-to:cc :message-id:from:date:dkim-signature:dkim-filter; bh=xXyYrf0EgteWkvzKH3RVYTzxUw64JdnW8DeW9VS7Eag=; b=iOX8sNhi9x/u0z9J1jMQRAV34v7Ghw4royx4SVns8evLUQLLH9rE9YYFomjYa/w87M vhMbYnZE0FxNVffGW2gbk/Qz8LYEn6R/Qf69cRrZaHf8cpWe0oeAAZGkCcwc8GhIHCwQ 4KUwLkeRsQvxzyKoD8VJueVyhDJfC2s3KC0jHwilhpueKH2WMPsU/yVYLJGyn7eRGAhM hdU/pp5Nk25EkI+br0ShUsA7VSl6djf1PNucEAq7ZsjxzrbueL/O0DFSeFuIvsFUovDO hTP2Xsu989Q9rMTEal3tYEN7wCUYtw1W+0MVJYwKlmUBwt5T+vq15usjU5s013QqZYUO xTCQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@zytor.com header.s=2019041745 header.b=Rgl7WnTF; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=zytor.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id t16si20441586pgl.97.2019.04.30.04.30.20; Tue, 30 Apr 2019 04:30:40 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@zytor.com header.s=2019041745 header.b=Rgl7WnTF; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=zytor.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727781AbfD3L1z (ORCPT + 99 others); Tue, 30 Apr 2019 07:27:55 -0400 Received: from terminus.zytor.com ([198.137.202.136]:55623 "EHLO terminus.zytor.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726129AbfD3L1y (ORCPT ); Tue, 30 Apr 2019 07:27:54 -0400 Received: from terminus.zytor.com (localhost [127.0.0.1]) by terminus.zytor.com (8.15.2/8.15.2) with ESMTPS id x3UBQrkD1350079 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NO); Tue, 30 Apr 2019 04:26:54 -0700 DKIM-Filter: OpenDKIM Filter v2.11.0 terminus.zytor.com x3UBQrkD1350079 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=zytor.com; s=2019041745; t=1556623615; bh=xXyYrf0EgteWkvzKH3RVYTzxUw64JdnW8DeW9VS7Eag=; h=Date:From:Cc:Reply-To:In-Reply-To:References:To:Subject:From; b=Rgl7WnTFdskDNyv+HGJ4Ut7YMo4tfN4PZ5h5dIxnOP3HPo4TZzZED/RLjM7wpJGYp qcACMjZoMmnZ6WOkrCSVBJ/dP4exMt+ua7/gy7vtLPJzDxzvwzIBs5AdX8VKdwDV3n IZ9YB8j6yEsaQB78oVWXWWZHQdxulBCBg8fkY2RXdk+ECmtqCU91f6LPyEA3KPgqTX urGwmuz8Mj7PeEuFNv8DGG70n9I9P3L2OxCofFtDs74N9y+j+xfZQ+VP9F4MpiZxwz LoM1bt/gyz32PC6EweXVhWB5GMNWi/QvuuFmd8UyUKhXyO3eAzGx17IC9R59QPgIj/ 4l5/BhuOnh8Mg== Received: (from tipbot@localhost) by terminus.zytor.com (8.15.2/8.15.2/Submit) id x3UBQrch1350076; Tue, 30 Apr 2019 04:26:53 -0700 Date: Tue, 30 Apr 2019 04:26:53 -0700 X-Authentication-Warning: terminus.zytor.com: tipbot set sender to tipbot@zytor.com using -f From: tip-bot for Rick Edgecombe Message-ID: Cc: tglx@linutronix.de, bp@alien8.de, mingo@kernel.org, deneen.t.dock@intel.com, peterz@infradead.org, will.deacon@arm.com, linux_dti@icloud.com, linux-kernel@vger.kernel.org, kernel-hardening@lists.openwall.com, kristen@linux.intel.com, rostedt@goodmis.org, akpm@linux-foundation.org, dave.hansen@linux.intel.com, rick.p.edgecombe@intel.com, nadav.amit@gmail.com, ard.biesheuvel@linaro.org, luto@kernel.org, hpa@zytor.com, jeyu@kernel.org, torvalds@linux-foundation.org, riel@surriel.com Reply-To: kristen@linux.intel.com, akpm@linux-foundation.org, rostedt@goodmis.org, dave.hansen@linux.intel.com, nadav.amit@gmail.com, rick.p.edgecombe@intel.com, mingo@kernel.org, tglx@linutronix.de, bp@alien8.de, will.deacon@arm.com, deneen.t.dock@intel.com, peterz@infradead.org, linux-kernel@vger.kernel.org, kernel-hardening@lists.openwall.com, linux_dti@icloud.com, torvalds@linux-foundation.org, riel@surriel.com, ard.biesheuvel@linaro.org, luto@kernel.org, hpa@zytor.com, jeyu@kernel.org In-Reply-To: <20190426001143.4983-18-namit@vmware.com> References: <20190426001143.4983-18-namit@vmware.com> To: linux-tip-commits@vger.kernel.org Subject: [tip:x86/mm] modules: Use vmalloc special flag Git-Commit-ID: 1a7b7d9220819afe79d1ec5d759fe4349bd2453e X-Mailer: tip-git-log-daemon Robot-ID: Robot-Unsubscribe: Contact to get blacklisted from these emails MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Content-Type: text/plain; charset=UTF-8 Content-Disposition: inline X-Spam-Status: No, score=-1.0 required=5.0 tests=ALL_TRUSTED,BAYES_00, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF, FREEMAIL_FORGED_REPLYTO,T_DATE_IN_FUTURE_96_Q autolearn=no autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on terminus.zytor.com Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Commit-ID: 1a7b7d9220819afe79d1ec5d759fe4349bd2453e Gitweb: https://git.kernel.org/tip/1a7b7d9220819afe79d1ec5d759fe4349bd2453e Author: Rick Edgecombe AuthorDate: Thu, 25 Apr 2019 17:11:37 -0700 Committer: Ingo Molnar CommitDate: Tue, 30 Apr 2019 12:37:58 +0200 modules: Use vmalloc special flag Use new flag for handling freeing of special permissioned memory in vmalloc and remove places where memory was set RW before freeing which is no longer needed. Since freeing of VM_FLUSH_RESET_PERMS memory is not supported in an interrupt by vmalloc, the freeing of init sections is moved to a work queue. Instead of call_rcu it now uses synchronize_rcu() in the work queue. Lastly, there is now a WARN_ON in module_memfree since it should not be called in an interrupt with special memory as is required for VM_FLUSH_RESET_PERMS. Signed-off-by: Rick Edgecombe Signed-off-by: Peter Zijlstra (Intel) Cc: Cc: Cc: Cc: Cc: Cc: Cc: Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Dave Hansen Cc: H. Peter Anvin Cc: Jessica Yu Cc: Linus Torvalds Cc: Nadav Amit Cc: Rik van Riel Cc: Steven Rostedt Cc: Thomas Gleixner Link: https://lkml.kernel.org/r/20190426001143.4983-18-namit@vmware.com Signed-off-by: Ingo Molnar --- kernel/module.c | 77 +++++++++++++++++++++++++++++---------------------------- 1 file changed, 39 insertions(+), 38 deletions(-) diff --git a/kernel/module.c b/kernel/module.c index 2b2845ae983e..a9020bdd4cf6 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -98,6 +98,10 @@ DEFINE_MUTEX(module_mutex); EXPORT_SYMBOL_GPL(module_mutex); static LIST_HEAD(modules); +/* Work queue for freeing init sections in success case */ +static struct work_struct init_free_wq; +static struct llist_head init_free_list; + #ifdef CONFIG_MODULES_TREE_LOOKUP /* @@ -1949,6 +1953,8 @@ 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_text(&mod->core_layout, set_memory_x); @@ -1972,15 +1978,6 @@ static void module_enable_nx(const struct module *mod) frob_writable_data(&mod->init_layout, set_memory_nx); } -static void module_disable_nx(const struct module *mod) -{ - frob_rodata(&mod->core_layout, set_memory_x); - frob_ro_after_init(&mod->core_layout, set_memory_x); - frob_writable_data(&mod->core_layout, set_memory_x); - frob_rodata(&mod->init_layout, set_memory_x); - frob_writable_data(&mod->init_layout, set_memory_x); -} - /* Iterate through all modules and set each module's text as RW */ void set_all_modules_text_rw(void) { @@ -2024,23 +2021,8 @@ void set_all_modules_text_ro(void) } mutex_unlock(&module_mutex); } - -static void disable_ro_nx(const struct module_layout *layout) -{ - if (rodata_enabled) { - frob_text(layout, set_memory_rw); - frob_rodata(layout, set_memory_rw); - frob_ro_after_init(layout, set_memory_rw); - } - frob_rodata(layout, set_memory_x); - frob_ro_after_init(layout, set_memory_x); - frob_writable_data(layout, set_memory_x); -} - #else -static void disable_ro_nx(const struct module_layout *layout) { } static void module_enable_nx(const struct module *mod) { } -static void module_disable_nx(const struct module *mod) { } #endif #ifdef CONFIG_LIVEPATCH @@ -2120,6 +2102,11 @@ static void free_module_elf(struct module *mod) void __weak module_memfree(void *module_region) { + /* + * This memory may be RO, and freeing RO memory in an interrupt is not + * supported by vmalloc. + */ + WARN_ON(in_interrupt()); vfree(module_region); } @@ -2171,7 +2158,6 @@ static void free_module(struct module *mod) mutex_unlock(&module_mutex); /* This may be empty, but that's OK */ - disable_ro_nx(&mod->init_layout); module_arch_freeing_init(mod); module_memfree(mod->init_layout.base); kfree(mod->args); @@ -2181,7 +2167,6 @@ static void free_module(struct module *mod) lockdep_free_key_range(mod->core_layout.base, mod->core_layout.size); /* Finally, free the core (containing the module structure) */ - disable_ro_nx(&mod->core_layout); module_memfree(mod->core_layout.base); } @@ -3420,17 +3405,34 @@ static void do_mod_ctors(struct module *mod) /* For freeing module_init on success, in case kallsyms traversing */ struct mod_initfree { - struct rcu_head rcu; + struct llist_node node; void *module_init; }; -static void do_free_init(struct rcu_head *head) +static void do_free_init(struct work_struct *w) { - struct mod_initfree *m = container_of(head, struct mod_initfree, rcu); - module_memfree(m->module_init); - kfree(m); + struct llist_node *pos, *n, *list; + struct mod_initfree *initfree; + + list = llist_del_all(&init_free_list); + + synchronize_rcu(); + + llist_for_each_safe(pos, n, list) { + initfree = container_of(pos, struct mod_initfree, node); + module_memfree(initfree->module_init); + kfree(initfree); + } } +static int __init modules_wq_init(void) +{ + INIT_WORK(&init_free_wq, do_free_init); + init_llist_head(&init_free_list); + return 0; +} +module_init(modules_wq_init); + /* * This is where the real work happens. * @@ -3507,7 +3509,6 @@ static noinline int do_init_module(struct module *mod) #endif module_enable_ro(mod, true); mod_tree_remove_init(mod); - disable_ro_nx(&mod->init_layout); module_arch_freeing_init(mod); mod->init_layout.base = NULL; mod->init_layout.size = 0; @@ -3518,14 +3519,18 @@ static noinline int do_init_module(struct module *mod) * We want to free module_init, but be aware that kallsyms may be * walking this with preempt disabled. In all the failure paths, we * call synchronize_rcu(), but we don't want to slow down the success - * path, so use actual RCU here. + * path. module_memfree() cannot be called in an interrupt, so do the + * work and call synchronize_rcu() in a work queue. + * * Note that module_alloc() on most architectures creates W+X page * mappings which won't be cleaned up until do_free_init() runs. Any * code such as mark_rodata_ro() which depends on those mappings to * be cleaned up needs to sync with the queued work - ie * rcu_barrier() */ - call_rcu(&freeinit->rcu, do_free_init); + if (llist_add(&freeinit->node, &init_free_list)) + schedule_work(&init_free_wq); + mutex_unlock(&module_mutex); wake_up_all(&module_wq); @@ -3822,10 +3827,6 @@ static int load_module(struct load_info *info, const char __user *uargs, module_bug_cleanup(mod); mutex_unlock(&module_mutex); - /* we can't deallocate the module until we clear memory protection */ - module_disable_ro(mod); - module_disable_nx(mod); - ddebug_cleanup: ftrace_release_mod(mod); dynamic_debug_remove(mod, info->debug);