zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

commit 09a5f172f876c20e52d6cc0c634d15ddeee8f1ff (tree)
parent cda73c3c189924bc085d1e89a9592d6632365c90
Author: LemonBoy <thatlemon@gmail.com>
Date:   Mon, 23 Mar 2020 19:50:29 +0100

std: Different thread stack allocation for NetBSD

* NetBSD is stricter than other OSs and doesn't allow mprotect to mark a
  non-accessible region as RW
* Fix mprotect call over the whole stack, oops

Diffstat:
Mlib/std/thread.zig | 87++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------
1 file changed, 62 insertions(+), 25 deletions(-)

diff --git a/lib/std/thread.zig b/lib/std/thread.zig @@ -292,32 +292,69 @@ pub const Thread = struct { l += tls_img.alloc_size; } } - break :blk l; + // Round the size to the page size. + break :blk mem.alignForward(l, mem.page_size); }; - // Map the whole stack with no rw permissions to avoid committing the - // whole region right away - const mmap_slice = os.mmap( - null, - mem.alignForward(mmap_len, mem.page_size), - os.PROT_NONE, - os.MAP_PRIVATE | os.MAP_ANONYMOUS, - -1, - 0, - ) catch |err| switch (err) { - error.MemoryMappingNotSupported => unreachable, - error.AccessDenied => unreachable, - error.PermissionDenied => unreachable, - else => |e| return e, - }; - errdefer os.munmap(mmap_slice); - - // Map everything but the guard page as rw - os.mprotect( - mmap_slice, - os.PROT_READ | os.PROT_WRITE, - ) catch |err| switch (err) { - error.AccessDenied => unreachable, - else => |e| return e, + + const mmap_slice = mem: { + if (std.Target.current.os.tag != .netbsd) { + // Map the whole stack with no rw permissions to avoid + // committing the whole region right away + const mmap_slice = os.mmap( + null, + mmap_len, + os.PROT_NONE, + os.MAP_PRIVATE | os.MAP_ANONYMOUS, + -1, + 0, + ) catch |err| switch (err) { + error.MemoryMappingNotSupported => unreachable, + error.AccessDenied => unreachable, + error.PermissionDenied => unreachable, + else => |e| return e, + }; + errdefer os.munmap(mmap_slice); + + // Map everything but the guard page as rw + os.mprotect( + mmap_slice[guard_end_offset..], + os.PROT_READ | os.PROT_WRITE, + ) catch |err| switch (err) { + error.AccessDenied => unreachable, + else => |e| return e, + }; + + break :mem mmap_slice; + } else { + // NetBSD mprotect is very strict and doesn't allow to "upgrade" + // a PROT_NONE mapping to a RW one so let's allocate everything + // right away + const mmap_slice = os.mmap( + null, + mmap_len, + os.PROT_READ | os.PROT_WRITE, + os.MAP_PRIVATE | os.MAP_ANONYMOUS, + -1, + 0, + ) catch |err| switch (err) { + error.MemoryMappingNotSupported => unreachable, + error.AccessDenied => unreachable, + error.PermissionDenied => unreachable, + else => |e| return e, + }; + errdefer os.munmap(mmap_slice); + + // Remap the guard page with no permissions + os.mprotect( + mmap_slice[0..guard_end_offset], + os.PROT_NONE, + ) catch |err| switch (err) { + error.AccessDenied => unreachable, + else => |e| return e, + }; + + break :mem mmap_slice; + } }; const mmap_addr = @ptrToInt(mmap_slice.ptr);