| 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 | |