diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2020-12-17 22:51:53 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2020-12-18 12:22:46 -0700 |
| commit | 2e4b409f31352ff08dbabf350519ba0f5212218a (patch) | |
| tree | e0107a3c5dc9aa81a0538c48c7adb798364df8f2 /lib/std/start.zig | |
| parent | 228a0937a2bb761b3a63d98ddda5402a1f594fe8 (diff) | |
| download | zig-2e4b409f31352ff08dbabf350519ba0f5212218a.tar.gz zig-2e4b409f31352ff08dbabf350519ba0f5212218a.zip | |
std: tlcsprng: cleanups & improvements
* get rid of the pointless fences
* make seed_len 16 instead of 32, which is accurate since it was
already padding the rest anyway; now we do 1 pad instead of 2.
* secureZero to clear the AT_RANDOM auxval
* add a flag root source files can use to disable the start code. This
is in case people want to opt out of the initialization when they
don't depend on it.
Diffstat (limited to 'lib/std/start.zig')
| -rw-r--r-- | lib/std/start.zig | 38 |
1 files changed, 20 insertions, 18 deletions
diff --git a/lib/std/start.zig b/lib/std/start.zig index d3065c7719..25c578c0ef 100644 --- a/lib/std/start.zig +++ b/lib/std/start.zig @@ -206,7 +206,6 @@ fn posixCallMainAndExit() noreturn { // Do this as early as possible, the aux vector is needed if (builtin.position_independent_executable) { @import("os/linux/start_pie.zig").apply_relocations(); - @fence(.SeqCst); } // Initialize the TLS area. We do a runtime check here to make sure @@ -215,10 +214,9 @@ fn posixCallMainAndExit() noreturn { const is_dynamic = @import("dynamic_library.zig").get_DYNAMIC() != null; if (!is_dynamic) { std.os.linux.tls.initStaticTLS(); - @fence(.SeqCst); } - { + if (!@hasDecl(root, "use_AT_RANDOM_auxval") or root.use_AT_RANDOM_auxval) { // Initialize the per-thread CSPRNG since Linux gave us the handy-dandy // AT_RANDOM. This depends on the TLS initialization above. var i: usize = 0; @@ -226,19 +224,7 @@ fn posixCallMainAndExit() noreturn { switch (auxv[i].a_type) { std.elf.AT_RANDOM => { // "The address of sixteen bytes containing a random value." - const addr = auxv[i].a_un.a_val; - if (addr == 0) break; - const ptr = @intToPtr(*[16]u8, addr); - var seed: [32]u8 = undefined; - seed[0..16].* = ptr.*; - seed[16..].* = ptr.*; - tlcsprng.init(seed); - // Overwrite AT_RANDOM after we use it, otherwise our secure - // seed is sitting in memory ready for some other code in the - // program to reuse, and hence break our security. - // We play nice by refreshing it with fresh random bytes - // rather than clearing it. - std.crypto.random.bytes(ptr); + initCryptoSeedFromAuxVal(auxv[i].a_un.a_val); break; }, else => continue, @@ -281,15 +267,31 @@ fn callMainWithArgs(argc: usize, argv: [*][*:0]u8, envp: [][*:0]u8) u8 { } fn main(c_argc: i32, c_argv: [*][*:0]u8, c_envp: [*:null]?[*:0]u8) callconv(.C) i32 { - // We do not attempt to initialize tlcsprng from AT_RANDOM here because - // libc owns the start code, not us, and therefore libc ows the random bytes + // By default, we do not attempt to initialize tlcsprng from AT_RANDOM here because + // libc owns the start code, not us, and therefore libc owns the random bytes // from AT_RANDOM. + if (builtin.os.tag == .linux and + @hasDecl(root, "use_AT_RANDOM_auxval") and + root.use_AT_RANDOM_auxval) + { + initCryptoSeedFromAuxVal(std.c.getauxval(std.elf.AT_RANDOM)); + } var env_count: usize = 0; while (c_envp[env_count] != null) : (env_count += 1) {} const envp = @ptrCast([*][*:0]u8, c_envp)[0..env_count]; return @call(.{ .modifier = .always_inline }, callMainWithArgs, .{ @intCast(usize, c_argc), c_argv, envp }); } +fn initCryptoSeedFromAuxVal(addr: usize) void { + if (addr == 0) return; + const ptr = @intToPtr(*[16]u8, addr); + tlcsprng.init(ptr.*); + // Clear AT_RANDOM after we use it, otherwise our secure + // seed is sitting in memory ready for some other code in the + // program to reuse, and hence break our security. + std.crypto.utils.secureZero(u8, ptr); +} + // General error message for a malformed return type const bad_main_ret = "expected return type of main to be 'void', '!void', 'noreturn', 'u8', or '!u8'"; |
