1 /*
2 * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25 #include "precompiled.hpp"
26 #include "logging/log.hpp"
27 #include "runtime/os.inline.hpp"
28 #include "runtime/stackOverflow.hpp"
29 #include "runtime/thread.hpp"
30 #include "utilities/align.hpp"
31 #include "utilities/globalDefinitions.hpp"
32
33 size_t StackOverflow::_stack_red_zone_size = 0;
34 size_t StackOverflow::_stack_yellow_zone_size = 0;
35 size_t StackOverflow::_stack_reserved_zone_size = 0;
36 size_t StackOverflow::_stack_shadow_zone_size = 0;
37
initialize_stack_zone_sizes()38 void StackOverflow::initialize_stack_zone_sizes() {
39 // Stack zone sizes must be page aligned.
40 size_t page_size = os::vm_page_size();
41
42 // We need to adapt the configured number of stack protection pages given
43 // in 4K pages to the actual os page size. We must do this before setting
44 // up minimal stack sizes etc. in os::init_2().
45 size_t alignment = 4*K;
46
47 assert(_stack_red_zone_size == 0, "This should be called only once.");
48 _stack_red_zone_size = align_up(StackRedPages * alignment, page_size);
49
50 assert(_stack_yellow_zone_size == 0, "This should be called only once.");
51 _stack_yellow_zone_size = align_up(StackYellowPages * alignment, page_size);
52
53 assert(_stack_reserved_zone_size == 0, "This should be called only once.");
54 _stack_reserved_zone_size = align_up(StackReservedPages * alignment, page_size);
55
56 // The shadow area is not allocated or protected, so
57 // it needs not be page aligned.
58 // But the stack bang currently assumes that it is a
59 // multiple of page size. This guarantees that the bang
60 // loop touches all pages in the shadow zone.
61 // This can be guaranteed differently, as well. E.g., if
62 // the page size is a multiple of 4K, banging in 4K steps
63 // suffices to touch all pages. (Some pages are banged
64 // several times, though.)
65 assert(_stack_shadow_zone_size == 0, "This should be called only once.");
66 _stack_shadow_zone_size = align_up(StackShadowPages * alignment, page_size);
67 }
68
stack_guards_enabled() const69 bool StackOverflow::stack_guards_enabled() const {
70 #ifdef ASSERT
71 if (os::uses_stack_guard_pages() &&
72 !(DisablePrimordialThreadGuardPages && os::is_primordial_thread())) {
73 assert(_stack_guard_state != stack_guard_unused, "guard pages must be in use");
74 }
75 #endif
76 return _stack_guard_state == stack_guard_enabled;
77 }
78
create_stack_guard_pages()79 void StackOverflow::create_stack_guard_pages() {
80 if (!os::uses_stack_guard_pages() ||
81 _stack_guard_state != stack_guard_unused ||
82 (DisablePrimordialThreadGuardPages && os::is_primordial_thread())) {
83 log_info(os, thread)("Stack guard page creation for thread "
84 UINTX_FORMAT " disabled", os::current_thread_id());
85 return;
86 }
87 address low_addr = stack_end();
88 size_t len = stack_guard_zone_size();
89
90 assert(is_aligned(low_addr, os::vm_page_size()), "Stack base should be the start of a page");
91 assert(is_aligned(len, os::vm_page_size()), "Stack size should be a multiple of page size");
92
93 int must_commit = os::must_commit_stack_guard_pages();
94 // warning("Guarding at " PTR_FORMAT " for len " SIZE_FORMAT "\n", low_addr, len);
95
96 if (must_commit && !os::create_stack_guard_pages((char *) low_addr, len)) {
97 log_warning(os, thread)("Attempt to allocate stack guard pages failed.");
98 return;
99 }
100
101 if (os::guard_memory((char *) low_addr, len)) {
102 _stack_guard_state = stack_guard_enabled;
103 } else {
104 log_warning(os, thread)("Attempt to protect stack guard pages failed ("
105 PTR_FORMAT "-" PTR_FORMAT ").", p2i(low_addr), p2i(low_addr + len));
106 vm_exit_out_of_memory(len, OOM_MPROTECT_ERROR, "memory to guard stack pages");
107 }
108
109 log_debug(os, thread)("Thread " UINTX_FORMAT " stack guard pages activated: "
110 PTR_FORMAT "-" PTR_FORMAT ".",
111 os::current_thread_id(), p2i(low_addr), p2i(low_addr + len));
112 }
113
remove_stack_guard_pages()114 void StackOverflow::remove_stack_guard_pages() {
115 if (_stack_guard_state == stack_guard_unused) return;
116 address low_addr = stack_end();
117 size_t len = stack_guard_zone_size();
118
119 if (os::must_commit_stack_guard_pages()) {
120 if (os::remove_stack_guard_pages((char *) low_addr, len)) {
121 _stack_guard_state = stack_guard_unused;
122 } else {
123 log_warning(os, thread)("Attempt to deallocate stack guard pages failed ("
124 PTR_FORMAT "-" PTR_FORMAT ").", p2i(low_addr), p2i(low_addr + len));
125 return;
126 }
127 } else {
128 if (_stack_guard_state == stack_guard_unused) return;
129 if (os::unguard_memory((char *) low_addr, len)) {
130 _stack_guard_state = stack_guard_unused;
131 } else {
132 log_warning(os, thread)("Attempt to unprotect stack guard pages failed ("
133 PTR_FORMAT "-" PTR_FORMAT ").", p2i(low_addr), p2i(low_addr + len));
134 return;
135 }
136 }
137
138 log_debug(os, thread)("Thread " UINTX_FORMAT " stack guard pages removed: "
139 PTR_FORMAT "-" PTR_FORMAT ".",
140 os::current_thread_id(), p2i(low_addr), p2i(low_addr + len));
141 }
142
enable_stack_reserved_zone(bool check_if_disabled)143 void StackOverflow::enable_stack_reserved_zone(bool check_if_disabled) {
144 if (check_if_disabled && _stack_guard_state == stack_guard_reserved_disabled) {
145 return;
146 }
147 assert(_stack_guard_state == stack_guard_reserved_disabled, "inconsistent state");
148
149 // The base notation is from the stack's point of view, growing downward.
150 // We need to adjust it to work correctly with guard_memory()
151 address base = stack_reserved_zone_base() - stack_reserved_zone_size();
152
153 guarantee(base < stack_base(),"Error calculating stack reserved zone");
154 guarantee(base < os::current_stack_pointer(),"Error calculating stack reserved zone");
155
156 if (os::guard_memory((char *) base, stack_reserved_zone_size())) {
157 _stack_guard_state = stack_guard_enabled;
158 } else {
159 warning("Attempt to guard stack reserved zone failed.");
160 }
161 }
162
disable_stack_reserved_zone()163 void StackOverflow::disable_stack_reserved_zone() {
164 assert(_stack_guard_state == stack_guard_enabled, "inconsistent state");
165
166 // Simply return if called for a thread that does not use guard pages.
167 if (_stack_guard_state != stack_guard_enabled) return;
168
169 // The base notation is from the stack's point of view, growing downward.
170 // We need to adjust it to work correctly with guard_memory()
171 address base = stack_reserved_zone_base() - stack_reserved_zone_size();
172
173 if (os::unguard_memory((char *)base, stack_reserved_zone_size())) {
174 _stack_guard_state = stack_guard_reserved_disabled;
175 } else {
176 warning("Attempt to unguard stack reserved zone failed.");
177 }
178 }
179
enable_stack_yellow_reserved_zone()180 void StackOverflow::enable_stack_yellow_reserved_zone() {
181 assert(_stack_guard_state != stack_guard_unused, "must be using guard pages.");
182 assert(_stack_guard_state != stack_guard_enabled, "already enabled");
183
184 // The base notation is from the stacks point of view, growing downward.
185 // We need to adjust it to work correctly with guard_memory()
186 address base = stack_red_zone_base();
187
188 guarantee(base < stack_base(), "Error calculating stack yellow zone");
189 guarantee(base < os::current_stack_pointer(), "Error calculating stack yellow zone");
190
191 if (os::guard_memory((char *) base, stack_yellow_reserved_zone_size())) {
192 _stack_guard_state = stack_guard_enabled;
193 } else {
194 warning("Attempt to guard stack yellow zone failed.");
195 }
196 }
197
disable_stack_yellow_reserved_zone()198 void StackOverflow::disable_stack_yellow_reserved_zone() {
199 assert(_stack_guard_state != stack_guard_unused, "must be using guard pages.");
200 assert(_stack_guard_state != stack_guard_yellow_reserved_disabled, "already disabled");
201
202 // Simply return if called for a thread that does not use guard pages.
203 if (_stack_guard_state == stack_guard_unused) return;
204
205 // The base notation is from the stacks point of view, growing downward.
206 // We need to adjust it to work correctly with guard_memory()
207 address base = stack_red_zone_base();
208
209 if (os::unguard_memory((char *)base, stack_yellow_reserved_zone_size())) {
210 _stack_guard_state = stack_guard_yellow_reserved_disabled;
211 } else {
212 warning("Attempt to unguard stack yellow zone failed.");
213 }
214 }
215
enable_stack_red_zone()216 void StackOverflow::enable_stack_red_zone() {
217 // The base notation is from the stacks point of view, growing downward.
218 // We need to adjust it to work correctly with guard_memory()
219 assert(_stack_guard_state != stack_guard_unused, "must be using guard pages.");
220 address base = stack_red_zone_base() - stack_red_zone_size();
221
222 guarantee(base < stack_base(), "Error calculating stack red zone");
223 guarantee(base < os::current_stack_pointer(), "Error calculating stack red zone");
224
225 if (!os::guard_memory((char *) base, stack_red_zone_size())) {
226 warning("Attempt to guard stack red zone failed.");
227 }
228 }
229
disable_stack_red_zone()230 void StackOverflow::disable_stack_red_zone() {
231 // The base notation is from the stacks point of view, growing downward.
232 // We need to adjust it to work correctly with guard_memory()
233 assert(_stack_guard_state != stack_guard_unused, "must be using guard pages.");
234 address base = stack_red_zone_base() - stack_red_zone_size();
235 if (!os::unguard_memory((char *)base, stack_red_zone_size())) {
236 warning("Attempt to unguard stack red zone failed.");
237 }
238 }
239
reguard_stack(address cur_sp)240 bool StackOverflow::reguard_stack(address cur_sp) {
241 if (_stack_guard_state != stack_guard_yellow_reserved_disabled
242 && _stack_guard_state != stack_guard_reserved_disabled) {
243 return true; // Stack already guarded or guard pages not needed.
244 }
245
246 // Java code never executes within the yellow zone: the latter is only
247 // there to provoke an exception during stack banging. If java code
248 // is executing there, either StackShadowPages should be larger, or
249 // some exception code in c1, c2 or the interpreter isn't unwinding
250 // when it should.
251 guarantee(cur_sp > stack_reserved_zone_base(),
252 "not enough space to reguard - increase StackShadowPages");
253 if (_stack_guard_state == stack_guard_yellow_reserved_disabled) {
254 enable_stack_yellow_reserved_zone();
255 if (reserved_stack_activation() != stack_base()) {
256 set_reserved_stack_activation(stack_base());
257 }
258 } else if (_stack_guard_state == stack_guard_reserved_disabled) {
259 set_reserved_stack_activation(stack_base());
260 enable_stack_reserved_zone();
261 }
262 return true;
263 }
264
reguard_stack(void)265 bool StackOverflow::reguard_stack(void) {
266 return reguard_stack(os::current_stack_pointer());
267 }
268
reguard_stack_if_needed()269 bool StackOverflow::reguard_stack_if_needed() {
270 return !stack_guards_enabled() ? reguard_stack() : true;
271 }
272