brintos

brintos / linux-shallow public Read only

0
0
Text · 5.6 KiB · 5bc0f7c Raw
154 lines · plain
1.. SPDX-License-Identifier: GPL-2.02 3=====================================4Virtually Mapped Kernel Stack Support5=====================================6 7:Author: Shuah Khan <skhan@linuxfoundation.org>8 9.. contents:: :local:10 11Overview12--------13 14This is a compilation of information from the code and original patch15series that introduced the `Virtually Mapped Kernel Stacks feature16<https://lwn.net/Articles/694348/>`17 18Introduction19------------20 21Kernel stack overflows are often hard to debug and make the kernel22susceptible to exploits. Problems could show up at a later time making23it difficult to isolate and root-cause.24 25Virtually mapped kernel stacks with guard pages cause kernel stack26overflows to be caught immediately rather than causing difficult to27diagnose corruptions.28 29HAVE_ARCH_VMAP_STACK and VMAP_STACK configuration options enable30support for virtually mapped stacks with guard pages. This feature31causes reliable faults when the stack overflows. The usability of32the stack trace after overflow and response to the overflow itself33is architecture dependent.34 35.. note::36        As of this writing, arm64, powerpc, riscv, s390, um, and x86 have37        support for VMAP_STACK.38 39HAVE_ARCH_VMAP_STACK40--------------------41 42Architectures that can support Virtually Mapped Kernel Stacks should43enable this bool configuration option. The requirements are:44 45- vmalloc space must be large enough to hold many kernel stacks. This46  may rule out many 32-bit architectures.47- Stacks in vmalloc space need to work reliably.  For example, if48  vmap page tables are created on demand, either this mechanism49  needs to work while the stack points to a virtual address with50  unpopulated page tables or arch code (switch_to() and switch_mm(),51  most likely) needs to ensure that the stack's page table entries52  are populated before running on a possibly unpopulated stack.53- If the stack overflows into a guard page, something reasonable54  should happen. The definition of "reasonable" is flexible, but55  instantly rebooting without logging anything would be unfriendly.56 57VMAP_STACK58----------59 60When enabled, the VMAP_STACK bool configuration option allocates virtually61mapped task stacks. This option depends on HAVE_ARCH_VMAP_STACK.62 63- Enable this if you want the use virtually-mapped kernel stacks64  with guard pages. This causes kernel stack overflows to be caught65  immediately rather than causing difficult-to-diagnose corruption.66 67.. note::68 69        Using this feature with KASAN requires architecture support70        for backing virtual mappings with real shadow memory, and71        KASAN_VMALLOC must be enabled.72 73.. note::74 75        VMAP_STACK is enabled, it is not possible to run DMA on stack76        allocated data.77 78Kernel configuration options and dependencies keep changing. Refer to79the latest code base:80 81`Kconfig <https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/Kconfig>`82 83Allocation84-----------85 86When a new kernel thread is created, a thread stack is allocated from87virtually contiguous memory pages from the page level allocator. These88pages are mapped into contiguous kernel virtual space with PAGE_KERNEL89protections.90 91alloc_thread_stack_node() calls __vmalloc_node_range() to allocate stack92with PAGE_KERNEL protections.93 94- Allocated stacks are cached and later reused by new threads, so memcg95  accounting is performed manually on assigning/releasing stacks to tasks.96  Hence, __vmalloc_node_range is called without __GFP_ACCOUNT.97- vm_struct is cached to be able to find when thread free is initiated98  in interrupt context. free_thread_stack() can be called in interrupt99  context.100- On arm64, all VMAP's stacks need to have the same alignment to ensure101  that VMAP'd stack overflow detection works correctly. Arch specific102  vmap stack allocator takes care of this detail.103- This does not address interrupt stacks - according to the original patch104 105Thread stack allocation is initiated from clone(), fork(), vfork(),106kernel_thread() via kernel_clone(). These are a few hints for searching107the code base to understand when and how a thread stack is allocated.108 109Bulk of the code is in:110`kernel/fork.c <https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/kernel/fork.c>`.111 112stack_vm_area pointer in task_struct keeps track of the virtually allocated113stack and a non-null stack_vm_area pointer serves as an indication that the114virtually mapped kernel stacks are enabled.115 116::117 118        struct vm_struct *stack_vm_area;119 120Stack overflow handling121-----------------------122 123Leading and trailing guard pages help detect stack overflows. When the stack124overflows into the guard pages, handlers have to be careful not to overflow125the stack again. When handlers are called, it is likely that very little126stack space is left.127 128On x86, this is done by handling the page fault indicating the kernel129stack overflow on the double-fault stack.130 131Testing VMAP allocation with guard pages132----------------------------------------133 134How do we ensure that VMAP_STACK is actually allocating with a leading135and trailing guard page? The following lkdtm tests can help detect any136regressions.137 138::139 140        void lkdtm_STACK_GUARD_PAGE_LEADING()141        void lkdtm_STACK_GUARD_PAGE_TRAILING()142 143Conclusions144-----------145 146- A percpu cache of vmalloced stacks appears to be a bit faster than a147  high-order stack allocation, at least when the cache hits.148- THREAD_INFO_IN_TASK gets rid of arch-specific thread_info entirely and149  simply embed the thread_info (containing only flags) and 'int cpu' into150  task_struct.151- The thread stack can be freed as soon as the task is dead (without152  waiting for RCU) and then, if vmapped stacks are in use, cache the153  entire stack for reuse on the same cpu.154