~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/include/linux/randomize_kstack.h

Version: ~ [ linux-6.11-rc3 ] ~ [ linux-6.10.4 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.45 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.104 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.164 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.223 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.281 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.319 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /* SPDX-License-Identifier: GPL-2.0-only */
  2 #ifndef _LINUX_RANDOMIZE_KSTACK_H
  3 #define _LINUX_RANDOMIZE_KSTACK_H
  4 
  5 #ifdef CONFIG_RANDOMIZE_KSTACK_OFFSET
  6 #include <linux/kernel.h>
  7 #include <linux/jump_label.h>
  8 #include <linux/percpu-defs.h>
  9 
 10 DECLARE_STATIC_KEY_MAYBE(CONFIG_RANDOMIZE_KSTACK_OFFSET_DEFAULT,
 11                          randomize_kstack_offset);
 12 DECLARE_PER_CPU(u32, kstack_offset);
 13 
 14 /*
 15  * Do not use this anywhere else in the kernel. This is used here because
 16  * it provides an arch-agnostic way to grow the stack with correct
 17  * alignment. Also, since this use is being explicitly masked to a max of
 18  * 10 bits, stack-clash style attacks are unlikely. For more details see
 19  * "VLAs" in Documentation/process/deprecated.rst
 20  *
 21  * The normal __builtin_alloca() is initialized with INIT_STACK_ALL (currently
 22  * only with Clang and not GCC). Initializing the unused area on each syscall
 23  * entry is expensive, and generating an implicit call to memset() may also be
 24  * problematic (such as in noinstr functions). Therefore, if the compiler
 25  * supports it (which it should if it initializes allocas), always use the
 26  * "uninitialized" variant of the builtin.
 27  */
 28 #if __has_builtin(__builtin_alloca_uninitialized)
 29 #define __kstack_alloca __builtin_alloca_uninitialized
 30 #else
 31 #define __kstack_alloca __builtin_alloca
 32 #endif
 33 
 34 /*
 35  * Use, at most, 6 bits of entropy (on 64-bit; 8 on 32-bit). This cap is
 36  * to keep the "VLA" from being unbounded (see above). Additionally clear
 37  * the bottom 4 bits (on 64-bit systems, 2 for 32-bit), since stack
 38  * alignment will always be at least word size. This makes the compiler
 39  * code gen better when it is applying the actual per-arch alignment to
 40  * the final offset. The resulting randomness is reasonable without overly
 41  * constraining usable stack space.
 42  */
 43 #ifdef CONFIG_64BIT
 44 #define KSTACK_OFFSET_MAX(x)    ((x) & 0b1111110000)
 45 #else
 46 #define KSTACK_OFFSET_MAX(x)    ((x) & 0b1111111100)
 47 #endif
 48 
 49 /**
 50  * add_random_kstack_offset - Increase stack utilization by previously
 51  *                            chosen random offset
 52  *
 53  * This should be used in the syscall entry path when interrupts and
 54  * preempt are disabled, and after user registers have been stored to
 55  * the stack. For testing the resulting entropy, please see:
 56  * tools/testing/selftests/lkdtm/stack-entropy.sh
 57  */
 58 #define add_random_kstack_offset() do {                                 \
 59         if (static_branch_maybe(CONFIG_RANDOMIZE_KSTACK_OFFSET_DEFAULT, \
 60                                 &randomize_kstack_offset)) {            \
 61                 u32 offset = raw_cpu_read(kstack_offset);               \
 62                 u8 *ptr = __kstack_alloca(KSTACK_OFFSET_MAX(offset));   \
 63                 /* Keep allocation even after "ptr" loses scope. */     \
 64                 asm volatile("" :: "r"(ptr) : "memory");                \
 65         }                                                               \
 66 } while (0)
 67 
 68 /**
 69  * choose_random_kstack_offset - Choose the random offset for the next
 70  *                               add_random_kstack_offset()
 71  *
 72  * This should only be used during syscall exit when interrupts and
 73  * preempt are disabled. This position in the syscall flow is done to
 74  * frustrate attacks from userspace attempting to learn the next offset:
 75  * - Maximize the timing uncertainty visible from userspace: if the
 76  *   offset is chosen at syscall entry, userspace has much more control
 77  *   over the timing between choosing offsets. "How long will we be in
 78  *   kernel mode?" tends to be more difficult to predict than "how long
 79  *   will we be in user mode?"
 80  * - Reduce the lifetime of the new offset sitting in memory during
 81  *   kernel mode execution. Exposure of "thread-local" memory content
 82  *   (e.g. current, percpu, etc) tends to be easier than arbitrary
 83  *   location memory exposure.
 84  */
 85 #define choose_random_kstack_offset(rand) do {                          \
 86         if (static_branch_maybe(CONFIG_RANDOMIZE_KSTACK_OFFSET_DEFAULT, \
 87                                 &randomize_kstack_offset)) {            \
 88                 u32 offset = raw_cpu_read(kstack_offset);               \
 89                 offset = ror32(offset, 5) ^ (rand);                     \
 90                 raw_cpu_write(kstack_offset, offset);                   \
 91         }                                                               \
 92 } while (0)
 93 #else /* CONFIG_RANDOMIZE_KSTACK_OFFSET */
 94 #define add_random_kstack_offset()              do { } while (0)
 95 #define choose_random_kstack_offset(rand)       do { } while (0)
 96 #endif /* CONFIG_RANDOMIZE_KSTACK_OFFSET */
 97 
 98 #endif
 99 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php