| ... | @@ -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 the | 298 | |
| 298 | // whole region right away | 299 | 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, |
| 313 | | 314 | else => |e| return e, |
| 314 | // Map everything but the guard page as rw | 315 | }; |
| 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 | }; |
| 322 | | 359 | |
| 323 | const mmap_addr = @ptrToInt(mmap_slice.ptr); | 360 | const mmap_addr = @ptrToInt(mmap_slice.ptr); |