There is a long-standing [bug report](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61439) pointing out that the `download_prerequisites` script doesn't verify the integrity of the packages it downloads. The original bug report is only concerned about stability but for me, this is first and foremost a security issue. Even more so since the downloads happen over unsecured FTP connections.
I have already posted an improved version of the script that does verify checksums on the Bugzilla thread in February this year but apparently, it went unnoticed there. Coincidentally, another person posted an alternative solution at the same place just about the same time that didn't seem to have received any attention either. Their fix is minimal invasive while I essentially re-wrote the script and added a bunch of command-line options. I believe those are useful but you could also arguably call it over-engineering. I'm okay with either fix but I'm not going to speak for the other person so I'll only explain my own patch here. The script relies on the files `contrib/prerequisites.sha512` and `contrib/prerequisites.md5` to be present in the GCC tarball and will use them to verify the package integrity. Said files are tiny and readily available here ftp://gcc.gnu.org/pub/gcc/infrastructure/sha512.sum ftp://gcc.gnu.org/pub/gcc/infrastructure/md5.sum but I didn't include them into the patch because I have no way of verifying their integrity. Somebody who has secure access to the GNU servers should verify that we add the correct checksums into the GCC archive. Every time a new version of the prerequisites is used, the checksum files have to be updated as well. The integrity of the downloaded prerequisites then follows transitively assuming that GCC's own tarball hasn't been tampered with which we have to assume anyway. (Ensuring this is beyond the scope of anything we can put *inside* the tarball itself.) Since my patch doesn't contain said checksum files and other than that, merely replaces a single file completely, I'm attaching just the new version of the `download_prerequisites` scripts and not a diff. It would be nice of somebody with trusted access to the GNU servers could be so kind to prepare the actual SVN patch for me. After adding the checksum files, the ChangeLog entry might be like this: * contrib/download_prerequisites: Verify integrity of downloaded packages and added more command-line options. * contrib/prerequisites.sha512: New. * contrib/prerequisites.md5: New. I already went through the copyright assignment process for GCC so I think you should be able to include my patch if it is accepted. (I also took the liberty to mention the FSF as copyright holder in the script without waiting for the patch being accepted.) I believe that attacking a system by compromising the compiler is a very serious threat so I hope that you'll consider patching the script. If there are any portability or other issues with the way I wrote the script, I'll be ready to fix them. Moritz -- OpenPGP: Public Key: http://openpgp.klammler.eu Fingerprint: 2732 DA32 C8D0 EEEC A081 BE9D CF6C 5166 F393 A9C0
#! /bin/sh -eu #! -*- coding:utf-8; mode:shell-script; -*- # Download some prerequisites needed by GCC. # Run this from the top level of the Gcc source tree and the Gcc build will do # the right thing. Run it with the `--help` option for more information. # # (C) 2016 Free Software Foundation # # This program is free software: you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free Software # Foundation, either version 3 of the License, or (at your option) any later # version. # # This program is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more # details. # # You should have received a copy of the GNU General Public License along with # this program. If not, see http://www.gnu.org/licenses/. program='download_prerequisites' version='(unversioned)' graphite=1 verify=1 force=0 chksum='sha512' directory='.' gmp='gmp-4.3.2.tar.bz2' mpfr='mpfr-2.4.2.tar.bz2' mpc='mpc-0.8.1.tar.gz' isl='isl-0.15.tar.bz2' base_url='ftp://gcc.gnu.org/pub/gcc/infrastructure/' echo_archives() { echo "${gmp}" echo "${mpfr}" echo "${mpc}" if [ ${graphite} -gt 0 ]; then echo "${isl}"; fi } helptext="usage: ${program} [OPTION...] Downloads some prerequisites needed by GCC. Run this from the top level of the GCC source tree and the GCC build will do the right thing. The following options are available: --directory=DIR download and unpack packages into DIR instead of '.' --force download again overwriting existing packages --no-force do not download existing packages again (default) --isl download ISL, needed for Graphite loop optimizations (default) --graphite same as --isl --no-isl don't download ISL --no-graphite same as --no-isl --verify verify package integrity after download (default) --no-verify don't verify package integrity --sha512 use SHA512 checksum to verify package integrity (default) --md5 use MD5 checksum to verify package integrity --help show this text and exit --version show version information and exit " versiontext="${program} ${version} Copyright (C) 2016 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." die() { echo "error: $@" >&2 exit 1 } for arg in "$@" do case "${arg}" in --help) echo "${helptext}" exit ;; --version) echo "${versiontext}" exit ;; esac done unset arg argnext= for arg in "$@" do if [ "x${argnext}" = x ] then case "${arg}" in --directory) argnext='directory' ;; --directory=*) directory="${arg#--directory=}" ;; --force) force=1 ;; --no-force) force=0 ;; --isl|--graphite) graphite=1 ;; --no-isl|--no-graphite) graphite=0 ;; --verify) verify=1 ;; --no-verify) verify=0 ;; --sha512) chksum='sha512' verify=1 ;; --md5) chksum='md5' verify=1 ;; -*) die "unknown option: ${arg}" ;; *) die "too many arguments" ;; esac else case "${arg}" in -*) die "Missing argument for option --${argnext}" ;; esac case "${argnext}" in directory) directory="${arg}" ;; *) die "The impossible has happened" ;; esac argnext= fi done [ "x${argnext}" = x ] || die "Missing argument for option --${argnext}" unset arg argnext [ -e ./gcc/BASE-VER ] \ || die "You must run this script in the top-level GCC source directory" [ -d "${directory}" ] \ || die "No such directory: ${directory}" for ar in $(echo_archives) do if [ ${force} -gt 0 ]; then rm -f "${directory}/${ar}"; fi [ -e "${directory}/${ar}" ] \ || wget --no-verbose -O "${directory}/${ar}" "${base_url}${ar}" \ || die "Cannot download ${ar} from ${base_url}" done unset ar if [ ${verify} -gt 0 ] then chksumfile="contrib/prerequisites.${chksum}" [ -r "${chksumfile}" ] || die "No checksums available" for ar in $(echo_archives) do grep "${ar}" "${chksumfile}" \ | ( cd "${directory}" && "${chksum}sum" --check ) \ || die "Cannot verify integrity of possibly corrupted file ${ar}" done unset chksumfile fi unset ar for ar in $(echo_archives) do package="${ar%.tar*}" if [ ${force} -gt 0 ]; then rm -rf "${directory}/${package}"; fi [ -e "${directory}/${package}" ] \ || ( cd "${directory}" && tar -xf "${ar}" ) \ || die "Cannot extract package from ${ar}" unset package done unset ar for ar in $(echo_archives) do target="${directory}/${ar%.tar*}/" linkname="${ar%-*}" if [ ${force} -gt 0 ]; then rm -f "${linkname}"; fi [ -e "${linkname}" ] \ || ln -s "${target}" "${linkname}" \ || die "Cannot create symbolic link ${linkname} --> ${target}" unset target linkname done unset ar echo "All prerequisites downloaded successfully."
signature.asc
Description: PGP signature