1.\" $NetBSD: stack.7,v 1.6 2023/12/07 17:24:22 riastradh Exp $ 2.\" 3.\" Copyright (c) 2023 The NetBSD Foundation, Inc. 4.\" All rights reserved. 5.\" 6.\" Redistribution and use in source and binary forms, with or without 7.\" modification, are permitted provided that the following conditions 8.\" are met: 9.\" 1. Redistributions of source code must retain the above copyright 10.\" notice, this list of conditions and the following disclaimer. 11.\" 2. Redistributions in binary form must reproduce the above copyright 12.\" notice, this list of conditions and the following disclaimer in the 13.\" documentation and/or other materials provided with the distribution. 14.\" 15.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 16.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 17.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 18.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 19.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25.\" POSSIBILITY OF SUCH DAMAGE. 26.\" 27.Dd November 23, 2023 28.Dt STACK 7 29.Os 30.Sh NAME 31.Nm stack 32.Nd layout of program execution stack memory 33.Sh DESCRIPTION 34When executing a program, with the 35.Xr execve 2 36or 37.Xr posix_spawn 3 38families of system calls, 39.Nx 40reserves a region in the new program image's virtual address space for 41the 42.Em stack , 43which stores return addresses and local variables for nested procedure 44calls in program execution. 45Similarly, threads created with 46.Xr pthread_create 3 47have regions allocated for per-thread stacks. 48.Pp 49The stack grows from the 50.Em base , 51where information of the outermost procedure call is stored, fixed at 52program start, to the 53.Em stack pointer , 54a 55.Tn CPU 56register that points to information used by the current procedure call, 57varying during execution as procedures are called. 58.Pp 59On most architectures, the stack base is at higher-numbered virtual 60addresses and the stack pointer is at lower-numbered virtual addresses 61\(em on these architectures, 62.Em the stack grows down . 63On some other architectures, notably 64.Tn HP PA-RISC 65.Pq Sq hppa , 66the stack base is at lower-numbered virtual addresses and the stack 67pointer is at higher-numbered virtual addresses, so on those 68architectures 69.Em the stack grows up . 70.Pp 71In the kernel, the C preprocessor macro 72.Dv __HAVE_MACHINE_STACK_GROWS_UP 73is defined in 74.In machine/types.h 75on architectures where the stack grows up. 76.Ss Main thread 77For single-threaded programs, and for the main thread of multi-threaded 78programs, 79.Nx 80reserves virtual addresses as follows on architectures where the stack 81grows down: 82.Bd -literal 83+--------------------+ USRSTACK 84| stack gap | 85+--------------------+ stack base 86| accessible pages | 87| . | 88| . | <-- stack pointer (varies during execution) 89| . | 90+--------------------+ (stack base) - (soft stack rlimit) 91| inaccessible pages | 92+--------------------+ (stack base) - (hard stack rlimit) 93| guard/redzone | 94+--------------------+ USRSTACK - MAXSSIZ 95.Ed 96.Pp 97On architectures where the stack grows up, the layout is: 98.Bd -literal 99+--------------------+ USRSTACK + MAXSSIZ 100| guard/redzone | 101+--------------------+ (stack base) + (hard stack rlimit) 102| inaccessible pages | 103+--------------------+ (stack base) + (soft stack rlimit) 104| . | 105| . | <-- stack pointer (varies during execution) 106| . | 107| accessible pages | 108+--------------------+ stack base 109| stack gap | 110+--------------------+ USRSTACK 111.Ed 112.Bl -bullet 113.It 114The 115.Em stack guard 116is allocated so that any access \(em read, write, or execute \(em will 117deliver 118.Dv SIGSEGV 119to the process. 120This serves to detect stack overflow and crash rather than silently 121overwrite other memory in the program's virtual address space. 122The size of the stack guard is tuned by the 123.Li vm.guard_size 124.Xr sysctl 7 125knob. 126.Pp 127The stack guard is also sometimes known as the 128.Sq redzone 129or 130.Sq red zone , 131although the term 132.Sq red zone 133is also sometimes used to mean a fixed space 134.Em above 135the stack pointer (in the direction of stack growth) that the system 136guarantees it will not overwrite when calling a signal handler in the 137.Tn ABI 138of some architectures; see also 139.Xr sigaltstack 2 140to specify an alternate stack base for the kernel to use when invoking 141signal handlers on signal delivery. 142.It 143The 144.Em inaccessible pages 145of the stack region are allocated so that any access will also deliver 146.Dv SIGSEGV 147to the process, but they can be made accessible by changing the soft 148stack rlimit with 149.Xr setrlimit 2 . 150.It 151The 152.Em accessible pages 153of the stack region are allocated with read/write access permitted, and 154are used to store the actual data in the program stack. 155.It 156When 157.Tn PaX ASLR , 158address space layout randomization, is enabled, the 159.Em stack gap 160is an 161.Em unallocated 162space of a size chosen unpredictably at random at program startup time. 163When 164.Tn PaX ASLR 165is disabled, the stack gap is empty. 166.El 167.Pp 168All of the boundaries \(em 169.Dv USRSTACK , 170the stack base, and the boundaries between the accessible, 171inaccessible, and guard pages \(em are page-aligned, or rounded to be 172page-aligned even if the rlimits are not themselves page-aligned, 173rounding so that the sizes of the regions do not exceed the rlimits. 174.Pp 175The stack base is exposed to programs via the 176.Dv AT_STACKBASE 177.Xr elf 5 178auxiliary info vector entry. 179.Pp 180The per-architecture constants 181.Dv USRSTACK 182and 183.Dv MAXSSIZ 184are defined in 185.In machine/vmparam.h . 186.Ss Non-main threads 187Threads created with 188.Xr pthread_create 3 189have stacks allocated at dynamically chosen addresses outside the main 190thread's stack region by default, and their stacks cannot be resized 191after creation. 192On architectures where the stack grows down, the layout is: 193.Bd -literal 194+--------------------+ stack base = stackaddr + stacksize + guardsize 195| stack | 196| . | 197| . | <-- stack pointer (varies during execution) 198| . | 199+--------------------+ stackaddr 200| guard/redzone | 201+--------------------+ stackaddr - guardsize 202.Ed 203.Pp 204On architectures where the stack grows up, the layout is: 205.Bd -literal 206+--------------------+ stackaddr + stacksize + guardsize 207| guard/redzone | 208+--------------------+ stackaddr + stacksize 209| . | 210| . | <-- stack pointer (varies during execution) 211| . | 212| stack | 213+--------------------+ stack base = stackaddr 214.Ed 215.Pp 216The parameters stackaddr, stacksize, and guardsize can be obtained from 217an existing thread using 218.Xr pthread_getattr_np 3 , 219.Xr pthread_attr_getguardsize 3 , 220and the 221.Xr pthread_attr_getstack 3 222family of functions. 223.Pp 224When creating a thread, the stack can be manually allocated and the 225parameters can be set using 226.Xr pthread_attr_setguardsize 3 227and the 228.Xr pthread_attr_setstack 3 229family of functions. 230However, the stack parameters cannot be changed after thread creation. 231The default guard size is tuned by the 232.Li vm.thread_guard_size 233.Xr sysctl 7 234knob. 235.Pp 236For the main thread, 237.Xr pthread_getattr_np 3 238returns a 239.Em snapshot 240of the parameters as they existed at program startup, so that stackaddr 241and stacksize reflect the current accessible pages of the stack, and 242guardsize is the value of the 243.Li vm.guard_size 244.Xr sysctl 7 245knob at the time of program startup. 246.Po 247Note that this means the 248.Xr pthread 3 249view of the main thread's stack guard may not coincide with the actual 250stack guard \(em it may overlap with, or lie entirely in, the 251inaccessible pages of the stack reserved on program start. 252.Pc 253However, if the program changes its soft stack rlimit with 254.Xr setrlimit 2 , 255this snapshot may become stale. 256.Sh SEE ALSO 257.Xr execve 2 , 258.Xr mmap 2 , 259.Xr mprotect 2 , 260.Xr sigaltstack 2 , 261.Xr ucontext 2 , 262.Xr posix_spawn 3 , 263.Xr pthread 3 , 264.Xr security 7 , 265.Xr sysctl 7 , 266.Xr paxctl 8 267.Sh BUGS 268.Tn PaX ASLR 269doesn't actually guarantee an accessible stack reservation of length 270equal to the soft stack rlimit \(em owing to a bug (XXX which PR 271number?), 272.Nx 273may sometimes reserve less space than the soft rlimit, in which case 274the accessible pages of the stack cannot be extended. 275.Pp 276There is a race between the kernel's access of 277.Li vm.guard_size 278at exec time, and userland's access of 279.Li vm.guard_size 280in 281.Xr pthread 3 282initialization. 283