@@ -223,15 +223,17 @@ pub const Thread = struct {
223
223
}
224
224
};
225
225
226
- const MAP_GROWSDOWN = if (os .linux .is_the_target ) os .linux .MAP_GROWSDOWN else 0 ;
227
-
226
+ var guard_end_offset : usize = undefined ;
228
227
var stack_end_offset : usize = undefined ;
229
228
var thread_start_offset : usize = undefined ;
230
229
var context_start_offset : usize = undefined ;
231
230
var tls_start_offset : usize = undefined ;
232
231
const mmap_len = blk : {
233
- // First in memory will be the stack, which grows downwards.
234
- var l : usize = mem .alignForward (default_stack_size , mem .page_size );
232
+ var l : usize = mem .page_size ;
233
+ // Allocate a guard page right after the end of the stack region
234
+ guard_end_offset = l ;
235
+ // The stack itself, which grows downwards.
236
+ l = mem .alignForward (l + default_stack_size , mem .page_size );
235
237
stack_end_offset = l ;
236
238
// Above the stack, so that it can be in the same mmap call, put the Thread object.
237
239
l = mem .alignForward (l , @alignOf (Thread ));
@@ -253,20 +255,33 @@ pub const Thread = struct {
253
255
}
254
256
break :blk l ;
255
257
};
258
+ // Map the whole stack with no rw permissions to avoid committing the
259
+ // whole region right away
256
260
const mmap_slice = os .mmap (
257
261
null ,
258
262
mem .alignForward (mmap_len , mem .page_size ),
259
- os .PROT_READ | os . PROT_WRITE ,
260
- os .MAP_PRIVATE | os .MAP_ANONYMOUS | MAP_GROWSDOWN ,
263
+ os .PROT_NONE ,
264
+ os .MAP_PRIVATE | os .MAP_ANONYMOUS ,
261
265
-1 ,
262
266
0 ,
263
267
) catch | err | switch (err ) {
264
- error .MemoryMappingNotSupported = > unreachable , // no file descriptor
265
- error .AccessDenied = > unreachable , // no file descriptor
266
- error .PermissionDenied = > unreachable , // no file descriptor
268
+ error .MemoryMappingNotSupported = > unreachable ,
269
+ error .AccessDenied = > unreachable ,
270
+ error .PermissionDenied = > unreachable ,
267
271
else = > | e | return e ,
268
272
};
269
273
errdefer os .munmap (mmap_slice );
274
+
275
+ // Map everything but the guard page as rw
276
+ os .mprotect (
277
+ mmap_slice ,
278
+ os .PROT_READ | os .PROT_WRITE ,
279
+ ) catch | err | switch (err ) {
280
+ error .OutOfMemory = > unreachable ,
281
+ error .AccessDenied = > unreachable ,
282
+ else = > | e | return e ,
283
+ };
284
+
270
285
const mmap_addr = @ptrToInt (mmap_slice .ptr );
271
286
272
287
const thread_ptr = @alignCast (@alignOf (Thread ), @intToPtr (* Thread , mmap_addr + thread_start_offset ));
0 commit comments