Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

x86/entry: Enable random_kstack_offset support

Allow for a randomized stack offset on a per-syscall basis, with roughly
5-6 bits of entropy, depending on compiler and word size. Since the
method of offsetting uses macros, this cannot live in the common entry
code (the stack offset needs to be retained for the life of the syscall,
which means it needs to happen at the actual entry point).

Signed-off-by: Kees Cook <keescook@chromium.org>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
Link: https://lore.kernel.org/r/20210401232347.2791257-5-keescook@chromium.org

authored by

Kees Cook and committed by
Thomas Gleixner
fe950f60 39218ff4

+20
+1
arch/x86/Kconfig
··· 165 165 select HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD if X86_64 166 166 select HAVE_ARCH_USERFAULTFD_WP if X86_64 && USERFAULTFD 167 167 select HAVE_ARCH_VMAP_STACK if X86_64 168 + select HAVE_ARCH_RANDOMIZE_KSTACK_OFFSET 168 169 select HAVE_ARCH_WITHIN_STACK_FRAMES 169 170 select HAVE_ASM_MODVERSIONS 170 171 select HAVE_CMPXCHG_DOUBLE
+3
arch/x86/entry/common.c
··· 38 38 #ifdef CONFIG_X86_64 39 39 __visible noinstr void do_syscall_64(unsigned long nr, struct pt_regs *regs) 40 40 { 41 + add_random_kstack_offset(); 41 42 nr = syscall_enter_from_user_mode(regs, nr); 42 43 43 44 instrumentation_begin(); ··· 84 83 { 85 84 unsigned int nr = syscall_32_enter(regs); 86 85 86 + add_random_kstack_offset(); 87 87 /* 88 88 * Subtlety here: if ptrace pokes something larger than 2^32-1 into 89 89 * orig_ax, the unsigned int return value truncates it. This may ··· 104 102 unsigned int nr = syscall_32_enter(regs); 105 103 int res; 106 104 105 + add_random_kstack_offset(); 107 106 /* 108 107 * This cannot use syscall_enter_from_user_mode() as it has to 109 108 * fetch EBP before invoking any of the syscall entry work
+16
arch/x86/include/asm/entry-common.h
··· 2 2 #ifndef _ASM_X86_ENTRY_COMMON_H 3 3 #define _ASM_X86_ENTRY_COMMON_H 4 4 5 + #include <linux/randomize_kstack.h> 5 6 #include <linux/user-return-notifier.h> 6 7 7 8 #include <asm/nospec-branch.h> ··· 71 70 */ 72 71 current_thread_info()->status &= ~(TS_COMPAT | TS_I386_REGS_POKED); 73 72 #endif 73 + 74 + /* 75 + * Ultimately, this value will get limited by KSTACK_OFFSET_MAX(), 76 + * but not enough for x86 stack utilization comfort. To keep 77 + * reasonable stack head room, reduce the maximum offset to 8 bits. 78 + * 79 + * The actual entropy will be further reduced by the compiler when 80 + * applying stack alignment constraints (see cc_stack_align4/8 in 81 + * arch/x86/Makefile), which will remove the 3 (x86_64) or 2 (ia32) 82 + * low bits from any entropy chosen here. 83 + * 84 + * Therefore, final stack offset entropy will be 5 (x86_64) or 85 + * 6 (ia32) bits. 86 + */ 87 + choose_random_kstack_offset(rdtsc() & 0xFF); 74 88 } 75 89 #define arch_exit_to_user_mode_prepare arch_exit_to_user_mode_prepare 76 90