@@ -209,6 +209,7 @@ pub mod guard {
209
209
pub type Guard = Range < usize > ;
210
210
pub unsafe fn current ( ) -> Option < Guard > { None }
211
211
pub unsafe fn init ( ) -> Option < Guard > { None }
212
+ pub unsafe fn deinit ( ) { }
212
213
}
213
214
214
215
@@ -222,8 +223,8 @@ pub mod guard {
222
223
#[ cfg_attr( test, allow( dead_code) ) ]
223
224
pub mod guard {
224
225
use libc;
225
- use libc:: mmap;
226
- use libc:: { PROT_NONE , MAP_PRIVATE , MAP_ANON , MAP_FAILED , MAP_FIXED } ;
226
+ use libc:: { mmap, mprotect } ;
227
+ use libc:: { PROT_NONE , PROT_READ , PROT_WRITE , MAP_PRIVATE , MAP_ANON , MAP_FAILED , MAP_FIXED } ;
227
228
use ops:: Range ;
228
229
use sys:: os;
229
230
@@ -284,10 +285,10 @@ pub mod guard {
284
285
ret
285
286
}
286
287
287
- pub unsafe fn init ( ) -> Option < Guard > {
288
- PAGE_SIZE = os :: page_size ( ) ;
289
-
290
- let mut stackaddr = get_stack_start ( ) ?;
288
+ // Precondition: PAGE_SIZE is initialized.
289
+ unsafe fn get_stack_start_aligned ( ) -> Option < * mut libc :: c_void > {
290
+ assert ! ( PAGE_SIZE != 0 ) ;
291
+ let stackaddr = get_stack_start ( ) ?;
291
292
292
293
// Ensure stackaddr is page aligned! A parent process might
293
294
// have reset RLIMIT_STACK to be non-page aligned. The
@@ -296,10 +297,17 @@ pub mod guard {
296
297
// page-aligned, calculate the fix such that stackaddr <
297
298
// new_page_aligned_stackaddr < stackaddr + stacksize
298
299
let remainder = ( stackaddr as usize ) % PAGE_SIZE ;
299
- if remainder != 0 {
300
- stackaddr = ( ( stackaddr as usize ) + PAGE_SIZE - remainder)
301
- as * mut libc:: c_void ;
302
- }
300
+ Some ( if remainder == 0 {
301
+ stackaddr
302
+ } else {
303
+ ( ( stackaddr as usize ) + PAGE_SIZE - remainder) as * mut libc:: c_void
304
+ } )
305
+ }
306
+
307
+ pub unsafe fn init ( ) -> Option < Guard > {
308
+ PAGE_SIZE = os:: page_size ( ) ;
309
+
310
+ let stackaddr = get_stack_start_aligned ( ) ?;
303
311
304
312
if cfg ! ( target_os = "linux" ) {
305
313
// Linux doesn't allocate the whole stack right away, and
@@ -336,6 +344,26 @@ pub mod guard {
336
344
}
337
345
}
338
346
347
+ pub unsafe fn deinit ( ) {
348
+ if !cfg ! ( target_os = "linux" ) {
349
+ if let Some ( stackaddr) = get_stack_start_aligned ( ) {
350
+ // Remove the protection on the guard page.
351
+ // FIXME: we cannot unmap the page, because when we mmap()
352
+ // above it may be already mapped by the OS, which we can't
353
+ // detect from mmap()'s return value. If we unmap this page,
354
+ // it will lead to failure growing stack size on platforms like
355
+ // macOS. Instead, just restore the page to a writable state.
356
+ // This ain't Linux, so we probably don't need to care about
357
+ // execstack.
358
+ let result = mprotect ( stackaddr, PAGE_SIZE , PROT_READ | PROT_WRITE ) ;
359
+
360
+ if result != 0 {
361
+ panic ! ( "unable to reset the guard page" ) ;
362
+ }
363
+ }
364
+ }
365
+ }
366
+
339
367
#[ cfg( any( target_os = "macos" ,
340
368
target_os = "bitrig" ,
341
369
target_os = "openbsd" ,
0 commit comments