authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-01-05 21:16:35-08:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-01-07 11:03:37-08:00
log7bd033275e3dd0d91ec61e227a18acea6da5eecb
tree2cb02bdccdd04a317b6bb4c3928e39940a5be03e
parent1f1381a866a110953f9950d8c0c6497a2567daa0

std.Io.Threaded: implement Windows random seed fallback


1 files changed, 32 insertions(+), 19 deletions(-)

lib/std/Io/Threaded.zig+32-19
......@@ -13929,7 +13929,7 @@ fn processSpawnWindows(userdata: ?*anyopaque, options: process.SpawnOptions) pro
1392913929 };
1393013930}
1393113931
13932fn getCngHandle(t: *Threaded) !windows.HANDLE {
13932fn getCngHandle(t: *Threaded) Io.RandomSecureError!windows.HANDLE {
1393313933 {
1393413934 t.mutex.lock();
1393513935 defer t.mutex.unlock();
......@@ -13980,8 +13980,8 @@ fn getCngHandle(t: *Threaded) !windows.HANDLE {
1398013980 try syscall.checkCancel();
1398113981 continue;
1398213982 },
13983 .OBJECT_NAME_NOT_FOUND => return syscall.fail(error.Unexpected), // Observed on wine 10.0
13984 else => |status| return syscall.unexpectedNtstatus(status),
13983 .OBJECT_NAME_NOT_FOUND => return syscall.fail(error.EntropyUnavailable), // Observed on wine 10.0
13984 else => return syscall.fail(error.EntropyUnavailable),
1398513985 };
1398613986}
1398713987
......@@ -15096,23 +15096,13 @@ fn randomMainThread(t: *Threaded, buffer: []u8) void {
1509615096 randomSecure(t, &seed) catch |err| switch (err) {
1509715097 error.Canceled => unreachable,
1509815098 error.EntropyUnavailable => {
15099 seed = @splat(0);
15100 std.mem.writeInt(posix.pid_t, seed[0..@sizeOf(posix.pid_t)], posix.system.getpid(), .native);
15101 const i_1 = @sizeOf(posix.pid_t);
15102
15103 var ts: posix.timespec = undefined;
15104 const Sec = @TypeOf(ts.sec);
15105 const Nsec = @TypeOf(ts.nsec);
15106 const i_2 = i_1 + @sizeOf(Sec);
15107 const i_3 = i_2 + @sizeOf(Nsec);
15108 switch (posix.errno(posix.system.clock_gettime(.REALTIME, &ts))) {
15109 .SUCCESS => {
15110 std.mem.writeInt(Sec, seed[i_1..][0..@sizeOf(Sec)], ts.sec, .native);
15111 std.mem.writeInt(Nsec, seed[i_2..][0..@sizeOf(Nsec)], ts.nsec, .native);
15112 },
15113 else => {},
15099 @memset(&seed, 0);
15100 const aslr_addr = @intFromPtr(t);
15101 std.mem.writeInt(usize, seed[seed.len - @sizeOf(usize) ..][0..@sizeOf(usize)], aslr_addr, .native);
15102 switch (native_os) {
15103 .windows => fallbackSeedWindows(&seed),
15104 else => fallbackSeedPosix(&seed),
1511415105 }
15115 std.mem.writeInt(usize, seed[i_3..][0..@sizeOf(usize)], @intFromPtr(t), .native);
1511615106 },
1511715107 };
1511815108 }
......@@ -15122,6 +15112,29 @@ fn randomMainThread(t: *Threaded, buffer: []u8) void {
1512215112 t.csprng.rng.fill(buffer);
1512315113}
1512415114
15115fn fallbackSeedPosix(seed: *[Csprng.seed_len]u8) void {
15116 std.mem.writeInt(posix.pid_t, seed[0..@sizeOf(posix.pid_t)], posix.system.getpid(), .native);
15117 const i_1 = @sizeOf(posix.pid_t);
15118
15119 var ts: posix.timespec = undefined;
15120 const Sec = @TypeOf(ts.sec);
15121 const Nsec = @TypeOf(ts.nsec);
15122 const i_2 = i_1 + @sizeOf(Sec);
15123 switch (posix.errno(posix.system.clock_gettime(.REALTIME, &ts))) {
15124 .SUCCESS => {
15125 std.mem.writeInt(Sec, seed[i_1..][0..@sizeOf(Sec)], ts.sec, .native);
15126 std.mem.writeInt(Nsec, seed[i_2..][0..@sizeOf(Nsec)], ts.nsec, .native);
15127 },
15128 else => {},
15129 }
15130}
15131
15132fn fallbackSeedWindows(seed: *[Csprng.seed_len]u8) void {
15133 var pc: windows.LARGE_INTEGER = undefined;
15134 _ = windows.ntdll.RtlQueryPerformanceCounter(&pc);
15135 std.mem.writeInt(windows.LARGE_INTEGER, seed[0..@sizeOf(windows.LARGE_INTEGER)], pc, .native);
15136}
15137
1512515138fn randomSecure(userdata: ?*anyopaque, buffer: []u8) Io.RandomSecureError!void {
1512615139 const t: *Threaded = @ptrCast(@alignCast(userdata));
1512715140