aboutsummaryrefslogtreecommitdiff
path: root/lib/std/os.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2020-12-18 15:38:38 -0700
committerAndrew Kelley <andrew@ziglang.org>2020-12-18 15:54:01 -0700
commit53987c932c9d62cc9cdae3d523fb62756ce83ca9 (patch)
tree280817d390ef900cf590c40f47cca4230b354b0e /lib/std/os.zig
parent2b8dcc76eba92ad44bd88756218de8d2bd8a1c10 (diff)
downloadzig-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.zig48
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),
+ }
+}