Hi! On Wed, 2018-11-28 at 07:52:08 +0500, Alexander E. Patrakov wrote: > Well, the buildd configuration change has been reverted. What worries me now > is that there is a risk not yet mitigated, coming from personal systems of > Debian developers, and we should also check porter boxes. > > As long as there is one Debian Developer (or any other person who has the > right to upload binary packages) who has a merged /usr on his system used > for building packages, there is a risk of reintroducing the bug through his > package. Maybe we should somehow, in the short term, modify dpkg to add > something like "Tainted-By: usr-merge" control field to all binary packages > produced, if a package is built on a system with merged /usr (detected via > /bin being a symlink). And a corresponding automatic check that would > auto-reject binary packages with any Tainted-By control field from being > uploaded to the Debian archive.
This is actually a great idea! I went ahead and implemented this, see attached tentative patch which I'm planning on including in dpkg 1.19.3. Thanks, Guillem
diff --git i/man/deb-buildinfo.man w/man/deb-buildinfo.man index 5013aa047..8aa333965 100644 --- i/man/deb-buildinfo.man +++ w/man/deb-buildinfo.man @@ -149,6 +149,19 @@ via some pattern match to avoid leaking possibly sensitive information. On Debian and derivatives only build paths starting with \fI/build/\fP will emit this field. .TP +.BR Build\-Tainted\-By: " \fItaint-reasons...\fP" +The list of reasons in the form of string tags (alphanumeric and dash), +that can taint the current build. +.RS +.TP +.B merged-usr-via-symlinks +The system has a merged /usr via symlinks. +This will confuse \fBdpkg\-query\fP as it messes with the \fBdpkg\fP +understanding of the filesystem it manages. +It can also produce packages with hardcoded paths that will be incompatible +with non-usr-merged filesystems. +.RE +.TP .BR Installed\-Build\-Depends: " (required)" .TQ .I " package-list" diff --git i/scripts/Dpkg/Control/FieldsCore.pm w/scripts/Dpkg/Control/FieldsCore.pm index b100366e1..f460433fc 100644 --- i/scripts/Dpkg/Control/FieldsCore.pm +++ w/scripts/Dpkg/Control/FieldsCore.pm @@ -176,6 +176,11 @@ our %FIELDS = ( allowed => CTRL_INFO_PKG, separator => FIELD_SEP_SPACE, }, + 'build-tainted-by' => { + name => 'Build-Tainted-By', + allowed => CTRL_FILE_BUILDINFO, + separator => FIELD_SEP_SPACE, + }, 'built-for-profiles' => { name => 'Built-For-Profiles', allowed => ALL_PKG | CTRL_FILE_CHANGES, @@ -634,7 +639,7 @@ our %FIELD_ORDER = ( qw(format source binary architecture version binary-only-changes), @src_checksums_fields, qw(build-origin build-architecture build-kernel-version build-date - build-path installed-build-depends environment), + build-path build-tainted-by installed-build-depends environment), ], CTRL_FILE_CHANGES() => [ qw(format date source binary binary-only built-for-profiles architecture diff --git i/scripts/Dpkg/Vendor/Debian.pm w/scripts/Dpkg/Vendor/Debian.pm index 7d4b6d802..0a1ad0b50 100644 --- i/scripts/Dpkg/Vendor/Debian.pm +++ w/scripts/Dpkg/Vendor/Debian.pm @@ -81,6 +81,8 @@ sub run_hook { $self->_add_build_flags(@params); } elsif ($hook eq 'builtin-system-build-paths') { return qw(/build/); + } elsif ($hook eq 'build-tainted-by') { + return $self->_build_tainted_by(); } else { return $self->SUPER::run_hook($hook, @params); } @@ -439,6 +441,24 @@ sub _add_build_flags { } } +sub _build_tainted_by { + my $self = shift; + my %tainted; + + foreach my $pathname (qw(/bin /sbin /lib /lib32 /lib64 /libx32 /libo32)) { + next unless -l $pathname; + + my $linkname = readlink $pathname; + if ($linkname eq "usr$pathname") { + $tainted{'merged-usr-via-symlinks'} = 1; + last; + } + } + + my @tainted = sort keys %tainted; + return @tainted; +} + =head1 CHANGES =head2 Version 0.xx diff --git i/scripts/Dpkg/Vendor/Default.pm w/scripts/Dpkg/Vendor/Default.pm index 40815efde..0ad0568df 100644 --- i/scripts/Dpkg/Vendor/Default.pm +++ w/scripts/Dpkg/Vendor/Default.pm @@ -140,6 +140,14 @@ field will be created if the current directory is "/build/dpkg-1.18.0". If the list contains "/", the path will always be recorded. If the list is empty, the current path will never be recorded. +=item build-tainted-by () + +The hook is called by dpkg-genbuildinfo to determine if the current system +has been tainted in some way that could affect the resulting build, which +will be recorded in the B<Build-Tainted-By> field (since dpkg 1.19.3). It +takes no parameters, but returns a (possibly empty) list of tainted reason +tags (alphanumeric with dashes). + =back =cut @@ -172,6 +180,8 @@ sub run_hook { my $flags = shift @params; } elsif ($hook eq 'builtin-system-build-paths') { return (); + } elsif ($hook eq 'build-tainted-by') { + return (); } # Default return value for unknown/unimplemented hooks diff --git i/scripts/dpkg-genbuildinfo.pl w/scripts/dpkg-genbuildinfo.pl index fe296506e..a324d960c 100755 --- i/scripts/dpkg-genbuildinfo.pl +++ w/scripts/dpkg-genbuildinfo.pl @@ -437,6 +437,8 @@ if ($use_feature{path}) { } } +$fields->{'Build-Tainted-By'} = join ' ', run_vendor_hook('build-tainted-by'); + $checksums->export_to_control($fields); $fields->{'Installed-Build-Depends'} = collect_installed_builddeps($control);