authorgravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2020-03-23 19:50:29+01:00
committergravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2020-03-23 19:50:29+01:00
log09a5f172f876c20e52d6cc0c634d15ddeee8f1ff
tree315019accf8a78b5989dd994624be9a5c16a0081
parentcda73c3c189924bc085d1e89a9592d6632365c90

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

1 files changed, 62 insertions(+), 25 deletions(-)

lib/std/thread.zig+62-25
...@@ -292,32 +292,69 @@ pub const Thread = struct {...@@ -292,32 +292,69 @@ pub const Thread = struct {
292 l += tls_img.alloc_size;292 l += tls_img.alloc_size;
293 }293 }
294 }294 }
295 break :blk l;295 // Round the size to the page size.
296 break :blk mem.alignForward(l, mem.page_size);
296 };297 };
297 // Map the whole stack with no rw permissions to avoid committing the298
298 // whole region right away299 const mmap_slice = mem: {
299 const mmap_slice = os.mmap(300 if (std.Target.current.os.tag != .netbsd) {
300 null,301 // Map the whole stack with no rw permissions to avoid
301 mem.alignForward(mmap_len, mem.page_size),302 // committing the whole region right away
302 os.PROT_NONE,303 const mmap_slice = os.mmap(
303 os.MAP_PRIVATE | os.MAP_ANONYMOUS,304 null,
304 -1,305 mmap_len,
305 0,306 os.PROT_NONE,
306 ) catch |err| switch (err) {307 os.MAP_PRIVATE | os.MAP_ANONYMOUS,
307 error.MemoryMappingNotSupported => unreachable,308 -1,
308 error.AccessDenied => unreachable,309 0,
309 error.PermissionDenied => unreachable,310 ) catch |err| switch (err) {
310 else => |e| return e,311 error.MemoryMappingNotSupported => unreachable,
311 };312 error.AccessDenied => unreachable,
312 errdefer os.munmap(mmap_slice);313 error.PermissionDenied => unreachable,
313314 else => |e| return e,
314 // Map everything but the guard page as rw315 };
315 os.mprotect(316 errdefer os.munmap(mmap_slice);
316 mmap_slice,317
317 os.PROT_READ | os.PROT_WRITE,318 // Map everything but the guard page as rw
318 ) catch |err| switch (err) {319 os.mprotect(
319 error.AccessDenied => unreachable,320 mmap_slice[guard_end_offset..],
320 else => |e| return e,321 os.PROT_READ | os.PROT_WRITE,
322 ) catch |err| switch (err) {
323 error.AccessDenied => unreachable,
324 else => |e| return e,
325 };
326
327 break :mem mmap_slice;
328 } else {
329 // NetBSD mprotect is very strict and doesn't allow to "upgrade"
330 // a PROT_NONE mapping to a RW one so let's allocate everything
331 // right away
332 const mmap_slice = os.mmap(
333 null,
334 mmap_len,
335 os.PROT_READ | os.PROT_WRITE,
336 os.MAP_PRIVATE | os.MAP_ANONYMOUS,
337 -1,
338 0,
339 ) catch |err| switch (err) {
340 error.MemoryMappingNotSupported => unreachable,
341 error.AccessDenied => unreachable,
342 error.PermissionDenied => unreachable,
343 else => |e| return e,
344 };
345 errdefer os.munmap(mmap_slice);
346
347 // Remap the guard page with no permissions
348 os.mprotect(
349 mmap_slice[0..guard_end_offset],
350 os.PROT_NONE,
351 ) catch |err| switch (err) {
352 error.AccessDenied => unreachable,
353 else => |e| return e,
354 };
355
356 break :mem mmap_slice;
357 }
321 };358 };
322359
323 const mmap_addr = @ptrToInt(mmap_slice.ptr);360 const mmap_addr = @ptrToInt(mmap_slice.ptr);