|
|
Message-Id: <1531999889-18343-1-git-send-email-alex.popov@linux.com>
Date: Thu, 19 Jul 2018 14:31:29 +0300
From: Alexander Popov <alex.popov@...ux.com>
To: kernel-hardening@...ts.openwall.com,
Kees Cook <keescook@...omium.org>,
Kees Cook <keescook@...gle.com>,
PaX Team <pageexec@...email.hu>,
Brad Spengler <spender@...ecurity.net>,
Ingo Molnar <mingo@...nel.org>,
Andy Lutomirski <luto@...nel.org>,
Tycho Andersen <tycho@...ho.ws>,
Laura Abbott <labbott@...hat.com>,
Mark Rutland <mark.rutland@....com>,
Ard Biesheuvel <ard.biesheuvel@...aro.org>,
Borislav Petkov <bp@...en8.de>,
Richard Sandiford <richard.sandiford@....com>,
Thomas Gleixner <tglx@...utronix.de>,
"H . Peter Anvin" <hpa@...or.com>,
Peter Zijlstra <a.p.zijlstra@...llo.nl>,
"Dmitry V . Levin" <ldv@...linux.org>,
Emese Revfy <re.emese@...il.com>,
Jonathan Corbet <corbet@....net>,
Andrey Ryabinin <aryabinin@...tuozzo.com>,
"Kirill A . Shutemov" <kirill.shutemov@...ux.intel.com>,
Thomas Garnier <thgarnie@...gle.com>,
Andrew Morton <akpm@...ux-foundation.org>,
Alexei Starovoitov <ast@...nel.org>,
Josef Bacik <jbacik@...com>,
Masami Hiramatsu <mhiramat@...nel.org>,
Nicholas Piggin <npiggin@...il.com>,
Al Viro <viro@...iv.linux.org.uk>,
"David S . Miller" <davem@...emloft.net>,
Ding Tianhong <dingtianhong@...wei.com>,
David Woodhouse <dwmw@...zon.co.uk>,
Josh Poimboeuf <jpoimboe@...hat.com>,
Steven Rostedt <rostedt@...dmis.org>,
Dominik Brodowski <linux@...inikbrodowski.net>,
Juergen Gross <jgross@...e.com>,
Linus Torvalds <torvalds@...ux-foundation.org>,
Greg Kroah-Hartman <gregkh@...uxfoundation.org>,
Dan Williams <dan.j.williams@...el.com>,
Dave Hansen <dave.hansen@...ux.intel.com>,
Mathias Krause <minipli@...glemail.com>,
Vikas Shivappa <vikas.shivappa@...ux.intel.com>,
Kyle Huey <me@...ehuey.com>,
Dmitry Safonov <dsafonov@...tuozzo.com>,
Will Deacon <will.deacon@....com>,
Arnd Bergmann <arnd@...db.de>,
Florian Weimer <fweimer@...hat.com>,
Boris Lukashev <blukashev@...pervictus.com>,
Andrey Konovalov <andreyknvl@...gle.com>,
x86@...nel.org,
linux-kernel@...r.kernel.org,
alex.popov@...ux.com
Subject: [PATCH v14 7/7] stackleak, sysctl: Allow runtime disabling of kernel stack erasing
Introduce CONFIG_STACKLEAK_RUNTIME_DISABLE option, which provides
'stack_erasing_bypass' sysctl. It can be used in runtime to disable
kernel stack erasing for kernels built with CONFIG_GCC_PLUGIN_STACKLEAK.
Stack erasing will then remain disabled and STACKLEAK_METRICS will not
be updated until the next boot.
Signed-off-by: Alexander Popov <alex.popov@...ux.com>
---
Documentation/sysctl/kernel.txt | 19 +++++++++++++++++++
include/linux/stackleak.h | 6 ++++++
kernel/stackleak.c | 40 ++++++++++++++++++++++++++++++++++++++++
kernel/sysctl.c | 15 ++++++++++++++-
scripts/gcc-plugins/Kconfig | 10 ++++++++++
5 files changed, 89 insertions(+), 1 deletion(-)
diff --git a/Documentation/sysctl/kernel.txt b/Documentation/sysctl/kernel.txt
index eded671d..63b7493 100644
--- a/Documentation/sysctl/kernel.txt
+++ b/Documentation/sysctl/kernel.txt
@@ -87,6 +87,7 @@ show up in /proc/sys/kernel:
- shmmni
- softlockup_all_cpu_backtrace
- soft_watchdog
+- stack_erasing_bypass
- stop-a [ SPARC only ]
- sysrq ==> Documentation/admin-guide/sysrq.rst
- sysctl_writes_strict
@@ -962,6 +963,24 @@ detect a hard lockup condition.
==============================================================
+stack_erasing_bypass
+
+This parameter can be used to disable kernel stack erasing at the end
+of syscalls for kernels built with CONFIG_GCC_PLUGIN_STACKLEAK.
+
+That erasing reduces the information which kernel stack leak bugs
+can reveal and blocks some uninitialized stack variable attacks.
+The tradeoff is the performance impact: on a single CPU system kernel
+compilation sees a 1% slowdown, other systems and workloads may vary.
+
+ 0: do nothing - stack erasing is enabled by default.
+
+ 1: enable stack erasing bypass - stack erasing will then remain
+ disabled and STACKLEAK_METRICS will not be updated until the
+ next boot.
+
+==============================================================
+
tainted:
Non-zero if the kernel has been tainted. Numeric values, which can be
diff --git a/include/linux/stackleak.h b/include/linux/stackleak.h
index b911b97..e1fc3d1 100644
--- a/include/linux/stackleak.h
+++ b/include/linux/stackleak.h
@@ -22,6 +22,12 @@ static inline void stackleak_task_init(struct task_struct *t)
t->prev_lowest_stack = t->lowest_stack;
# endif
}
+
+#ifdef CONFIG_STACKLEAK_RUNTIME_DISABLE
+int stack_erasing_bypass_sysctl(struct ctl_table *table, int write,
+ void __user *buffer, size_t *lenp, loff_t *ppos);
+#endif
+
#else /* !CONFIG_GCC_PLUGIN_STACKLEAK */
static inline void stackleak_task_init(struct task_struct *t) { }
#endif
diff --git a/kernel/stackleak.c b/kernel/stackleak.c
index f5c4111..f731c9a 100644
--- a/kernel/stackleak.c
+++ b/kernel/stackleak.c
@@ -14,6 +14,36 @@
#include <linux/stackleak.h>
+#ifdef CONFIG_STACKLEAK_RUNTIME_DISABLE
+#include <linux/jump_label.h>
+
+static DEFINE_STATIC_KEY_FALSE(stack_erasing_bypass);
+
+int stack_erasing_bypass_sysctl(struct ctl_table *table, int write,
+ void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+ int ret = 0;
+ int state = static_branch_unlikely(&stack_erasing_bypass);
+
+ table->data = &state;
+ table->maxlen = sizeof(int);
+ ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
+ if (ret || !write)
+ return ret;
+
+ /* Stack erasing re-enabling is not supported */
+ if (static_branch_unlikely(&stack_erasing_bypass))
+ return -EOPNOTSUPP;
+
+ if (state) {
+ static_branch_enable(&stack_erasing_bypass);
+ pr_warn("stackleak: stack erasing is disabled until reboot\n");
+ }
+
+ return ret;
+}
+#endif /* CONFIG_STACKLEAK_RUNTIME_DISABLE */
+
asmlinkage void stackleak_erase(void)
{
/* It would be nice not to have 'kstack_ptr' and 'boundary' on stack */
@@ -22,6 +52,11 @@ asmlinkage void stackleak_erase(void)
unsigned int poison_count = 0;
const unsigned int depth = STACKLEAK_SEARCH_DEPTH / sizeof(unsigned long);
+#ifdef CONFIG_STACKLEAK_RUNTIME_DISABLE
+ if (static_branch_unlikely(&stack_erasing_bypass))
+ return;
+#endif
+
/* Search for the poison value in the kernel stack */
while (kstack_ptr > boundary && poison_count <= depth) {
if (*(unsigned long *)kstack_ptr == STACKLEAK_POISON)
@@ -78,6 +113,11 @@ void __used stackleak_track_stack(void)
*/
unsigned long sp = (unsigned long)&sp;
+#ifdef CONFIG_STACKLEAK_RUNTIME_DISABLE
+ if (static_branch_unlikely(&stack_erasing_bypass))
+ return;
+#endif
+
/*
* Having CONFIG_STACKLEAK_TRACK_MIN_SIZE larger than
* STACKLEAK_SEARCH_DEPTH makes the poison search in
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 2d9837c..0ac25ca 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -91,7 +91,9 @@
#ifdef CONFIG_CHR_DEV_SG
#include <scsi/sg.h>
#endif
-
+#ifdef CONFIG_STACKLEAK_RUNTIME_DISABLE
+#include <linux/stackleak.h>
+#endif
#ifdef CONFIG_LOCKUP_DETECTOR
#include <linux/nmi.h>
#endif
@@ -1230,6 +1232,17 @@ static struct ctl_table kern_table[] = {
.extra2 = &one,
},
#endif
+#ifdef CONFIG_STACKLEAK_RUNTIME_DISABLE
+ {
+ .procname = "stack_erasing_bypass",
+ .data = NULL,
+ .maxlen = sizeof(int),
+ .mode = 0600,
+ .proc_handler = stack_erasing_bypass_sysctl,
+ .extra1 = &zero,
+ .extra2 = &one,
+ },
+#endif
{ }
};
diff --git a/scripts/gcc-plugins/Kconfig b/scripts/gcc-plugins/Kconfig
index 292161d..0028945 100644
--- a/scripts/gcc-plugins/Kconfig
+++ b/scripts/gcc-plugins/Kconfig
@@ -182,4 +182,14 @@ config STACKLEAK_METRICS
can be useful for estimating the STACKLEAK performance impact for
your workloads.
+config STACKLEAK_RUNTIME_DISABLE
+ bool "Allow runtime disabling of kernel stack erasing"
+ depends on GCC_PLUGIN_STACKLEAK
+ help
+ This option provides 'stack_erasing_bypass' sysctl, which can be
+ used in runtime to disable kernel stack erasing for kernels built
+ with CONFIG_GCC_PLUGIN_STACKLEAK. Stack erasing will then remain
+ disabled and STACKLEAK_METRICS will not be updated until the
+ next boot.
+
endif
--
2.7.4
Powered by blists - more mailing lists
Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.