|
|
Message-ID: <CAGXu5jLcF_EHMtp+vb-zdjqKe+Z33ZKKVrx1FEVSXPyEEBa_qQ@mail.gmail.com>
Date: Fri, 9 Jun 2017 10:28:39 -0700
From: Kees Cook <keescook@...omium.org>
To: Alexander Popov <alex.popov@...ux.com>
Cc: "kernel-hardening@...ts.openwall.com" <kernel-hardening@...ts.openwall.com>, PaX Team <pageexec@...email.hu>,
Brad Spengler <spender@...ecurity.net>, Tycho Andersen <tycho@...ker.com>
Subject: Re: [PATCH RFC v2 1/1] gcc-plugins: Add stackleak feature erasing the
kernel stack at the end of syscalls
On Fri, Jun 9, 2017 at 7:30 AM, Alexander Popov <alex.popov@...ux.com> wrote:
> Hello,
>
> My employer Positive Technologies kindly allowed me to spend a part of my
> working time on helping KSPP. So I join the initiative of porting STACKLEAK
> to the mainline, which was started by Tycho Andersen.
Great, thanks for working on this!
> STACKLEAK is a security feature developed by Grsecurity/PaX (kudos to them!),
> which can mitigate the damage from kernel stack leak bugs (see CVE-2010-2963,
> CVE-2016-4569 and CVE-2016-4578).
It might help to distinguish that this covers at least two classes of
issues: stack content exposure (the latter two CVEs above), and it can
block some uninitialized variable attacks (like the mentioned
CVE-2010-2963). In other words, this can be more than just an info
exposure defense.
> I carefully extracted STACKLEAK from the last public patch of Grsecurity/PaX
> and do my best to understand it. So I added some comments describing that
> understanding. You are welcome to discuss it.
Great, adding more comments to the gcc plugin will help others who are
trying to get up to speed on it (like me). :)
> Here are the results of a brief performance test on x86_64:
>
> Hardware: Intel Core i7-4770, 16 GB RAM
>
> Test #1: stress-ng --cpu 4 --io 2 --vm 2 --vm-bytes 2G --timeout 300s
> --metrics-brief
> Result on 4.11-rc8:
> cpu bogo ops 269955
> iosync bogo ops 9809985
> vm bogo ops 17093608
> Result on 4.11-rc8+stackleak:
> cpu bogo ops 270106 (+0.6%)
> iosync bogo ops 9474535 (-3.42%)
> vm bogo ops 17093608 (the same)
>
> Test #2: hackbench -s 4096 -l 2000 -g 15 -f 25 -P
> Average result on 4.11-rc8: 8.71s
> Average result on 4.11-rc8+stackleak: 9.08s (+4.29%)
>
> Test #3: building the Linux kernel with Ubuntu config (time make -j9)
> Result on 4.11-rc8:
> real 32m14.893s
> user 237m30.886s
> sys 11m12.273s
> Result on 4.11-rc8+stackleak:
> real 32m26.881s (+0.62%)
> user 238m38.926s (+0.48%)
> sys 11m36.426s (+3.59%)
Awesome, and thanks for the benchmarks! That should really help people
understand the trade-offs for using this feature (and is likely worth
mentioning in the Kconfig). Seems like less than 4% overhead, maybe
much less? Real time on build times seems like a tiny difference, but
hackbench shows 4%.
> There is an important aspect of STACKLEAK on i386. PaX Team might know
> about it, I can't say for sure. Dear Grsecurity, is it fine to talk with
> you about such things in that mailing list? Should I do it differently?
>
> The STACKLEAK gcc plugin does not instrument the kernel code for i386. I've
> checked that for the last public patch of Grsecurity/PaX and see the same
> behaviour on my machines. The reason: the ix86_cmodel for the Linux kernel
> on i386 is not CM_KERNEL. So the STACKLEAK plugin seems to skip the
> instrumentation for that platform. As a result, on i386 erase_kstack()
> always starts to search for the bottom of the stack from the top minus 128.
What version of gcc did you use for these builds, btw? Perhaps
something changed there?
> See the results of the same performance tests on i386:
>
> Test #1: stress-ng --cpu 4 --io 2 --vm 2 --vm-bytes 2G --timeout 300s
> --metrics-brief
> Result on 4.11-rc8:
> cpu bogo ops 207754
> iosync bogo ops 9442815
> vm bogo ops 8546804
> Result on 4.11-rc8+stackleak:
> cpu bogo ops 206061 (-0.81%)
> iosync bogo ops 9435139 (-0.08%)
> vm bogo ops 8546804 (the same)
>
> Test #2: hackbench -s 4096 -l 2000 -g 15 -f 25 -P
> Average result on 4.11-rc8: 8.197s
> Average result on 4.11-rc8+stackleak: 9.134s (+11.43%)
>
> Test #3: building the Linux kernel with Ubuntu config (time make -j9)
> Result on 4.11-rc8:
> real 18m15.372s
> user 129m58.169s
> sys 8m27.884s
> Result on 4.11-rc8+stackleak:
> real 18m34.244s (+1.72%)
> user 132m33.843s (+2.00%)
> sys 8m37.658s (+1.92%)
>
> More things to be done:
> - understand how the STACKLEAK gcc plugin works;
> - develop tests for STACKLEAK.
Since this is mostly an anti-exposure defense, LKDTM is probably not a
good match (i.e. organizing a test for the uninit variable case can be
very fragile). I think something similar to test_user_copy.c would be
better.
> From d22af45233b2f6d657a29dcb1815b35a5a45c539 Mon Sep 17 00:00:00 2001
> From: Alexander Popov <alex.popov@...ux.com>
> Date: Fri, 9 Jun 2017 15:21:16 +0300
> Subject: [PATCH RFC v2 1/1] gcc-plugins: Add stackleak feature erasing the
> kernel stack at the end of syscalls
>
> The stackleak feature erases the kernel stack before returning from syscalls.
> That reduces the information which a kernel stack leak bug can reveal.
>
> This feature consists of:
> - the architecture-specific code filling the used part of the kernel stack
> with a poison value before returning to the userspace (currently only
> for i386 and x86_64);
> - the gcc plugin for tracking the lowest border of the kernel stack. It
> instruments the kernel code inserting the track_stack() function call if
> a stack frame size is over a specified limit.
>
> The stackleak feature is ported from grsecurity/PaX. For more information see:
> https://grsecurity.net/
> https://pax.grsecurity.net/
>
> This code is verbatim from Brad Spengler/PaX Team's code in the last public
Maybe "nearly verbatim" since Kconfigs and such were (correctly)
renamed/expanded, and comments were added.
> patch of grsecurity/PaX based on our understanding of the code. Changes or
> omissions from the original code are ours and don't reflect the original
> grsecurity/PaX code.
>
> Signed-off-by: Alexander Popov <alex.popov@...ux.com>
> Signed-off-by: Tycho Andersen <tycho@...ker.com>
This S-o-b is not right, I think it should just be yours. Perhaps say
something like "Continued upstreaming work started by Tycho Anderson."
in the commit log.
> ---
> arch/Kconfig | 20 ++
> arch/x86/Kconfig | 1 +
> arch/x86/entry/common.c | 17 +-
> arch/x86/entry/entry_32.S | 71 +++++++
> arch/x86/entry/entry_64.S | 99 ++++++++++
> arch/x86/entry/entry_64_compat.S | 8 +
> arch/x86/include/asm/processor.h | 4 +
> arch/x86/kernel/asm-offsets.c | 9 +
> arch/x86/kernel/dumpstack_32.c | 12 ++
> arch/x86/kernel/dumpstack_64.c | 33 ++++
> arch/x86/kernel/process_32.c | 5 +
> arch/x86/kernel/process_64.c | 5 +
> fs/exec.c | 17 ++
> scripts/Makefile.gcc-plugins | 3 +
> scripts/gcc-plugins/stackleak_plugin.c | 342 +++++++++++++++++++++++++++++++++
> 15 files changed, 643 insertions(+), 3 deletions(-)
> create mode 100644 scripts/gcc-plugins/stackleak_plugin.c
>
> diff --git a/arch/Kconfig b/arch/Kconfig
> index cd211a1..a209bd5 100644
> --- a/arch/Kconfig
> +++ b/arch/Kconfig
> @@ -436,6 +436,26 @@ config GCC_PLUGIN_STRUCTLEAK_VERBOSE
> initialized. Since not all existing initializers are detected
> by the plugin, this can produce false positive warnings.
>
> +config ARCH_HAS_STACKLEAK
> + def_bool n
This can just be "bool" (it will default off).
> + help
> + An architecture should select this if it has the code which
> + fills the used part of the kernel stack with a poison value
> + before returning from system calls.
Maybe specifically mention the -0xBEEF value?
> +
> +config STACKLEAK
I would follow the naming of the others, and call this GCC_PLUGIN_STACKLEAK
> + bool "Erase the kernel stack before returning from syscalls"
> + depends on GCC_PLUGINS
> + depends on ARCH_HAS_STACKLEAK
> + help
> + This option makes the kernel erase the kernel stack before it
> + returns from a system call. That reduces the information which
> + a kernel stack leak bug can reveal.
> +
> + This plugin was ported from grsecurity/PaX. More information at:
> + * https://grsecurity.net/
> + * https://pax.grsecurity.net/
Is Kconfig smart enough to include this in the gcc plugins sub-page
when the ARCH_HAS_STACKLEAK config is between this and the others?
> +
> config HAVE_CC_STACKPROTECTOR
> bool
> help
> diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
> index cc98d5a..5988a5f 100644
> --- a/arch/x86/Kconfig
> +++ b/arch/x86/Kconfig
> @@ -56,6 +56,7 @@ config X86
> select ARCH_HAS_PMEM_API if X86_64
> select ARCH_HAS_SET_MEMORY
> select ARCH_HAS_SG_CHAIN
> + select ARCH_HAS_STACKLEAK
> select ARCH_HAS_STRICT_KERNEL_RWX
> select ARCH_HAS_STRICT_MODULE_RWX
> select ARCH_HAS_UBSAN_SANITIZE_ALL
> diff --git a/arch/x86/entry/common.c b/arch/x86/entry/common.c
> index 370c42c..8ff0a84 100644
> --- a/arch/x86/entry/common.c
> +++ b/arch/x86/entry/common.c
> @@ -43,6 +43,12 @@ __visible inline void enter_from_user_mode(void)
> static inline void enter_from_user_mode(void) {}
> #endif
>
> +#ifdef CONFIG_STACKLEAK
> +asmlinkage void erase_kstack(void);
> +#else
> +static void erase_kstack(void) {}
> +#endif
> +
> static void do_audit_syscall_entry(struct pt_regs *regs, u32 arch)
> {
> #ifdef CONFIG_X86_64
> @@ -79,8 +85,10 @@ static long syscall_trace_enter(struct pt_regs *regs)
> emulated = true;
>
> if ((emulated || (work & _TIF_SYSCALL_TRACE)) &&
> - tracehook_report_syscall_entry(regs))
> + tracehook_report_syscall_entry(regs)) {
> + erase_kstack();
> return -1L;
> + }
>
> if (emulated)
> return -1L;
> @@ -114,9 +122,11 @@ static long syscall_trace_enter(struct pt_regs *regs)
> sd.args[5] = regs->bp;
> }
>
> - ret = __secure_computing(&sd);
> - if (ret == -1)
> + ret = secure_computing(&sd);
> + if (ret == -1) {
> + erase_kstack();
> return ret;
> + }
> }
> #endif
Since this is x86-specific, maybe Cc x86@...nel.org and/or Andy
Lutomirski on follow-up versions. I'm sure they'll have opinions about
changes to the entry code. :)
It seems like it shouldn't be too hard to add on-user-return erasure
code to other architectures too.
-Kees
--
Kees Cook
Pixel Security
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.