mirror of
https://github.com/Evolution-X-Devices/kernel_google_b1c1
synced 2026-02-02 17:12:39 +00:00
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>
135 lines
3.2 KiB
C
135 lines
3.2 KiB
C
/* thread_info.h: common low-level thread information accessors
|
|
*
|
|
* Copyright (C) 2002 David Howells (dhowells@redhat.com)
|
|
* - Incorporating suggestions made by Linus Torvalds
|
|
*/
|
|
|
|
#ifndef _LINUX_THREAD_INFO_H
|
|
#define _LINUX_THREAD_INFO_H
|
|
|
|
#include <linux/types.h>
|
|
#include <linux/bug.h>
|
|
|
|
struct timespec;
|
|
struct compat_timespec;
|
|
|
|
#ifdef CONFIG_THREAD_INFO_IN_TASK
|
|
#define current_thread_info() ((struct thread_info *)current)
|
|
#endif
|
|
|
|
/*
|
|
* System call restart block.
|
|
*/
|
|
struct restart_block {
|
|
long (*fn)(struct restart_block *);
|
|
union {
|
|
/* For futex_wait and futex_wait_requeue_pi */
|
|
struct {
|
|
u32 __user *uaddr;
|
|
u32 val;
|
|
u32 flags;
|
|
u32 bitset;
|
|
u64 time;
|
|
u32 __user *uaddr2;
|
|
} futex;
|
|
/* For nanosleep */
|
|
struct {
|
|
clockid_t clockid;
|
|
struct timespec __user *rmtp;
|
|
#ifdef CONFIG_COMPAT
|
|
struct compat_timespec __user *compat_rmtp;
|
|
#endif
|
|
u64 expires;
|
|
} nanosleep;
|
|
/* For poll */
|
|
struct {
|
|
struct pollfd __user *ufds;
|
|
int nfds;
|
|
int has_timeout;
|
|
unsigned long tv_sec;
|
|
unsigned long tv_nsec;
|
|
} poll;
|
|
};
|
|
};
|
|
|
|
extern long do_no_restart_syscall(struct restart_block *parm);
|
|
|
|
#include <linux/bitops.h>
|
|
#include <asm/thread_info.h>
|
|
|
|
#ifdef __KERNEL__
|
|
|
|
#define THREADINFO_GFP (GFP_KERNEL_ACCOUNT | __GFP_NOTRACK | __GFP_ZERO)
|
|
|
|
/*
|
|
* flag set/clear/test wrappers
|
|
* - pass TIF_xxxx constants to these functions
|
|
*/
|
|
|
|
static inline void set_ti_thread_flag(struct thread_info *ti, int flag)
|
|
{
|
|
set_bit(flag, (unsigned long *)&ti->flags);
|
|
}
|
|
|
|
static inline void clear_ti_thread_flag(struct thread_info *ti, int flag)
|
|
{
|
|
clear_bit(flag, (unsigned long *)&ti->flags);
|
|
}
|
|
|
|
static inline int test_and_set_ti_thread_flag(struct thread_info *ti, int flag)
|
|
{
|
|
return test_and_set_bit(flag, (unsigned long *)&ti->flags);
|
|
}
|
|
|
|
static inline int test_and_clear_ti_thread_flag(struct thread_info *ti, int flag)
|
|
{
|
|
return test_and_clear_bit(flag, (unsigned long *)&ti->flags);
|
|
}
|
|
|
|
static inline int test_ti_thread_flag(struct thread_info *ti, int flag)
|
|
{
|
|
return test_bit(flag, (unsigned long *)&ti->flags);
|
|
}
|
|
|
|
#define set_thread_flag(flag) \
|
|
set_ti_thread_flag(current_thread_info(), flag)
|
|
#define clear_thread_flag(flag) \
|
|
clear_ti_thread_flag(current_thread_info(), flag)
|
|
#define test_and_set_thread_flag(flag) \
|
|
test_and_set_ti_thread_flag(current_thread_info(), flag)
|
|
#define test_and_clear_thread_flag(flag) \
|
|
test_and_clear_ti_thread_flag(current_thread_info(), flag)
|
|
#define test_thread_flag(flag) \
|
|
test_ti_thread_flag(current_thread_info(), flag)
|
|
|
|
#define tif_need_resched() test_thread_flag(TIF_NEED_RESCHED)
|
|
|
|
#ifndef CONFIG_HAVE_ARCH_WITHIN_STACK_FRAMES
|
|
static inline int arch_within_stack_frames(const void * const stack,
|
|
const void * const stackend,
|
|
const void *obj, unsigned long len)
|
|
{
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
#ifdef CONFIG_HARDENED_USERCOPY
|
|
extern void __check_object_size(const void *ptr, unsigned long n,
|
|
bool to_user);
|
|
|
|
static __always_inline void check_object_size(const void *ptr, unsigned long n,
|
|
bool to_user)
|
|
{
|
|
if (!__builtin_constant_p(n))
|
|
__check_object_size(ptr, n, to_user);
|
|
}
|
|
#else
|
|
static inline void check_object_size(const void *ptr, unsigned long n,
|
|
bool to_user)
|
|
{ }
|
|
#endif /* CONFIG_HARDENED_USERCOPY */
|
|
|
|
#endif /* __KERNEL__ */
|
|
|
|
#endif /* _LINUX_THREAD_INFO_H */
|