authorgravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2019-05-28 18:26:38+02:00
committergravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2019-05-28 18:26:38+02:00
log381f845287c8aef25a5351be81dfdfad055f0785
tree521a88bcbe327834ed8e696026082f5cdb63b448
parent594366a4824d7e65485033ca1002d8635ff6fbf9

Add a guard page for each thread


1 files changed, 24 insertions(+), 9 deletions(-)

std/thread.zig+24-9
...@@ -223,15 +223,17 @@ pub const Thread = struct {...@@ -223,15 +223,17 @@ pub const Thread = struct {
223 }223 }
224 };224 };
225225
226 const MAP_GROWSDOWN = if (os.linux.is_the_target) os.linux.MAP_GROWSDOWN else 0;226 var guard_end_offset: usize = undefined;
227
228 var stack_end_offset: usize = undefined;227 var stack_end_offset: usize = undefined;
229 var thread_start_offset: usize = undefined;228 var thread_start_offset: usize = undefined;
230 var context_start_offset: usize = undefined;229 var context_start_offset: usize = undefined;
231 var tls_start_offset: usize = undefined;230 var tls_start_offset: usize = undefined;
232 const mmap_len = blk: {231 const mmap_len = blk: {
233 // First in memory will be the stack, which grows downwards.232 var l: usize = mem.page_size;
234 var l: usize = mem.alignForward(default_stack_size, 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 stack_end_offset = l;237 stack_end_offset = l;
236 // Above the stack, so that it can be in the same mmap call, put the Thread object.238 // Above the stack, so that it can be in the same mmap call, put the Thread object.
237 l = mem.alignForward(l, @alignOf(Thread));239 l = mem.alignForward(l, @alignOf(Thread));
...@@ -253,20 +255,33 @@ pub const Thread = struct {...@@ -253,20 +255,33 @@ pub const Thread = struct {
253 }255 }
254 break :blk l;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 const mmap_slice = os.mmap(260 const mmap_slice = os.mmap(
257 null,261 null,
258 mem.alignForward(mmap_len, mem.page_size),262 mem.alignForward(mmap_len, mem.page_size),
259 os.PROT_READ | os.PROT_WRITE,263 os.PROT_NONE,
260 os.MAP_PRIVATE | os.MAP_ANONYMOUS | MAP_GROWSDOWN,264 os.MAP_PRIVATE | os.MAP_ANONYMOUS,
261 -1,265 -1,
262 0,266 0,
263 ) catch |err| switch (err) {267 ) catch |err| switch (err) {
264 error.MemoryMappingNotSupported => unreachable, // no file descriptor268 error.MemoryMappingNotSupported => unreachable,
265 error.AccessDenied => unreachable, // no file descriptor269 error.AccessDenied => unreachable,
266 error.PermissionDenied => unreachable, // no file descriptor270 error.PermissionDenied => unreachable,
267 else => |e| return e,271 else => |e| return e,
268 };272 };
269 errdefer os.munmap(mmap_slice);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 const mmap_addr = @ptrToInt(mmap_slice.ptr);285 const mmap_addr = @ptrToInt(mmap_slice.ptr);
271286
272 const thread_ptr = @alignCast(@alignOf(Thread), @intToPtr(*Thread, mmap_addr + thread_start_offset));287 const thread_ptr = @alignCast(@alignOf(Thread), @intToPtr(*Thread, mmap_addr + thread_start_offset));