commit 7bd033275e3dd0d91ec61e227a18acea6da5eecb (tree)
parent 1f1381a866a110953f9950d8c0c6497a2567daa0
Author: Andrew Kelley <andrew@ziglang.org>
Date: Mon, 5 Jan 2026 21:16:35 -0800
std.Io.Threaded: implement Windows random seed fallback
Diffstat:
1 file changed, 32 insertions(+), 19 deletions(-)
diff --git a/lib/std/Io/Threaded.zig b/lib/std/Io/Threaded.zig
@@ -13929,7 +13929,7 @@ fn processSpawnWindows(userdata: ?*anyopaque, options: process.SpawnOptions) pro
};
}
-fn getCngHandle(t: *Threaded) !windows.HANDLE {
+fn getCngHandle(t: *Threaded) Io.RandomSecureError!windows.HANDLE {
{
t.mutex.lock();
defer t.mutex.unlock();
@@ -13980,8 +13980,8 @@ fn getCngHandle(t: *Threaded) !windows.HANDLE {
try syscall.checkCancel();
continue;
},
- .OBJECT_NAME_NOT_FOUND => return syscall.fail(error.Unexpected), // Observed on wine 10.0
- else => |status| return syscall.unexpectedNtstatus(status),
+ .OBJECT_NAME_NOT_FOUND => return syscall.fail(error.EntropyUnavailable), // Observed on wine 10.0
+ else => return syscall.fail(error.EntropyUnavailable),
};
}
@@ -15096,23 +15096,13 @@ fn randomMainThread(t: *Threaded, buffer: []u8) void {
randomSecure(t, &seed) catch |err| switch (err) {
error.Canceled => unreachable,
error.EntropyUnavailable => {
- seed = @splat(0);
- std.mem.writeInt(posix.pid_t, seed[0..@sizeOf(posix.pid_t)], posix.system.getpid(), .native);
- const i_1 = @sizeOf(posix.pid_t);
-
- var ts: posix.timespec = undefined;
- const Sec = @TypeOf(ts.sec);
- const Nsec = @TypeOf(ts.nsec);
- const i_2 = i_1 + @sizeOf(Sec);
- const i_3 = i_2 + @sizeOf(Nsec);
- switch (posix.errno(posix.system.clock_gettime(.REALTIME, &ts))) {
- .SUCCESS => {
- std.mem.writeInt(Sec, seed[i_1..][0..@sizeOf(Sec)], ts.sec, .native);
- std.mem.writeInt(Nsec, seed[i_2..][0..@sizeOf(Nsec)], ts.nsec, .native);
- },
- else => {},
+ @memset(&seed, 0);
+ const aslr_addr = @intFromPtr(t);
+ std.mem.writeInt(usize, seed[seed.len - @sizeOf(usize) ..][0..@sizeOf(usize)], aslr_addr, .native);
+ switch (native_os) {
+ .windows => fallbackSeedWindows(&seed),
+ else => fallbackSeedPosix(&seed),
}
- std.mem.writeInt(usize, seed[i_3..][0..@sizeOf(usize)], @intFromPtr(t), .native);
},
};
}
@@ -15122,6 +15112,29 @@ fn randomMainThread(t: *Threaded, buffer: []u8) void {
t.csprng.rng.fill(buffer);
}
+fn fallbackSeedPosix(seed: *[Csprng.seed_len]u8) void {
+ std.mem.writeInt(posix.pid_t, seed[0..@sizeOf(posix.pid_t)], posix.system.getpid(), .native);
+ const i_1 = @sizeOf(posix.pid_t);
+
+ var ts: posix.timespec = undefined;
+ const Sec = @TypeOf(ts.sec);
+ const Nsec = @TypeOf(ts.nsec);
+ const i_2 = i_1 + @sizeOf(Sec);
+ switch (posix.errno(posix.system.clock_gettime(.REALTIME, &ts))) {
+ .SUCCESS => {
+ std.mem.writeInt(Sec, seed[i_1..][0..@sizeOf(Sec)], ts.sec, .native);
+ std.mem.writeInt(Nsec, seed[i_2..][0..@sizeOf(Nsec)], ts.nsec, .native);
+ },
+ else => {},
+ }
+}
+
+fn fallbackSeedWindows(seed: *[Csprng.seed_len]u8) void {
+ var pc: windows.LARGE_INTEGER = undefined;
+ _ = windows.ntdll.RtlQueryPerformanceCounter(&pc);
+ std.mem.writeInt(windows.LARGE_INTEGER, seed[0..@sizeOf(windows.LARGE_INTEGER)], pc, .native);
+}
+
fn randomSecure(userdata: ?*anyopaque, buffer: []u8) Io.RandomSecureError!void {
const t: *Threaded = @ptrCast(@alignCast(userdata));