Skip to content

Commit 381f845

Browse files
committed
Add a guard page for each thread
1 parent 594366a commit 381f845

File tree

1 file changed

+24
-9
lines changed

1 file changed

+24
-9
lines changed

std/thread.zig

+24-9
Original file line numberDiff line numberDiff line change
@@ -223,15 +223,17 @@ pub const Thread = struct {
223223
}
224224
};
225225

226-
const MAP_GROWSDOWN = if (os.linux.is_the_target) os.linux.MAP_GROWSDOWN else 0;
227-
226+
var guard_end_offset: usize = undefined;
228227
var stack_end_offset: usize = undefined;
229228
var thread_start_offset: usize = undefined;
230229
var context_start_offset: usize = undefined;
231230
var tls_start_offset: usize = undefined;
232231
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);
235237
stack_end_offset = l;
236238
// Above the stack, so that it can be in the same mmap call, put the Thread object.
237239
l = mem.alignForward(l, @alignOf(Thread));
@@ -253,20 +255,33 @@ pub const Thread = struct {
253255
}
254256
break :blk l;
255257
};
258+
// Map the whole stack with no rw permissions to avoid committing the
259+
// whole region right away
256260
const mmap_slice = os.mmap(
257261
null,
258262
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,
261265
-1,
262266
0,
263267
) 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,
267271
else => |e| return e,
268272
};
269273
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+
270285
const mmap_addr = @ptrToInt(mmap_slice.ptr);
271286

272287
const thread_ptr = @alignCast(@alignOf(Thread), @intToPtr(*Thread, mmap_addr + thread_start_offset));

0 commit comments

Comments
 (0)