1*4fcf9491Sriastradh.\" $NetBSD: stack.7,v 1.6 2023/12/07 17:24:22 riastradh Exp $ 2001acc2fSriastradh.\" 3001acc2fSriastradh.\" Copyright (c) 2023 The NetBSD Foundation, Inc. 4001acc2fSriastradh.\" All rights reserved. 5001acc2fSriastradh.\" 6001acc2fSriastradh.\" Redistribution and use in source and binary forms, with or without 7001acc2fSriastradh.\" modification, are permitted provided that the following conditions 8001acc2fSriastradh.\" are met: 9001acc2fSriastradh.\" 1. Redistributions of source code must retain the above copyright 10001acc2fSriastradh.\" notice, this list of conditions and the following disclaimer. 11001acc2fSriastradh.\" 2. Redistributions in binary form must reproduce the above copyright 12001acc2fSriastradh.\" notice, this list of conditions and the following disclaimer in the 13001acc2fSriastradh.\" documentation and/or other materials provided with the distribution. 14001acc2fSriastradh.\" 15001acc2fSriastradh.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 16001acc2fSriastradh.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 17001acc2fSriastradh.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 18001acc2fSriastradh.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 19001acc2fSriastradh.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20001acc2fSriastradh.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21001acc2fSriastradh.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22001acc2fSriastradh.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23001acc2fSriastradh.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24001acc2fSriastradh.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25001acc2fSriastradh.\" POSSIBILITY OF SUCH DAMAGE. 26001acc2fSriastradh.\" 27001acc2fSriastradh.Dd November 23, 2023 28001acc2fSriastradh.Dt STACK 7 29001acc2fSriastradh.Os 30001acc2fSriastradh.Sh NAME 31001acc2fSriastradh.Nm stack 32001acc2fSriastradh.Nd layout of program execution stack memory 33001acc2fSriastradh.Sh DESCRIPTION 34001acc2fSriastradhWhen executing a program, with the 35001acc2fSriastradh.Xr execve 2 36001acc2fSriastradhor 37001acc2fSriastradh.Xr posix_spawn 3 38001acc2fSriastradhfamilies of system calls, 39001acc2fSriastradh.Nx 40001acc2fSriastradhreserves a region in the new program image's virtual address space for 41001acc2fSriastradhthe 42001acc2fSriastradh.Em stack , 43001acc2fSriastradhwhich stores return addresses and local variables for nested procedure 44001acc2fSriastradhcalls in program execution. 45001acc2fSriastradhSimilarly, threads created with 46001acc2fSriastradh.Xr pthread_create 3 47001acc2fSriastradhhave regions allocated for per-thread stacks. 48001acc2fSriastradh.Pp 49001acc2fSriastradhThe stack grows from the 50001acc2fSriastradh.Em base , 51001acc2fSriastradhwhere information of the outermost procedure call is stored, fixed at 52001acc2fSriastradhprogram start, to the 53001acc2fSriastradh.Em stack pointer , 54001acc2fSriastradha 55001acc2fSriastradh.Tn CPU 56001acc2fSriastradhregister that points to information used by the current procedure call, 57001acc2fSriastradhvarying during execution as procedures are called. 58001acc2fSriastradh.Pp 59001acc2fSriastradhOn most architectures, the stack base is at higher-numbered virtual 60001acc2fSriastradhaddresses and the stack pointer is at lower-numbered virtual addresses 61001acc2fSriastradh\(em on these architectures, 62001acc2fSriastradh.Em the stack grows down . 63001acc2fSriastradhOn some other architectures, notably 64001acc2fSriastradh.Tn HP PA-RISC 65001acc2fSriastradh.Pq Sq hppa , 66001acc2fSriastradhthe stack base is at lower-numbered virtual addresses and the stack 67001acc2fSriastradhpointer is at higher-numbered virtual addresses, so on those 68001acc2fSriastradharchitectures 69001acc2fSriastradh.Em the stack grows up . 70001acc2fSriastradh.Pp 71001acc2fSriastradhIn the kernel, the C preprocessor macro 72001acc2fSriastradh.Dv __HAVE_MACHINE_STACK_GROWS_UP 73001acc2fSriastradhis defined in 74001acc2fSriastradh.In machine/types.h 75001acc2fSriastradhon architectures where the stack grows up. 76001acc2fSriastradh.Ss Main thread 77001acc2fSriastradhFor single-threaded programs, and for the main thread of multi-threaded 78001acc2fSriastradhprograms, 79001acc2fSriastradh.Nx 80001acc2fSriastradhreserves virtual addresses as follows on architectures where the stack 81001acc2fSriastradhgrows down: 82001acc2fSriastradh.Bd -literal 83001acc2fSriastradh+--------------------+ USRSTACK 84001acc2fSriastradh| stack gap | 85001acc2fSriastradh+--------------------+ stack base 863c3bf573Sriastradh| accessible pages | 87001acc2fSriastradh| . | 88001acc2fSriastradh| . | <-- stack pointer (varies during execution) 89001acc2fSriastradh| . | 90001acc2fSriastradh+--------------------+ (stack base) - (soft stack rlimit) 913c3bf573Sriastradh| inaccessible pages | 92001acc2fSriastradh+--------------------+ (stack base) - (hard stack rlimit) 93001acc2fSriastradh| guard/redzone | 94001acc2fSriastradh+--------------------+ USRSTACK - MAXSSIZ 95001acc2fSriastradh.Ed 96001acc2fSriastradh.Pp 97001acc2fSriastradhOn architectures where the stack grows up, the layout is: 98001acc2fSriastradh.Bd -literal 99001acc2fSriastradh+--------------------+ USRSTACK + MAXSSIZ 100001acc2fSriastradh| guard/redzone | 101001acc2fSriastradh+--------------------+ (stack base) + (hard stack rlimit) 102001acc2fSriastradh| inaccessible pages | 103001acc2fSriastradh+--------------------+ (stack base) + (soft stack rlimit) 104001acc2fSriastradh| . | 105001acc2fSriastradh| . | <-- stack pointer (varies during execution) 106001acc2fSriastradh| . | 107001acc2fSriastradh| accessible pages | 108001acc2fSriastradh+--------------------+ stack base 109001acc2fSriastradh| stack gap | 110001acc2fSriastradh+--------------------+ USRSTACK 111001acc2fSriastradh.Ed 112001acc2fSriastradh.Bl -bullet 113001acc2fSriastradh.It 114001acc2fSriastradhThe 115001acc2fSriastradh.Em stack guard 116001acc2fSriastradhis allocated so that any access \(em read, write, or execute \(em will 117001acc2fSriastradhdeliver 118001acc2fSriastradh.Dv SIGSEGV 119001acc2fSriastradhto the process. 120001acc2fSriastradhThis serves to detect stack overflow and crash rather than silently 121001acc2fSriastradhoverwrite other memory in the program's virtual address space. 122001acc2fSriastradhThe size of the stack guard is tuned by the 123001acc2fSriastradh.Li vm.guard_size 124001acc2fSriastradh.Xr sysctl 7 125001acc2fSriastradhknob. 126001acc2fSriastradh.Pp 127001acc2fSriastradhThe stack guard is also sometimes known as the 128001acc2fSriastradh.Sq redzone 129001acc2fSriastradhor 130001acc2fSriastradh.Sq red zone , 131001acc2fSriastradhalthough the term 132001acc2fSriastradh.Sq red zone 133001acc2fSriastradhis also sometimes used to mean a fixed space 134001acc2fSriastradh.Em above 135001acc2fSriastradhthe stack pointer (in the direction of stack growth) that the system 136f1d67e98Sriastradhguarantees it will not overwrite when calling a signal handler in the 137001acc2fSriastradh.Tn ABI 138001acc2fSriastradhof some architectures; see also 139001acc2fSriastradh.Xr sigaltstack 2 140001acc2fSriastradhto specify an alternate stack base for the kernel to use when invoking 141001acc2fSriastradhsignal handlers on signal delivery. 142001acc2fSriastradh.It 143001acc2fSriastradhThe 144001acc2fSriastradh.Em inaccessible pages 145001acc2fSriastradhof the stack region are allocated so that any access will also deliver 146001acc2fSriastradh.Dv SIGSEGV 147001acc2fSriastradhto the process, but they can be made accessible by changing the soft 148001acc2fSriastradhstack rlimit with 149001acc2fSriastradh.Xr setrlimit 2 . 150001acc2fSriastradh.It 151001acc2fSriastradhThe 152001acc2fSriastradh.Em accessible pages 153001acc2fSriastradhof the stack region are allocated with read/write access permitted, and 154001acc2fSriastradhare used to store the actual data in the program stack. 155001acc2fSriastradh.It 156001acc2fSriastradhWhen 157001acc2fSriastradh.Tn PaX ASLR , 158001acc2fSriastradhaddress space layout randomization, is enabled, the 159001acc2fSriastradh.Em stack gap 160001acc2fSriastradhis an 161001acc2fSriastradh.Em unallocated 162001acc2fSriastradhspace of a size chosen unpredictably at random at program startup time. 163001acc2fSriastradhWhen 164001acc2fSriastradh.Tn PaX ASLR 165001acc2fSriastradhis disabled, the stack gap is empty. 166001acc2fSriastradh.El 167001acc2fSriastradh.Pp 168001acc2fSriastradhAll of the boundaries \(em 169001acc2fSriastradh.Dv USRSTACK , 170001acc2fSriastradhthe stack base, and the boundaries between the accessible, 171001acc2fSriastradhinaccessible, and guard pages \(em are page-aligned, or rounded to be 172001acc2fSriastradhpage-aligned even if the rlimits are not themselves page-aligned, 173001acc2fSriastradhrounding so that the sizes of the regions do not exceed the rlimits. 174001acc2fSriastradh.Pp 175001acc2fSriastradhThe stack base is exposed to programs via the 176001acc2fSriastradh.Dv AT_STACKBASE 177001acc2fSriastradh.Xr elf 5 178001acc2fSriastradhauxiliary info vector entry. 179001acc2fSriastradh.Pp 180001acc2fSriastradhThe per-architecture constants 181001acc2fSriastradh.Dv USRSTACK 182001acc2fSriastradhand 183001acc2fSriastradh.Dv MAXSSIZ 184001acc2fSriastradhare defined in 185001acc2fSriastradh.In machine/vmparam.h . 186001acc2fSriastradh.Ss Non-main threads 187001acc2fSriastradhThreads created with 188001acc2fSriastradh.Xr pthread_create 3 189f1d67e98Sriastradhhave stacks allocated at dynamically chosen addresses outside the main 190f1d67e98Sriastradhthread's stack region by default, and their stacks cannot be resized 191f1d67e98Sriastradhafter creation. 192001acc2fSriastradhOn architectures where the stack grows down, the layout is: 193001acc2fSriastradh.Bd -literal 194*4fcf9491Sriastradh+--------------------+ stack base = stackaddr + stacksize + guardsize 195bfb59bbaSriastradh| stack | 196001acc2fSriastradh| . | 197001acc2fSriastradh| . | <-- stack pointer (varies during execution) 198001acc2fSriastradh| . | 199*4fcf9491Sriastradh+--------------------+ stackaddr 200001acc2fSriastradh| guard/redzone | 201*4fcf9491Sriastradh+--------------------+ stackaddr - guardsize 202001acc2fSriastradh.Ed 203001acc2fSriastradh.Pp 204001acc2fSriastradhOn architectures where the stack grows up, the layout is: 205001acc2fSriastradh.Bd -literal 206001acc2fSriastradh+--------------------+ stackaddr + stacksize + guardsize 207001acc2fSriastradh| guard/redzone | 208001acc2fSriastradh+--------------------+ stackaddr + stacksize 209001acc2fSriastradh| . | 210001acc2fSriastradh| . | <-- stack pointer (varies during execution) 211001acc2fSriastradh| . | 212001acc2fSriastradh| stack | 213*4fcf9491Sriastradh+--------------------+ stack base = stackaddr 214001acc2fSriastradh.Ed 215001acc2fSriastradh.Pp 216001acc2fSriastradhThe parameters stackaddr, stacksize, and guardsize can be obtained from 217001acc2fSriastradhan existing thread using 218001acc2fSriastradh.Xr pthread_getattr_np 3 , 219001acc2fSriastradh.Xr pthread_attr_getguardsize 3 , 220001acc2fSriastradhand the 221001acc2fSriastradh.Xr pthread_attr_getstack 3 222001acc2fSriastradhfamily of functions. 223001acc2fSriastradh.Pp 224001acc2fSriastradhWhen creating a thread, the stack can be manually allocated and the 225001acc2fSriastradhparameters can be set using 226001acc2fSriastradh.Xr pthread_attr_setguardsize 3 227001acc2fSriastradhand the 228001acc2fSriastradh.Xr pthread_attr_setstack 3 229001acc2fSriastradhfamily of functions. 230001acc2fSriastradhHowever, the stack parameters cannot be changed after thread creation. 231001acc2fSriastradhThe default guard size is tuned by the 232001acc2fSriastradh.Li vm.thread_guard_size 233001acc2fSriastradh.Xr sysctl 7 234001acc2fSriastradhknob. 235001acc2fSriastradh.Pp 236001acc2fSriastradhFor the main thread, 237001acc2fSriastradh.Xr pthread_getattr_np 3 238001acc2fSriastradhreturns a 239001acc2fSriastradh.Em snapshot 240001acc2fSriastradhof the parameters as they existed at program startup, so that stackaddr 241001acc2fSriastradhand stacksize reflect the current accessible pages of the stack, and 242001acc2fSriastradhguardsize is the value of the 243001acc2fSriastradh.Li vm.guard_size 244001acc2fSriastradh.Xr sysctl 7 245001acc2fSriastradhknob at the time of program startup. 246f1d67e98Sriastradh.Po 247f1d67e98SriastradhNote that this means the 248623621d6Sriastradh.Xr pthread 3 249623621d6Sriastradhview of the main thread's stack guard may not coincide with the actual 250623621d6Sriastradhstack guard \(em it may overlap with, or lie entirely in, the 251f1d67e98Sriastradhinaccessible pages of the stack reserved on program start. 252f1d67e98Sriastradh.Pc 253001acc2fSriastradhHowever, if the program changes its soft stack rlimit with 254001acc2fSriastradh.Xr setrlimit 2 , 255001acc2fSriastradhthis snapshot may become stale. 256001acc2fSriastradh.Sh SEE ALSO 257001acc2fSriastradh.Xr execve 2 , 258001acc2fSriastradh.Xr mmap 2 , 259001acc2fSriastradh.Xr mprotect 2 , 260001acc2fSriastradh.Xr sigaltstack 2 , 261001acc2fSriastradh.Xr ucontext 2 , 262001acc2fSriastradh.Xr posix_spawn 3 , 263001acc2fSriastradh.Xr pthread 3 , 264001acc2fSriastradh.Xr security 7 , 265001acc2fSriastradh.Xr sysctl 7 , 266001acc2fSriastradh.Xr paxctl 8 267001acc2fSriastradh.Sh BUGS 268001acc2fSriastradh.Tn PaX ASLR 269001acc2fSriastradhdoesn't actually guarantee an accessible stack reservation of length 270001acc2fSriastradhequal to the soft stack rlimit \(em owing to a bug (XXX which PR 271001acc2fSriastradhnumber?), 272001acc2fSriastradh.Nx 273001acc2fSriastradhmay sometimes reserve less space than the soft rlimit, in which case 274001acc2fSriastradhthe accessible pages of the stack cannot be extended. 275001acc2fSriastradh.Pp 276001acc2fSriastradhThere is a race between the kernel's access of 277001acc2fSriastradh.Li vm.guard_size 278001acc2fSriastradhat exec time, and userland's access of 279001acc2fSriastradh.Li vm.guard_size 280001acc2fSriastradhin 281001acc2fSriastradh.Xr pthread 3 282001acc2fSriastradhinitialization. 283