make-initrd: create reproducible initrds

To achieve reproducible results, `cpio` archive members are added in
sorted order and inodes renumbered.

The `cpio-clean.pl` script is made obsolete by setting mtimes via
`touch` & using `cpio --reproducible`.  Suggested by @dezgeg in
https://github.com/NixOS/nixpkgs/pull/21273#issuecomment-268116605.

Note that using `--reproducible` means that initial ramdisk creation now
requires at least `cpio` version 2.12 (released in 2015).
This commit is contained in:
Joachim Fasting 2016-12-20 10:27:13 +01:00 committed by Joachim F
parent 49e3190efa
commit 5a8147479e
3 changed files with 5 additions and 22 deletions

View file

@ -1,17 +0,0 @@
use strict;
# Make inode number, link info and mtime consistent in order to get a consistent hash.
#
# Author: Alexander Kjeldaas <ak@formalprivacy.com>
use Archive::Cpio;
my $cpio = Archive::Cpio->new;
my $IN = \*STDIN;
my $ino = 1;
$cpio->read_with_handler($IN, sub {
my ($e) = @_;
$e->{mtime} = 1;
$cpio->write_one(\*STDOUT, $e);
});
$cpio->write_trailer(\*STDOUT);

View file

@ -12,10 +12,10 @@
# `contents = {object = ...; symlink = /init;}' is a typical
# argument.
{ stdenv, perl, perlArchiveCpio, cpio, contents, ubootChooser, compressor, prepend }:
{ stdenv, perl, cpio, contents, ubootChooser, compressor, prepend }:
let
inputsFun = ubootName : [perl cpio perlArchiveCpio ]
inputsFun = ubootName : [ perl cpio ]
++ stdenv.lib.optional (ubootName != null) [ (ubootChooser ubootName) ];
makeUInitrdFun = ubootName : (ubootName != null);
in
@ -30,12 +30,11 @@ stdenv.mkDerivation {
objects = map (x: x.object) contents;
symlinks = map (x: x.symlink) contents;
suffices = map (x: if x ? suffix then x.suffix else "none") contents;
# For obtaining the closure of `contents'.
exportReferencesGraph =
map (x: [("closure-" + baseNameOf x.symlink) x.object]) contents;
pathsFromGraph = ./paths-from-graph.pl;
cpioClean = ./cpio-clean.pl;
crossAttrs = {
nativeBuildInputs = inputsFun stdenv.cross.platform.uboot;

View file

@ -39,7 +39,8 @@ mkdir -p $out
for PREP in $prepend; do
cat $PREP >> $out/initrd
done
(cd root && find * -print0 | cpio -o -H newc -R 0:0 --null | perl $cpioClean | $compressor >> $out/initrd)
(cd root && find * -print0 | xargs -0r touch -h -d '@1')
(cd root && find * -print0 | sort -z | cpio -o -H newc -R +0:+0 --reproducible --null | $compressor >> $out/initrd)
if [ -n "$makeUInitrd" ]; then
mv $out/initrd $out/initrd.gz