vmTools.debClosureGenerator: Fix non-determinism in dependency graph

By default, Perl versions since 5.8.1 use randomization to make hashes
resistant to complexity attacks.

That randomization makes building VM images such as ubuntu1804x86_64
non-deterministic because the (imported) derivations built by
deb/deb-closure.pl are not stable.

This can easily be observed by repeating the following sequence of
commands and noting the path of the image's .drv:

    nix-instantiate -E '(import <nixpkgs> {}).vmTools.diskImageFuns.ubuntu1804x86_64 {}'
    nix-store --delete /nix/store/*ubuntu-18.04-bionic-amd64.nix

One source of non-determinism is the handling of Provides/Replaces,
which depends on the order of iteration over %packages.  Here is a
diff showing the corresponding change in output:

     >>> awk
    -virtual awk: using original-awk
    -    original-awk: libc6 (>= 2.14)
    +virtual awk: using mawk
    +    mawk: libc6 (>= 2.14)

    -    mawk: libc6 (>= 2.14)
    ->>> libc6

This patch sorts packages by name for Provides/Replaces processing,
which seems to result in stable output.

(If the above turns out not to be sufficient, one could also set the
PERL_HASH_SEED and PERL_PERTURB_KEYS environment variables, documented
in 'perlrun', to disable Perl's built-in randomization.  Complexity
attacks are not an issue as we control and trust all inputs.)
This commit is contained in:
Damien Diederen 2020-12-30 11:23:45 +01:00
parent f6188ca545
commit 3363377530

View file

@ -50,7 +50,7 @@ sub getDeps {
# virtual dependencies.
my %provides;
foreach my $cdata (values %packages) {
foreach my $cdata (sort {$a->{Package} cmp $b->{Package}} (values %packages)) {
if (defined $cdata->{Provides}) {
my @provides = getDeps(Dpkg::Deps::deps_parse($cdata->{Provides}));
foreach my $name (@provides) {