From ca8f13e11d422fa01bc031ff0610442b82ea6b65 Mon Sep 17 00:00:00 2001 From: Daniel Edgecumbe Date: Sat, 7 Sep 2019 11:15:26 +0100 Subject: mkinitcpio: Produce reproducible initramfs images We achieve this by stripping timestamps from within the filesystem, and by using a pipeline to strip inodes from the cpio archive. It functions for at least the 'gzip', 'xz', 'bzip2', 'lz4' and 'cat' compressors. The 'lzop' compressor embeds a runtime timestamp. Motivation: https://reproducible-builds.org Signed-off-by: Daniel Edgecumbe --- man/mkinitcpio.8.txt | 16 ++++++++++++++++ mkinitcpio | 23 +++++++++++++---------- 2 files changed, 29 insertions(+), 10 deletions(-) diff --git a/man/mkinitcpio.8.txt b/man/mkinitcpio.8.txt index 931a167..6a9b59e 100644 --- a/man/mkinitcpio.8.txt +++ b/man/mkinitcpio.8.txt @@ -301,6 +301,22 @@ These are only the variables that the core of mkinitcpio honor. Additional hooks may look for other environment variables and should be documented by the help output for the hook. +Reproducibility +--------------- +mkinitcpio aims to create reproducible initramfs images by default. + +This means that two subsequent runs of mkinitcpio should produce two files +that are identical at the binary level. + +Timestamps within the initramfs are set to the Unix epoch of 1970-01-01. + +Note that in order for the build to be fully reproducible, the compressor +specified (e.g. gzip, xz) must also produce reproducible archives. At the time +of writing, as an inexhaustive example, the lzop compressor is incapable of +producing reproducible archives due to the insertion of a runtime timestamp. + +More information can be found at https://reproducible-builds.org. + Files ----- '/etc/mkinitcpio.conf':: diff --git a/mkinitcpio b/mkinitcpio index 5583d07..db7a61a 100755 --- a/mkinitcpio +++ b/mkinitcpio @@ -211,25 +211,28 @@ build_image() { ;; esac - cpio_opts=('-0' '-o' '-H' 'newc') - (( _optquiet )) && cpio_opts+=('--quiet') - if (( EUID != 0 )); then - warning 'Not building as root, ownership cannot be preserved' - cpio_opts+=('-R' '0:0') - fi - pushd "$BUILDROOT" >/dev/null - find . -mindepth 1 -printf '%P\0' | - LANG=C bsdcpio "${cpio_opts[@]}" | + + # Reproducibility: set all timestamps to 0 + find . -mindepth 1 -execdir touch -hcd "@0" "{}" + + + find . -mindepth 1 -printf '%P\0' | sort -z | + LANG=C bsdtar --null -cnf - -T - | + LANG=C bsdtar --uid 0 --gid 0 --null -cf - --format=newc @- | $compress "${COMPRESSION_OPTIONS[@]}" > "$out" + pipesave=("${PIPESTATUS[@]}") # save immediately popd >/dev/null if (( pipesave[0] )); then errmsg="find reported an error" elif (( pipesave[1] )); then - errmsg="bsdcpio reported an error" + errmsg="sort reported an error" elif (( pipesave[2] )); then + errmsg="bsdtar (step 1) reported an error" + elif (( pipesave[3] )); then + errmsg="bsdtar (step 2) reported an error" + elif (( pipesave[4] )); then errmsg="$compress reported an error" fi -- cgit v1.2.3-24-g4f1b