Reproducible builds for PaX/Grsecurity
A series of scripts are created to do reproducible builds for Linux kernel with PaX/Grsecurity patch set.
Thanks to:
- PaX/Grsecurity
- Mempo project
- Debian GNU/Linux Community
- Shawn C[a.k.a “Citypw”]
- Linux From Scratch
Without the contributions of the projects, community and people, the scripts cannot be accomplished.
The project’s GitHub repo is at https://github.com/hardenedlinux/grsecurity-reproducible-build .
Why do reproducible builds?
Reproducible builds are important to the binary’s reliability.
With reproducible builds, anyone can recreate the binary, so it can be proved that the source code provided is really the source code used to build the binary, and no more backdoors (either manually inserted into the code or inserted by hijacked toolchain) is contained in the binary.
Spirits of the build scripts
The spirits of “cross toolchain” are from the Linux From Scratch and Cross Linux From Scratch project. They’re trying to build a runnable full Linux system without being impacted by the host system. For the independence of the target system, they used a “x86 to x86 cross toolchain” to build the target system.
The key to the reproducible kernel builds
Fixed environment
Fixed C Compiler
The C compiler usually acts differently for different version. So to deterministically build a kernel, a fixed C compiler version is needed.
In order to provided the fixed-version C compiler independently (have no effect from the host’s C compiler and libc), a “cross-compiler” is built here. (To build the cross-compiler, a different triplet, “x86_64-kernelonly-linux-gnu” is used)
As the cross-compiler is used only to build the kernel, the cross libc and stage2 GCC is not built, only a stage1 GCC is built. This is barely enough for kernel building.
Note: To run the built kernel, the cross-compiler is NOT needed.
Fixed directory
In order to build the kernel deterministically, a fixed build directory is requied.
Currently the build script used “/kbuild” as the fixed directory.
Fixed build info
Build fingerprint
The volatile build info used in the scripts is written to a file named “fingerprint.sh”.
It contains two variables:
-
KERNEL_TIMESTAMP: A timestamp used in kernel building process
-
GRSEC_RANDSTRUCT_SEED: the random seed of struct randomize.
Machine info
The kernel will contain some info (hostname, username) retrieved from the build machine.
But, fortunately, they can be overwritten with environment variables: KBUILD_BUILD_USER and KBUILD_BUILD_HOST.
Kill the timestamps
Kernel building needs a timestamp. It can be passed to the kernel build system with the environment variable “KBUILD_BUILD_TIMESTAMP”.
Debian packaging needs also a timestamp (for the debian changelog). In order to remove it, the “builddeb” script in the kernel source is patched.
Gzip contains also some timestamps. The compression in the kernel has already no timestamps, as a patch have been merged into the kernel source for deterministic build. The compression in the “builddeb” script is also patched, to pass the “-n” option to Gzip, which disabled the internal timestamp of Gzip.
Config options to be noted
CONFIG_MODULE_SIG (Module signature verification)
When this option is enabled, there will be a key embedded into the kernel, which is used to sign modules.
The key is either generated at build time (from /dev/random, which made the key not reproducible), or pre-generated (which made the signing system useless, as the key-pair will be provided to anyone who wants to verify the build).
Although support for pre-generated key-pair can be implemented, it’s not implemented now.
So the option should be DISABLED now.
TODO: support for external pre-generated key-pair.
CONFIG_PAX_LATENT_ENTROPY (Generate some entropy during boot and runtime)
When this option is enabled, the generated binary code will contain some random bits generated by GCC at build time, as entropy.
Enabling this option will lead to irreproducible builds.
So the option should be DISABLED now.
It’s noticed that the GCC plugin have appeared in linux-next tree now. Maybe there will soon be a deterministic way to use it.
CONFIG_GRKERNSEC_RANDSTRUCT (Randomize layout of sensitive kernel structures)
When this option is enabled, the generated binary will have sensitive kernel structures randomized.
It uses a seed from /dev/urandom at build time, currently the scripts have already hacked the seed generation process. Now the seed is part of the build fingerprint.
So the option is now safe to ENABLE.
Reference
- http://www.dwheeler.com/trusting-trust/
- https://github.com/mempo/mempo-kernel
- https://wiki.debian.org/Mempo
- https://wiki.debian.org/ReproducibleBuilds