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 bed397d6f07e..fe23025df1d8 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) {