aboutsummaryrefslogtreecommitdiff
path: root/lib/std/start.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2020-12-17 22:51:53 -0700
committerAndrew Kelley <andrew@ziglang.org>2020-12-18 12:22:46 -0700
commit2e4b409f31352ff08dbabf350519ba0f5212218a (patch)
treee0107a3c5dc9aa81a0538c48c7adb798364df8f2 /lib/std/start.zig
parent228a0937a2bb761b3a63d98ddda5402a1f594fe8 (diff)
downloadzig-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.zig38
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'";