diff --git a/build-kernel.py b/build-kernel.py index d2f2a07..1bc0d2d 100755 --- a/build-kernel.py +++ b/build-kernel.py @@ -1,4 +1,5 @@ #!/usr/bin/env python3 +import hashlib import os import re import shutil @@ -17,6 +18,61 @@ def render_template(filename, context): Path(filename).write_text(rendered_content) +def derive_seed(release, purpose): + """ + Because our kernels are public, using a random seed doesn't provide any hardening + but it interferes with reproducibility. Instead we use a deterministic seed. + """ + return hashlib.sha256(f"{release}-{purpose}".encode()).hexdigest() + + +def pin_build_seeds(srcdir, release): + """ + Override various scripts that reach for randomness with values based on our + deterministic seed instead. + """ + print("Pinning build seeds for", release) + # randstruct: scripts/basic/Makefile calls this with the seed file and the + # hashed-seed header as $1 and $2. Same 64 hex chars as `od -t x8 -N 32`. + randstruct = srcdir / "scripts/gen-randstruct-seed.sh" + if not randstruct.exists(): + print(f"ERROR: {randstruct} not found, cannot pin the randstruct seed") + sys.exit(1) + randstruct.write_text( + "#!/bin/sh\n" + "# SPDX-License-Identifier: GPL-2.0\n" + "# Seed pinned by kernel-builder for reproducibility; see derive_seed().\n" + f'SEED="{derive_seed(release, "randstruct")}"\n' + 'echo "$SEED" > "$1"\n' + 'HASH=$(echo -n "$SEED" | sha256sum | cut -d" " -f1)\n' + 'echo "#define RANDSTRUCT_HASHED_SEED \\"$HASH\\"" > "$2"\n' + ) + + # type_canary (grsecurity only): writes the header to stdout. The original + # emits four ULL words from 32 bytes of urandom, then an 8-char hash of them. + type_canary = srcdir / "scripts/gcc-plugins/gen-type_canary.sh" + if type_canary.exists(): + digest = bytes.fromhex(derive_seed(release, "type_canary")) + words = ", ".join( + f"0x{int.from_bytes(digest[i : i + 8], 'big'):016x}ULL" for i in range(0, 32, 8) + ) + type_canary.write_text( + "#!/bin/sh\n" + "# SPDX-License-Identifier: GPL-2.0\n" + "# Seed pinned by kernel-builder for reproducibility; see derive_seed().\n" + f'RAND=" {words} "\n' + 'HASH=$(echo "$RAND" | sha256sum | cut -d" " -f1 | tr -d " \\n" | cut -c1-8)\n' + "cat<