From patchwork Tue Oct 18 06:09:51 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AKASHI Takahiro X-Patchwork-Id: 77918 Delivered-To: patch@linaro.org Received: by 10.140.97.247 with SMTP id m110csp721904qge; Mon, 17 Oct 2016 23:02:10 -0700 (PDT) X-Received: by 10.99.126.11 with SMTP id z11mr1561149pgc.46.1476770530743; Mon, 17 Oct 2016 23:02:10 -0700 (PDT) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id 3si30531694pgb.311.2016.10.17.23.02.10; Mon, 17 Oct 2016 23:02:10 -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=@linaro.org; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1758178AbcJRGCH (ORCPT + 27 others); Tue, 18 Oct 2016 02:02:07 -0400 Received: from mail-pf0-f180.google.com ([209.85.192.180]:36174 "EHLO mail-pf0-f180.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755507AbcJRGB4 (ORCPT ); Tue, 18 Oct 2016 02:01:56 -0400 Received: by mail-pf0-f180.google.com with SMTP id e6so88329118pfk.3 for ; Mon, 17 Oct 2016 23:01:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=date:from:to:subject:message-id:mail-followup-to:mime-version :content-disposition:user-agent; bh=OAriAa3AyCsRpZYFGfcv27KlpZRrNpmuQJP1CnuJhJ8=; b=EOkeE0zDwtiiONYmqh0qM+ycTVkCDgSlBaySJdF7WI4/y1zcyzFKV+g2In2OVt4UaA OV0Iaw/2dc3LYuVqEz6wXdQMVVPHbYL5i4mBu0HhJZb4vfbjtlq5PqKjNgX3/tp7EiFR qcfqdU1h+YASwWIlHR5G+YyKHe/+JAenTb2n8= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:date:from:to:subject:message-id:mail-followup-to :mime-version:content-disposition:user-agent; bh=OAriAa3AyCsRpZYFGfcv27KlpZRrNpmuQJP1CnuJhJ8=; b=UUB9dPdl2umdgLy1Npg0bBYRGMHzv+9ni3yhAe25e96KItI1M8qbiMZA2E1wxAtcnx oTPsL6Wzmxuh+v+gqdduGE16xyyXtwmVXgts1MZgqH9cEz+aXifbyVLA+9+PnFgQ6q1D IVPg9xlF2+4lQMUhiRSFcMJIMWzAA6/aqK9ayU4tAQAQLMfzIXGBvAlOnbBMq1w5MVIZ 9ElbzIfyEXas1OIoB+DIQH/YtglwTKOLOM/T4xK3RYIjV8iXGkRGINaJWu+uFbRzB4vc wTe4SHur3FFxoL1sUq1VVQpFJsvUbeqlFWkuhkUZImSqbYEbfbeHGsizHjy+puSI2lMp X/Kw== X-Gm-Message-State: AA6/9RlZE8fjVf58LS8bO4a1IUOKYDZGCA/7v9IDGcMS/tNwIaDUFjEbS0K3rYo3vgHnvvqi X-Received: by 10.99.98.5 with SMTP id w5mr1498245pgb.77.1476770515143; Mon, 17 Oct 2016 23:01:55 -0700 (PDT) Received: from linaro.org ([121.95.100.191]) by smtp.googlemail.com with ESMTPSA id o82sm52295569pfk.24.2016.10.17.23.01.53 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 17 Oct 2016 23:01:54 -0700 (PDT) Date: Tue, 18 Oct 2016 15:09:51 +0900 From: AKASHI Takahiro To: kernel-hardening@lists.openwall.com, linux-kernel@vger.kernel.org Subject: [RFC] module: add 'module_ronx=off' boot cmdline parameter to disable ro/nx module mappings Message-ID: <20161018060950.GM19531@linaro.org> Mail-Followup-To: AKASHI Takahiro , kernel-hardening@lists.openwall.com, linux-kernel@vger.kernel.org MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.24 (2015-08-30) Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org As making CONFIG_DEBUG_RODATA mandatory is a good idea, so will be for CONFIG_SET_MODULE_RONX. This patch adds a command line parameter, "module_ronx=," in order to make this configuration always on in the future, but still allowing for disabling read-only module mappings at boot time as "rodata=" does. I have, however, some concerns on this prototype: (1) should we use a separate parameter like "module_ronx=," or unify it with "rodata="? (2) should we keep NX permission set even if module_ronx=off? I tested this patch with: - insmod lkdtm.ko cpoint_name=DIRECT cpoint_type="WRITE_KERN" - insmod lkdtm.ko cpoint_name=DIRECT cpoint_type="WRITE_RO" - insmod lkdtm.ko cpoint_name=DIRECT cpoint_type="EXEC_DATA" WRITE_RO_AFTER_INIT case doesn't fail because the test is executed *before* setting the ro_after_init data ro. Any comments are welcome. Thanks, -Takahiro AKASHI -- 2.10.0 ===8<=== >From aeb6bcdbe462251f5aab828ba58f2f64e9c51d69 Mon Sep 17 00:00:00 2001 From: AKASHI Takahiro Date: Thu, 13 Oct 2016 14:39:20 +0900 Subject: [RFC] module: add 'module_ronx=off' boot cmdline parameter to disable ro/nx module mappings "module_ronx=off" allows for writing to read-only module text as well as executing any code in data section (as if !CONFIG_SET_MODULE_RONX). It corresponds to the kernel patch: commit d2aa1acad22f ("mm/init: Add 'rodata=off' boot cmdline parameter to disable read-only kernel mappings") Signed-off-by: AKASHI Takahiro --- kernel/module.c | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/kernel/module.c b/kernel/module.c index f57dd63..cc75ad6 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -1855,6 +1855,9 @@ static void mod_sysfs_teardown(struct module *mod) } #ifdef CONFIG_DEBUG_SET_MODULE_RONX +static bool module_ronx_enabled = true; +core_param(module_ronx, module_ronx_enabled, bool, 0); + /* * LKM RO/NX protection: protect module's text/ro-data * from modification and any data from execution. @@ -1989,6 +1992,8 @@ static void disable_ro_nx(const struct module_layout *layout) } #else +#define module_ronx_enabled false + 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) { } @@ -2124,7 +2129,8 @@ 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); + if (module_ronx_enabled) + disable_ro_nx(&mod->init_layout); module_arch_freeing_init(mod); module_memfree(mod->init_layout.base); kfree(mod->args); @@ -2134,7 +2140,8 @@ 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); + if (module_ronx_enabled) + disable_ro_nx(&mod->core_layout); module_memfree(mod->core_layout.base); #ifdef CONFIG_MPU @@ -3428,9 +3435,11 @@ static noinline int do_init_module(struct module *mod) /* Switch to core kallsyms now init is done: kallsyms may be walking! */ rcu_assign_pointer(mod->kallsyms, &mod->core_kallsyms); #endif - module_enable_ro(mod, true); + if (module_ronx_enabled) + module_enable_ro(mod, true); mod_tree_remove_init(mod); - disable_ro_nx(&mod->init_layout); + if (module_ronx_enabled) + disable_ro_nx(&mod->init_layout); module_arch_freeing_init(mod); mod->init_layout.base = NULL; mod->init_layout.size = 0; @@ -3527,8 +3536,10 @@ static int complete_formation(struct module *mod, struct load_info *info) /* This relies on module_mutex for list integrity. */ module_bug_finalize(info->hdr, info->sechdrs, mod); - module_enable_ro(mod, false); - module_enable_nx(mod); + if (module_ronx_enabled) { + module_enable_ro(mod, false); + module_enable_nx(mod); + } /* Mark state as coming so strong_try_module_get() ignores us, * but kallsyms etc. can see us. */ @@ -3718,8 +3729,10 @@ static int load_module(struct load_info *info, const char __user *uargs, mutex_unlock(&module_mutex); /* we can't deallocate the module until we clear memory protection */ - module_disable_ro(mod); - module_disable_nx(mod); + if (module_ronx_enabled) { + module_disable_ro(mod); + module_disable_nx(mod); + } ddebug_cleanup: dynamic_debug_remove(info->debug);