| From e01e80634ecdde1dd113ac43b3adad21b47f3957 Mon Sep 17 00:00:00 2001 |
| From: Kees Cook <keescook@chromium.org> |
| Date: Fri, 20 Apr 2018 14:55:31 -0700 |
| Subject: fork: unconditionally clear stack on fork |
| |
| From: Kees Cook <keescook@chromium.org> |
| |
| commit e01e80634ecdde1dd113ac43b3adad21b47f3957 upstream. |
| |
| One of the classes of kernel stack content leaks[1] is exposing the |
| contents of prior heap or stack contents when a new process stack is |
| allocated. Normally, those stacks are not zeroed, and the old contents |
| remain in place. In the face of stack content exposure flaws, those |
| contents can leak to userspace. |
| |
| Fixing this will make the kernel no longer vulnerable to these flaws, as |
| the stack will be wiped each time a stack is assigned to a new process. |
| There's not a meaningful change in runtime performance; it almost looks |
| like it provides a benefit. |
| |
| Performing back-to-back kernel builds before: |
| Run times: 157.86 157.09 158.90 160.94 160.80 |
| Mean: 159.12 |
| Std Dev: 1.54 |
| |
| and after: |
| Run times: 159.31 157.34 156.71 158.15 160.81 |
| Mean: 158.46 |
| Std Dev: 1.46 |
| |
| Instead of making this a build or runtime config, Andy Lutomirski |
| recommended this just be enabled by default. |
| |
| [1] A noisy search for many kinds of stack content leaks can be seen here: |
| https://cve.mitre.org/cgi-bin/cvekey.cgi?keyword=linux+kernel+stack+leak |
| |
| I did some more with perf and cycle counts on running 100,000 execs of |
| /bin/true. |
| |
| before: |
| Cycles: 218858861551 218853036130 214727610969 227656844122 224980542841 |
| Mean: 221015379122.60 |
| Std Dev: 4662486552.47 |
| |
| after: |
| Cycles: 213868945060 213119275204 211820169456 224426673259 225489986348 |
| Mean: 217745009865.40 |
| Std Dev: 5935559279.99 |
| |
| It continues to look like it's faster, though the deviation is rather |
| wide, but I'm not sure what I could do that would be less noisy. I'm |
| open to ideas! |
| |
| Link: http://lkml.kernel.org/r/20180221021659.GA37073@beast |
| Signed-off-by: Kees Cook <keescook@chromium.org> |
| Acked-by: Michal Hocko <mhocko@suse.com> |
| Reviewed-by: Andrew Morton <akpm@linux-foundation.org> |
| Cc: Andy Lutomirski <luto@kernel.org> |
| Cc: Laura Abbott <labbott@redhat.com> |
| Cc: Rasmus Villemoes <rasmus.villemoes@prevas.dk> |
| Cc: Mel Gorman <mgorman@techsingularity.net> |
| Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
| Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> |
| [ Srivatsa: Backported to 4.9.y ] |
| Signed-off-by: Srivatsa S. Bhat <srivatsa@csail.mit.edu> |
| Reviewed-by: Srinidhi Rao <srinidhir@vmware.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| include/linux/thread_info.h | 7 +------ |
| kernel/fork.c | 3 +-- |
| 2 files changed, 2 insertions(+), 8 deletions(-) |
| |
| --- a/include/linux/thread_info.h |
| +++ b/include/linux/thread_info.h |
| @@ -59,12 +59,7 @@ extern long do_no_restart_syscall(struct |
| |
| #ifdef __KERNEL__ |
| |
| -#if IS_ENABLED(CONFIG_DEBUG_STACK_USAGE) || IS_ENABLED(CONFIG_DEBUG_KMEMLEAK) |
| -# define THREADINFO_GFP (GFP_KERNEL_ACCOUNT | __GFP_NOTRACK | \ |
| - __GFP_ZERO) |
| -#else |
| -# define THREADINFO_GFP (GFP_KERNEL_ACCOUNT | __GFP_NOTRACK) |
| -#endif |
| +#define THREADINFO_GFP (GFP_KERNEL_ACCOUNT | __GFP_NOTRACK | __GFP_ZERO) |
| |
| /* |
| * flag set/clear/test wrappers |
| --- a/kernel/fork.c |
| +++ b/kernel/fork.c |
| @@ -184,10 +184,9 @@ static unsigned long *alloc_thread_stack |
| continue; |
| this_cpu_write(cached_stacks[i], NULL); |
| |
| -#ifdef CONFIG_DEBUG_KMEMLEAK |
| /* Clear stale pointers from reused stack. */ |
| memset(s->addr, 0, THREAD_SIZE); |
| -#endif |
| + |
| tsk->stack_vm_area = s; |
| local_irq_enable(); |
| return s->addr; |