Bruno Haible <br...@clisp.org> writes:

> Hi Simon,
>
> In the other thread [1][2][2a], but see also [3] and [4], you are asking

Hi Bruno -- thanks for attempting to bring som order to this complicated
matter!  I am in agreement with most of what you say, although some
comments below.

>> Has this changed, so we should recommend maintainers
>> to 'EXTRA_DIST = bootstrap bootstrap-funclib.sh bootstrap.conf' so this
>> is even possible?
>
> 1) I think changing the contents of a tarball ad-hoc, like this, will not
>    lead to satisfying results, because too many packages will do things
>    differently.

Right, and people tend to jump to the incorrect conclusion that running
autoreconf -fvi or running ./bootstrap from a tarball is a good idea.

Rather than trying to fix that solution, I think we should guide these
people towards using 'git-archive' style tarballs instead.  Then they
will need to do all the work that is actually required to bootstrap a
project, including getting all the dependencies in place.

Some will succeed in that.

Some will give up and realize they wanted the traditional curated
tarball after all, and go back to it, and this time hopefully not do the
'autoreconf -fi' harmful dance.

In both situations, I think we are better off than with the current
situation.  Now people take the 'make dist' tarballs and try to reverse
engineer all the required dependencies to regenerate all artifacts, and
do a half-baked job at that, with an end result that is even harder to
audit than what we started with.

>    (Y) Some distros want to be able to verify the tarballs.[9] (I don't agree
>        with this. If you can't trust the release manager who produced the
>        tarballs (C), you cannot trust (A) either. If there is a mechanism
>        for verifying (C) from (A), criminals will commit their malware
>        entirely into (A).)

I have another perspective here.  I don't think people necessarily want
to blindly trust either the git repository source code (A) or tarball
with generated code and source code (C).  So people will want the
ability to audit and verify everything.  Once people start to work on
auditing, they realize that there is no way around auditing (A).  You
need to audit XZUtils source code to gain trust in XZUtils.  So people
work on doing that.  Then someone realize that people aren't actually
using git source code (A) to build the XZUtils binaries -- they are
using (A) plus generated content, that is the full tarball (C).  However
auditing (C) is just a waste of human time if there was a way to avoid
using (C) completely, and have people use (A) directly.  This isn't all
that complicated, I just did it for Libntlm and will try to do the same
for other packages.

I think you are right that if we succeed with this, criminals will put
their malware directly into git source code repositories.  However that
is addressed by the people working on reviewing the core code of
projects.  There is no longer any need for people to spend time auditing
tarballs with a lot of other stuff in them.  This time can be redirected
towards auditing the code.  Which over the years saves a lot of human
cycles.

Most code audits I've seen focus on what's in git, not what's in the
tarball nor in the binary packages that people use.  Which is how it
should be -- the build environment is better to audit on its own rathen
than as part of the upstream code audit.

> 6) How could (X) be implemented?
>
>    The main differences between (A) and (C) are [10]:
>      - Tarballs contain source code from other packages.
>      - Tarballs contain generated files.
>      - Tarballs contain localizations.
>
>    I could imagine an intermediate step between (A) and (C):
>
>      (B) is for users with many packages installed and for distros, to apply
>          modifications (even to the set of gnulib modules) and then build
>          binaries of the package for one or more architectures, without
>          needing to fetch anything (other than build prerequisites) from the
>          network.
>
>    This is a different stage than (A), because most developers don't want
>    to commit source code from other packages into (A) — due to size — nor
>    to commit generated files into (A) — due to hassles with branches.
>
>    Going from (A) to (B) means pulling additional sources from the network.
>    It could be implemented
>      - by "git submodule update --init", or
>      - by 'npm' for JavaScript packages, or
>      - by 'cargo' for Rust packages [11]
>    and, for the localizations:
>      - essentially by a 'wget' command that fetches the *.po files.
>
>    The proposed name of a script that does this is 'autopull.sh'.
>    But I am equally open to a declarative YAML file instead of a shell script.

Another point of view is to give up on forcing the autopull part on
users -- instead we can mention the required dependencies in README and
let the user/packager worry about having them available.  At least as an
option.

The reason for giving up here is that different users seems to want to
do this in wildly different ways, and validate or patch the dependencies
in different ways.  Presuming that we know better than the person
building the software leads to some of the conflicting demands that we
see here.

For example, some people build without network connections.  Then 'git
submodule update --init' doesn't work.  So we provide them with some
alternative and add --gnulib-srcdir to ./bootstrap, which added
complexity.  Then someone comes up with another method they preferred,
and we added --gnulib-refdir.  Then someone realized yet another way
they preferred, and we added GNULIB_REVISION.  This suggests this is an
evolving space and that is getting a bit away from our expertise or
field of domain: as maintainer of Libntlm I would prefer to focus on
Libntlm source code and document the dependencies people need.

Another example is wget of *.po files.  I feel uncomfortable with that,
what if someone corrupts https://translationproject.org/ and serves
malicious files, possibly on a per-IP basis to selected users?  There is
no checksum checking going on, autopull trust whatever it gets.  Now
maybe translation files cannot trigger vulnerabilities, and maybe there
aren't any vulnerabilities to being with, but verifying that isn't as
easy.  The files are arbitrary untrusted data.  I'm considering adding
*.po files into git, like we used to do in the CVS days, and update them
manually once in a while before a release. Having a po/SHA256SUMS,
curated by the maintainer, that autopull could verify files against
would be another approach.  But then old versions of the software cannot
be bootstrapped any more, if it is not possible to fetch the *.po files
by SHA256 checksum value.  I'm not sure what the best solution is.

> 7) How could (Y) be implemented?
>    Like in (E+), we would define:
>
>      (C+) Like (C), plus:
>           A user with all kinds of special tools can determine whether (C)
>           was built with a published build recipe, without tampering.
>
>    Again, this requires
>      - formalizing the notion of a build environment,
>      - adding this build environment into (C).
>
>    For example, we would need a way to specify a build dependency on a
>    particular version of groff or texinfo or doxygen (for the documentation),
>    a particular version of m4, autoconf, automake (for the configure script
>    and Makefile.ins).
>
>    So far, some people have published their build environment in form of
>    ad-hoc plain text ("This release was bootstrapped with the following 
> tools")
>    inside release announcements. [12] Of course, that's the wrong place to
>    do so, because a user who receives (C) and wants to verify it does not
>    want to search for the release announcement in order to get the build
>    environment.

It is better than nothing, though.

Ideally what you need is SHA256 checksums for all binaries (including
its auxilliary files) that were needed to reproduce the full 'make dist'
tarball, and ideally a way to recreate all those binaries from source,
chaining back to some small binary hand-curated seed.  This is
essentially what Guix is working on, but we are pretty far away from
this being the standard environment.

Alternatively, just offer a SHA256 checksum of your 'git archive' source
code, and let distributors and others worry about assuring the build
process.

>    Some people are suggesting that (Y) could be implemented on top of (X) [9].
>    That is, the distro should start from (B), not (C). However, I think it
>    does not change much of the problem. The user's question "can I trust (C),
>    built by the package's release manager" is replaced with two questions
>      "can I trust (B), built by the package's release manager" and
>      "can I trust (C), built by the distro's build service".

Again, to offer another perspective, consider if a users doesn't
necessarily want to trust anything.  So we should make it easy to audit
what they need to trust, namely:

  1) Upstream source code from 'git archive'.

  2) The distribution build recipes.  That is the debian/ sub-directory
  or RPM spec file, usually fairly short.

  3) The build infrastructure.

Today users have to audit 1), 2) and 3) but ALSO the following:

  4) Upstream's 'make dist' tarball with generated content added coming
  from other packages (autoconf, automake, gnulib, texinfo etc).

  5) Debian's *.orig.tar.gz tarball, which may be different from
  upstream's tarball, and often also contains generated files.

Auditing these two last artifacts takes human time.  If you can compute
a checksum proving 1) == 4) == 5) then that time would be saved.

/Simon

Attachment: signature.asc
Description: PGP signature

Reply via email to