diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2020-12-18 15:38:38 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2020-12-18 15:54:01 -0700 |
| commit | 53987c932c9d62cc9cdae3d523fb62756ce83ca9 (patch) | |
| tree | 280817d390ef900cf590c40f47cca4230b354b0e /lib/std/os.zig | |
| parent | 2b8dcc76eba92ad44bd88756218de8d2bd8a1c10 (diff) | |
| download | zig-53987c932c9d62cc9cdae3d523fb62756ce83ca9.tar.gz zig-53987c932c9d62cc9cdae3d523fb62756ce83ca9.zip | |
std.crypto.random: introduce fork safety
Everybody gets what they want!
* AT_RANDOM is completely ignored.
* On Linux, MADV_WIPEONFORK is used to provide fork safety.
* On pthread systems, `pthread_atfork` is used to provide fork safety.
* For systems that do not have the capability to provide fork safety,
the implementation falls back to calling getrandom() every time.
* If madvise is unavailable or returns an error, or pthread_atfork
fails for whatever reason, it falls back to calling getrandom() every
time.
* Applications may choose to opt-out of fork safety.
* Applications may choose to opt-in to unconditionally calling
getrandom() for every call to std.crypto.random.fillFn.
* Added `std.meta.globalOption`.
* Added `std.os.madvise` and related bits.
* Bumped up the size of the main thread TLS buffer. See the comment
there for justification.
* Simpler hot path in TLS initialization.
Diffstat (limited to 'lib/std/os.zig')
| -rw-r--r-- | lib/std/os.zig | 48 |
1 files changed, 48 insertions, 0 deletions
diff --git a/lib/std/os.zig b/lib/std/os.zig index b42cdf756f..fb67b89d0a 100644 --- a/lib/std/os.zig +++ b/lib/std/os.zig @@ -5845,3 +5845,51 @@ pub fn setrlimit(resource: rlimit_resource, limits: rlimit) SetrlimitError!void else => |err| return unexpectedErrno(err), } } + +pub const MadviseError = error{ + /// advice is MADV_REMOVE, but the specified address range is not a shared writable mapping. + AccessDenied, + /// advice is MADV_HWPOISON, but the caller does not have the CAP_SYS_ADMIN capability. + PermissionDenied, + /// A kernel resource was temporarily unavailable. + SystemResources, + /// One of the following: + /// * addr is not page-aligned or length is negative + /// * advice is not valid + /// * advice is MADV_DONTNEED or MADV_REMOVE and the specified address range + /// includes locked, Huge TLB pages, or VM_PFNMAP pages. + /// * advice is MADV_MERGEABLE or MADV_UNMERGEABLE, but the kernel was not + /// configured with CONFIG_KSM. + /// * advice is MADV_FREE or MADV_WIPEONFORK but the specified address range + /// includes file, Huge TLB, MAP_SHARED, or VM_PFNMAP ranges. + InvalidSyscall, + /// (for MADV_WILLNEED) Paging in this area would exceed the process's + /// maximum resident set size. + WouldExceedMaximumResidentSetSize, + /// One of the following: + /// * (for MADV_WILLNEED) Not enough memory: paging in failed. + /// * Addresses in the specified range are not currently mapped, or + /// are outside the address space of the process. + OutOfMemory, + /// The madvise syscall is not available on this version and configuration + /// of the Linux kernel. + MadviseUnavailable, + /// The operating system returned an undocumented error code. + Unexpected, +}; + +/// Give advice about use of memory. +/// This syscall is optional and is sometimes configured to be disabled. +pub fn madvise(ptr: [*]align(mem.page_size) u8, length: usize, advice: u32) MadviseError!void { + switch (errno(system.madvise(ptr, length, advice))) { + 0 => return, + EACCES => return error.AccessDenied, + EAGAIN => return error.SystemResources, + EBADF => unreachable, // The map exists, but the area maps something that isn't a file. + EINVAL => return error.InvalidSyscall, + EIO => return error.WouldExceedMaximumResidentSetSize, + ENOMEM => return error.OutOfMemory, + ENOSYS => return error.MadviseUnavailable, + else => |err| return unexpectedErrno(err), + } +} |
