From 80626ded3e849ba840ddd64c1713be5abb1c7449 Mon Sep 17 00:00:00 2001 From: Harald Hoyer Date: Thu, 3 Jul 2014 12:52:58 +0200 Subject: [PATCH] Generate reproducible initramfs images With the same source of files, it should be possible to generate the same image file with every dracut run. To accomplish this, we modify the timestamps of the files we generate at runtime, call gzip with "-n" and cpio with "--reproducible". The cpio --reproducible option is not yet upstream though, so if you feel like it should be then please nag at the cpio mailing list. http://lists.gnu.org/archive/html/bug-cpio/2014-08/msg00000.html --- dracut.8.asc | 3 +++ dracut.conf.5.asc | 3 +++ dracut.sh | 40 ++++++++++++++++++++++++++++++++++------ 3 files changed, 40 insertions(+), 6 deletions(-) diff --git a/dracut.8.asc b/dracut.8.asc index 51a4e9f..44530bd 100644 --- a/dracut.8.asc +++ b/dracut.8.asc @@ -412,6 +412,9 @@ will not be able to boot. Do not compress the generated initramfs. This will override any other compression options. +**--reproducible**:: + Create reproducible images. + **--list-modules**:: List all available dracut modules. diff --git a/dracut.conf.5.asc b/dracut.conf.5.asc index 0b6be6a..9259951 100644 --- a/dracut.conf.5.asc +++ b/dracut.conf.5.asc @@ -179,6 +179,9 @@ provide a valid _/etc/fstab_. *i18n_install_all=*"__{yes|no}__":: Install everything regardless of generic or hostonly mode. +*reproducible=*"__{yes|no}__":: + Create reproducible images. + Files ----- _/etc/dracut.conf_:: diff --git a/dracut.sh b/dracut.sh index 1844336..2cce85b 100755 --- a/dracut.sh +++ b/dracut.sh @@ -191,6 +191,7 @@ Creates initial ramdisk images for preloading modules --printsize Print out the module install size --sshkey [SSHKEY] Add ssh key to initramfs (use with ssh-client module) --logfile [FILE] Logfile to use (overrides configuration setting) + --reproducible Create reproducible images If [LIST] has multiple arguments, then you have to put these in quotes. @@ -372,6 +373,7 @@ rearrange_params() --long noimageifnotneeded \ --long early-microcode \ --long no-early-microcode \ + --long reproducible \ -- "$@") if (( $? != 0 )); then @@ -557,7 +559,7 @@ while :; do --printsize) printsize="yes";; --regenerate-all) regenerate_all="yes";; --noimageifnotneeded) noimageifnotneeded="yes";; - + --reproducible) reproducible_l="yes";; --) shift; break;; *) # should not even reach this point @@ -801,6 +803,8 @@ stdloglvl=$((stdloglvl + verbosity_mod_l)) [[ $early_microcode_l ]] && early_microcode=$early_microcode_l [[ $early_microcode ]] || early_microcode=no [[ $logfile_l ]] && logfile="$logfile_l" +[[ $reproducible_l ]] && reproducible="$reproducible_l" + # eliminate IFS hackery when messing with fw_dir fw_dir=${fw_dir//:/ } @@ -810,7 +814,7 @@ case $compress in bzip2) compress="bzip2 -9";; lzma) compress="lzma -9 -T0";; xz) compress="xz --check=crc32 --lzma2=dict=1MiB -T0";; - gzip) compress="gzip -9"; command -v pigz > /dev/null 2>&1 && compress="pigz -9";; + gzip) compress="gzip -n -9 --rsyncable"; command -v pigz > /dev/null 2>&1 && compress="pigz -9 -n -T -R";; lzo) compress="lzop -9";; lz4) compress="lz4 -l -9";; esac @@ -821,6 +825,8 @@ fi [[ $hostonly = yes ]] && hostonly="-h" [[ $hostonly != "-h" ]] && unset hostonly +[[ $reproducible == yes ]] && DRACUT_REPRODUCIBLE=1 + readonly TMPDIR="$tmpdir" readonly initdir="$(mktemp --tmpdir="$TMPDIR/" -d -t initramfs.XXXXXX)" [ -d "$initdir" ] || { @@ -1498,7 +1504,7 @@ if [[ $acpi_override = yes ]] && [[ -d $acpi_table_dir ]]; then mkdir -p $_dest_dir for table in $acpi_table_dir/*.aml; do dinfo " Adding ACPI table: $table" - cp $table $_dest_dir + cp -a $table $_dest_dir create_early_cpio="yes" done fi @@ -1512,15 +1518,37 @@ fi rm -f -- "$outfile" dinfo "*** Creating image file ***" +if [[ $DRACUT_REPRODUCIBLE ]]; then + find "$initdir" -newer "$dracutbasedir/dracut-functions.sh" -print0 \ + | xargs -r -0 touch -h -m -c -r "$dracutbasedir/dracut-functions.sh" + + [[ "$(cpio --help)" == *--reproducible* ]] && CPIO_REPRODUCIBLE=1 +fi + [[ "$UID" != 0 ]] && cpio_owner_root="-R 0:0" if [[ $create_early_cpio = yes ]]; then echo 1 > "$early_cpio_dir/d/early_cpio" + + if [[ $DRACUT_REPRODUCIBLE ]]; then + find "$early_cpio_dir/d" -newer "$dracutbasedir/dracut-functions.sh" -print0 \ + | xargs -r -0 touch -h -m -c -r "$dracutbasedir/dracut-functions.sh" + fi + # The microcode blob is _before_ the initramfs blob, not after - (cd "$early_cpio_dir/d"; find . -print0 | cpio --null $cpio_owner_root -H newc -o --quiet > $outfile) + ( + cd "$early_cpio_dir/d" + find . -print0 | sort -z \ + | cpio ${CPIO_REPRODUCIBLE:+--reproducible} --null $cpio_owner_root -H newc -o --quiet > $outfile + ) fi -if ! ( umask 077; cd "$initdir"; find . -print0 | cpio --null $cpio_owner_root -H newc -o --quiet | \ - $compress >> "$outfile"; ); then + +if ! ( + umask 077; cd "$initdir" + find . -print0 | sort -z \ + | cpio ${CPIO_REPRODUCIBLE:+--reproducible} --null $cpio_owner_root -H newc -o --quiet \ + | $compress >> "$outfile" + ); then dfatal "dracut: creation of $outfile failed" exit 1 fi