From 3363377530931ceac030e66be2be43b75719377b Mon Sep 17 00:00:00 2001 From: Damien Diederen Date: Wed, 30 Dec 2020 11:23:45 +0100 Subject: [PATCH] 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 {}).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.) --- pkgs/build-support/vm/deb/deb-closure.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/build-support/vm/deb/deb-closure.pl b/pkgs/build-support/vm/deb/deb-closure.pl index bed397d6f07..fe23025df1d 100644 --- a/pkgs/build-support/vm/deb/deb-closure.pl +++ b/pkgs/build-support/vm/deb/deb-closure.pl @@ -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) {