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 {
292292 l += tls_img.alloc_size;
293293 }
294294 }
295 break :blk l;
295 // Round the size to the page size.
296 break :blk mem.alignForward(l, mem.page_size);
296297 };
297 // Map the whole stack with no rw permissions to avoid committing the
298 // whole region right away
299 const mmap_slice = os.mmap(
300 null,
301 mem.alignForward(mmap_len, mem.page_size),
302 os.PROT_NONE,
303 os.MAP_PRIVATE | os.MAP_ANONYMOUS,
304 -1,
305 0,
306 ) catch |err| switch (err) {
307 error.MemoryMappingNotSupported => unreachable,
308 error.AccessDenied => unreachable,
309 error.PermissionDenied => unreachable,
310 else => |e| return e,
311 };
312 errdefer os.munmap(mmap_slice);
313
314 // Map everything but the guard page as rw
315 os.mprotect(
316 mmap_slice,
317 os.PROT_READ | os.PROT_WRITE,
318 ) catch |err| switch (err) {
319 error.AccessDenied => unreachable,
320 else => |e| return e,
298
299 const mmap_slice = mem: {
300 if (std.Target.current.os.tag != .netbsd) {
301 // Map the whole stack with no rw permissions to avoid
302 // committing the whole region right away
303 const mmap_slice = os.mmap(
304 null,
305 mmap_len,
306 os.PROT_NONE,
307 os.MAP_PRIVATE | os.MAP_ANONYMOUS,
308 -1,
309 0,
310 ) catch |err| switch (err) {
311 error.MemoryMappingNotSupported => unreachable,
312 error.AccessDenied => unreachable,
313 error.PermissionDenied => unreachable,
314 else => |e| return e,
315 };
316 errdefer os.munmap(mmap_slice);
317
318 // Map everything but the guard page as rw
319 os.mprotect(
320 mmap_slice[guard_end_offset..],
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 }
321358 };
322359
323360 const mmap_addr = @ptrToInt(mmap_slice.ptr);