xref: /netbsd-src/share/man/man7/stack.7 (revision 4fcf94919aae7826a59ef7f32be39e6304120ca3)
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