diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..5eff5c8 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,3 @@ +/*/**/Dockerfile linguist-generated +/*/**/Dockerfile.builder linguist-generated linguist-language=Dockerfile +/Dockerfile*.template linguist-language=Dockerfile diff --git a/.github/workflows/fake-gsl.sh b/.github/workflows/fake-gsl.sh index 20f1b8a..ebc1fd8 100755 --- a/.github/workflows/fake-gsl.sh +++ b/.github/workflows/fake-gsl.sh @@ -3,13 +3,20 @@ set -Eeuo pipefail # this is a fake version of "generate-stackbrew-library.sh" just so https://github.com/docker-library/bashbrew/blob/c74be66ae6a019e0baee601287187dc6df29b384/scripts/github-actions/generate.sh can generate us a sane starter matrix +[ -f versions.json ] # run "versions.sh" first + +if [ "$#" -eq 0 ]; then + dirs="$(jq -r 'to_entries | map(.key + "/" + (.value.variants[])) | map(@sh) | join(" ")' versions.json)" + eval "set -- $dirs" +fi + echo 'Maintainers: foo (@bar)' echo 'GitRepo: https://github.com/docker-library/busybox.git' -for f in */Dockerfile.builder; do - d="$(dirname "$f")" + +for d; do commit="$(git log -1 --format='format:%H' "$d/Dockerfile")" echo - echo "Tags: $d" + echo "Tags: ${d////-}" echo "Directory: $d" echo "GitCommit: $commit" done diff --git a/.github/workflows/verify-templating.yml b/.github/workflows/verify-templating.yml new file mode 100644 index 0000000..7e833f1 --- /dev/null +++ b/.github/workflows/verify-templating.yml @@ -0,0 +1,22 @@ +name: Verify Templating + +on: + pull_request: + push: + +defaults: + run: + shell: 'bash -Eeuo pipefail -x {0}' + +jobs: + apply-templates: + name: Check For Uncomitted Changes + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Apply Templates + run: ./apply-templates.sh + - name: Check Git Status + run: | + status="$(git status --short)" + [ -z "$status" ] diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d548f66 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.jq-template.awk diff --git a/Dockerfile-builder.template b/Dockerfile-builder.template new file mode 100644 index 0000000..bccc57b --- /dev/null +++ b/Dockerfile-builder.template @@ -0,0 +1,415 @@ +{{ if env.variant == "musl" then ( -}} +FROM alpine:3.12 + +RUN set -eux; \ + apk add --no-cache \ + bzip2 \ + coreutils \ + curl \ + gcc \ + gnupg \ + linux-headers \ + make \ + musl-dev \ + tzdata \ + ; +{{ ) else ( -}} +FROM debian:buster-slim + +RUN set -eux; \ + apt-get update; \ + apt-get install -y \ + bzip2 \ + curl \ + gcc \ + gnupg dirmngr \ + make \ + ; \ + rm -rf /var/lib/apt/lists/* +{{ ) end -}} +{{ if env.variant == "uclibc" then ( -}} + +# grab/use buildroot for its uClibc toolchain + +RUN set -eux; \ + apt-get update; \ + apt-get install -y \ + bc \ + cpio \ + dpkg-dev \ + g++ \ + patch \ + perl \ + python \ + rsync \ + unzip \ + wget \ + ; \ + rm -rf /var/lib/apt/lists/* + +# pub 1024D/59C36319 2009-01-15 +# Key fingerprint = AB07 D806 D2CE 741F B886 EE50 B025 BA8B 59C3 6319 +# uid Peter Korsgaard +# sub 2048g/45428075 2009-01-15 +RUN gpg --batch --keyserver ha.pool.sks-keyservers.net --recv-keys AB07D806D2CE741FB886EE50B025BA8B59C36319 + +# https://buildroot.org/download.html +# https://buildroot.org/downloads/?C=M;O=D +ENV BUILDROOT_VERSION {{ .buildroot.version }} + +RUN set -eux; \ + tarball="buildroot-${BUILDROOT_VERSION}.tar.bz2"; \ + curl -fL -o buildroot.tar.bz2 "https://buildroot.org/downloads/$tarball"; \ + curl -fL -o buildroot.tar.bz2.sign "https://buildroot.org/downloads/$tarball.sign"; \ + gpg --batch --decrypt --output buildroot.tar.bz2.txt buildroot.tar.bz2.sign; \ + awk '$1 == "SHA1:" && $2 ~ /^[0-9a-f]+$/ && $3 == "'"$tarball"'" { print $2, "*buildroot.tar.bz2" }' buildroot.tar.bz2.txt > buildroot.tar.bz2.sha1; \ + test -s buildroot.tar.bz2.sha1; \ + sha1sum -c buildroot.tar.bz2.sha1; \ + mkdir -p /usr/src/buildroot; \ + tar -xf buildroot.tar.bz2 -C /usr/src/buildroot --strip-components 1; \ + rm buildroot.tar.bz2* + +RUN set -eux; \ + \ + cd /usr/src/buildroot; \ + \ + setConfs=' \ + BR2_STATIC_LIBS=y \ + BR2_TOOLCHAIN_BUILDROOT_UCLIBC=y \ + BR2_TOOLCHAIN_BUILDROOT_WCHAR=y \ + '; \ + \ + unsetConfs=' \ + BR2_SHARED_LIBS \ + '; \ + \ +# buildroot arches: https://git.busybox.net/buildroot/tree/arch +# buildroot+uclibc arches: https://git.busybox.net/buildroot/tree/toolchain/toolchain-buildroot/Config.in ("config BR2_TOOLCHAIN_BUILDROOT_UCLIBC") + dpkgArch="$(dpkg --print-architecture)"; \ + case "$dpkgArch" in \ + amd64) \ + setConfs="$setConfs \ + BR2_x86_64=y \ + "; \ + ;; \ + \ + arm64) \ + setConfs="$setConfs \ + BR2_aarch64=y \ + "; \ + ;; \ + \ +# https://wiki.debian.org/ArmEabiPort#Choice_of_minimum_CPU +# https://github.com/free-electrons/toolchains-builder/blob/db259641eaf5bbcf13f4a3c5003e5436e806770c/configs/arch/armv5-eabi.config +# https://git.busybox.net/buildroot/tree/arch/Config.in.arm +# (Debian minimums at ARMv4, we minimum at ARMv5 instead) + armel) \ + setConfs="$setConfs \ + BR2_arm=y \ + BR2_arm926t=y \ + BR2_ARM_EABI=y \ + BR2_ARM_INSTRUCTIONS_THUMB=y \ + BR2_ARM_SOFT_FLOAT=y \ + "; \ + ;; \ + \ +# "Currently the Debian armhf port requires at least an ARMv7 CPU with Thumb-2 and VFP3D16." +# https://wiki.debian.org/ArmHardFloatPort#Supported_devices +# https://github.com/free-electrons/toolchains-builder/blob/db259641eaf5bbcf13f4a3c5003e5436e806770c/configs/arch/armv7-eabihf.config +# https://git.busybox.net/buildroot/tree/arch/Config.in.arm + armhf) \ + setConfs="$setConfs \ + BR2_arm=y \ + BR2_cortex_a9=y \ + BR2_ARM_EABIHF=y \ + BR2_ARM_ENABLE_VFP=y \ + BR2_ARM_FPU_VFPV3D16=y \ + BR2_ARM_INSTRUCTIONS_THUMB2=y \ + "; \ + unsetConfs="$unsetConfs BR2_ARM_SOFT_FLOAT"; \ + ;; \ + \ + i386) \ + setConfs="$setConfs \ + BR2_i386=y \ + "; \ + ;; \ + \ + mips64el) \ + setConfs="$setConfs \ + BR2_mips64el=y \ + BR2_mips_64r2=y \ + BR2_MIPS_NABI64=y \ + "; \ + unsetConfs="$unsetConfs \ + BR2_MIPS_SOFT_FLOAT \ + " \ + ;; \ + \ +# TODO ppc64el ? (needs BR2_TOOLCHAIN_BUILDROOT_UCLIBC support) + \ +# TODO s390x ? (needs BR2_TOOLCHAIN_BUILDROOT_UCLIBC support) + \ + *) \ + echo >&2 "error: unsupported architecture '$dpkgArch'!"; \ + exit 1; \ + ;; \ + esac; \ + if [ "$dpkgArch" != 'i386' ]; then \ + unsetConfs="$unsetConfs BR2_i386"; \ + fi; \ + \ + make defconfig; \ + \ + for conf in $unsetConfs; do \ + sed -i \ + -e "s!^$conf=.*\$!# $conf is not set!" \ + .config; \ + done; \ + \ + for confV in $setConfs; do \ + conf="${confV%=*}"; \ + sed -i \ + -e "s!^$conf=.*\$!$confV!" \ + -e "s!^# $conf is not set\$!$confV!" \ + .config; \ + if ! grep -q "^$confV\$" .config; then \ + echo "$confV" >> .config; \ + fi; \ + done; \ + \ + make oldconfig; \ + \ +# trust, but verify + for conf in $unsetConfs; do \ + ! grep -q "^$conf=" .config; \ + done; \ + for confV in $setConfs; do \ + grep -q "^$confV\$" .config; \ + done; + +# https://www.finnie.org/2014/02/13/compiling-busybox-with-uclibc/ +RUN set -eux; \ +# force a particular GNU arch for "host-gmp" (otherwise it fails on some arches) + gnuArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; \ + make -C /usr/src/buildroot \ + HOST_GMP_CONF_OPTS="--build='"$gnuArch"'" \ +# building host-tar: +# configure: error: you should not run configure as root (set FORCE_UNSAFE_CONFIGURE=1 in environment to bypass this check) + FORCE_UNSAFE_CONFIGURE=1 \ + -j "$(nproc)" \ + toolchain +ENV PATH /usr/src/buildroot/output/host/usr/bin:$PATH +{{ ) else "" end -}} + +# pub 1024D/ACC9965B 2006-12-12 +# Key fingerprint = C9E9 416F 76E6 10DB D09D 040F 47B7 0C55 ACC9 965B +# uid Denis Vlasenko +# sub 1024g/2C766641 2006-12-12 +RUN gpg --batch --keyserver ha.pool.sks-keyservers.net --recv-keys C9E9416F76E610DBD09D040F47B70C55ACC9965B + +ENV BUSYBOX_VERSION {{ .version }} +ENV BUSYBOX_SHA256 {{ .sha256 }} + +RUN set -eux; \ + tarball="busybox-${BUSYBOX_VERSION}.tar.bz2"; \ + curl -fL -o busybox.tar.bz2.sig "https://busybox.net/downloads/$tarball.sig"; \ + curl -fL -o busybox.tar.bz2 "https://busybox.net/downloads/$tarball"; \ + echo "$BUSYBOX_SHA256 *busybox.tar.bz2" | sha256sum -c -; \ + gpg --batch --verify busybox.tar.bz2.sig busybox.tar.bz2; \ + mkdir -p /usr/src/busybox; \ + tar -xf busybox.tar.bz2 -C /usr/src/busybox --strip-components 1; \ + rm busybox.tar.bz2* + +WORKDIR /usr/src/busybox + +RUN set -eux; \ + \ + setConfs=' \ + CONFIG_AR=y \ + CONFIG_FEATURE_AR_CREATE=y \ + CONFIG_FEATURE_AR_LONG_FILENAMES=y \ +# CONFIG_LAST_SUPPORTED_WCHAR: see https://github.com/docker-library/busybox/issues/13 (UTF-8 input) + CONFIG_LAST_SUPPORTED_WCHAR=0 \ +{{ if env.variant == "glibc" then ( -}} +# As long as we rely on libnss (see below), we have to have libc.so anyhow, so we've removed CONFIG_STATIC here... :cry: +{{ ) else ( -}} + CONFIG_STATIC=y \ +{{ ) end -}} + '; \ + \ + unsetConfs=' \ + CONFIG_FEATURE_SYNC_FANCY \ +{{ if env.variant == "musl" then ( -}} + \ +# see https://wiki.musl-libc.org/wiki/Building_Busybox + CONFIG_FEATURE_HAVE_RPC \ + CONFIG_FEATURE_INETD_RPC \ + CONFIG_FEATURE_UTMP \ + CONFIG_FEATURE_WTMP \ +{{ ) else "" end -}} + '; \ + \ + make defconfig; \ + \ + for conf in $unsetConfs; do \ + sed -i \ + -e "s!^$conf=.*\$!# $conf is not set!" \ + .config; \ + done; \ + \ + for confV in $setConfs; do \ + conf="${confV%=*}"; \ + sed -i \ + -e "s!^$conf=.*\$!$confV!" \ + -e "s!^# $conf is not set\$!$confV!" \ + .config; \ + if ! grep -q "^$confV\$" .config; then \ + echo "$confV" >> .config; \ + fi; \ + done; \ + \ + make oldconfig; \ + \ +# trust, but verify + for conf in $unsetConfs; do \ + ! grep -q "^$conf=" .config; \ + done; \ + for confV in $setConfs; do \ + grep -q "^$confV\$" .config; \ + done + +RUN set -eux; \ + nproc="$(nproc)"; \ +{{ if env.variant == "uclibc" then ( -}} + CROSS_COMPILE="$(basename /usr/src/buildroot/output/host/usr/*-buildroot-linux-uclibc*)"; \ + export CROSS_COMPILE="$CROSS_COMPILE-"; \ +{{ ) else "" end -}} + make -j "$nproc" busybox; \ + ./busybox --help; \ + mkdir -p rootfs/bin; \ + ln -vL busybox rootfs/bin/; \ + \ +{{ if env.variant == "uclibc" then ( -}} +# copy "getconf" from buildroot + ln -vL ../buildroot/output/target/usr/bin/getconf rootfs/bin/; \ +{{ ) elif env.variant == "glibc" then ( -}} +# copy "getconf" from Debian + getconf="$(which getconf)"; \ + ln -vL "$getconf" rootfs/bin/getconf; \ + \ +# hack hack hack hack hack +# with glibc, busybox (static or not) uses libnss for DNS resolution :( + mkdir -p rootfs/etc; \ + cp /etc/nsswitch.conf rootfs/etc/; \ + mkdir -p rootfs/lib; \ + ln -sT lib rootfs/lib64; \ + gccMultiarch="$(gcc -print-multiarch)"; \ + set -- \ + rootfs/bin/busybox \ + rootfs/bin/getconf \ + /lib/"$gccMultiarch"/libnss*.so.* \ +# libpthread is part of glibc: https://stackoverflow.com/a/11210463/433558 + /lib/"$gccMultiarch"/libpthread*.so.* \ + ; \ + while [ "$#" -gt 0 ]; do \ + f="$1"; shift; \ + fn="$(basename "$f")"; \ + if [ -e "rootfs/lib/$fn" ]; then continue; fi; \ + if [ "${f#rootfs/}" = "$f" ]; then \ + if [ "${fn#ld-}" = "$fn" ]; then \ + ln -vL "$f" "rootfs/lib/$fn"; \ + else \ + cp -v "$f" "rootfs/lib/$fn"; \ + fi; \ + fi; \ + ldd="$(ldd "$f" | awk ' \ + $1 ~ /^\// { print $1; next } \ + $2 == "=>" && $3 ~ /^\// { print $3; next } \ + ')"; \ + set -- "$@" $ldd; \ + done; \ +{{ ) elif env.variant == "musl" then ( -}} +# copy simplified getconf port from Alpine + aportsVersion="v$(cat /etc/alpine-release)"; \ + curl -fsSL \ + "https://git.alpinelinux.org/cgit/aports/plain/main/musl/getconf.c?h=${aportsVersion}" \ + -o /usr/src/getconf.c \ + ; \ + gcc -o rootfs/bin/getconf -static -Os /usr/src/getconf.c; \ +{{ ) else "" end -}} + chroot rootfs /bin/getconf _NPROCESSORS_ONLN; \ + \ + chroot rootfs /bin/busybox --install /bin + +# install a few extra files from buildroot (/etc/passwd, etc) +RUN set -eux; \ +{{ if env.variant == "uclibc" then "" else ( -}} + buildrootVersion={{ .buildroot.version | @sh }}; \ + for file in \ + system/device_table.txt \ + system/skeleton/etc/group \ + system/skeleton/etc/passwd \ + system/skeleton/etc/shadow \ + ; do \ + dir="$(dirname "$file")"; \ + mkdir -p "../buildroot/$dir"; \ + curl -fL -o "../buildroot/$file" "https://git.busybox.net/buildroot/plain/$file?id=$buildrootVersion"; \ + [ -s "../buildroot/$file" ]; \ + done; \ + \ +{{ ) end -}} + mkdir -p rootfs/etc; \ + ln -vL \ + ../buildroot/system/skeleton/etc/group \ + ../buildroot/system/skeleton/etc/passwd \ + ../buildroot/system/skeleton/etc/shadow \ + rootfs/etc/ \ + ; \ +# CVE-2019-5021, https://github.com/docker-library/official-images/pull/5880#issuecomment-490681907 + grep -E '^root::' rootfs/etc/shadow; \ + sed -ri -e 's/^root::/root:*:/' rootfs/etc/shadow; \ + grep -E '^root:[*]:' rootfs/etc/shadow; \ +# set expected permissions, etc too (https://git.busybox.net/buildroot/tree/system/device_table.txt) + awk ' \ + !/^#/ { \ + if ($2 != "d" && $2 != "f") { \ + printf "error: unknown type \"%s\" encountered in line %d: %s\n", $2, NR, $0 > "/dev/stderr"; \ + exit 1; \ + } \ + sub(/^\/?/, "rootfs/", $1); \ + if ($2 == "d") { \ + printf "mkdir -p %s\n", $1; \ + } \ + printf "chmod %s %s\n", $3, $1; \ + } \ + ' ../buildroot/system/device_table.txt | sh -eux + +# create missing home directories +RUN set -eux; \ + cd rootfs; \ + for userHome in $(awk -F ':' '{ print $3 ":" $4 "=" $6 }' etc/passwd); do \ + user="${userHome%%=*}"; \ + home="${userHome#*=}"; \ + home="./${home#/}"; \ + if [ ! -d "$home" ]; then \ + mkdir -p "$home"; \ + chown "$user" "$home"; \ + chmod 755 "$home"; \ + fi; \ + done + +# test and make sure it works +RUN chroot rootfs /bin/sh -xec 'true' + +# ensure correct timezone (UTC) +RUN set -eux; \ + ln -vL /usr/share/zoneinfo/UTC rootfs/etc/localtime; \ + [ "$(chroot rootfs date +%Z)" = 'UTC' ] + +# test and make sure DNS works too +RUN cp -L /etc/resolv.conf rootfs/etc/; \ + chroot rootfs /bin/sh -xec 'nslookup google.com'; \ + rm rootfs/etc/resolv.conf + +# vim:set ft=dockerfile: diff --git a/glibc/Dockerfile b/Dockerfile.template similarity index 100% rename from glibc/Dockerfile rename to Dockerfile.template diff --git a/apply-templates.sh b/apply-templates.sh new file mode 100755 index 0000000..5b93321 --- /dev/null +++ b/apply-templates.sh @@ -0,0 +1,49 @@ +#!/usr/bin/env bash +set -Eeuo pipefail + +[ -f versions.json ] # run "versions.sh" first + +cd "$(dirname "$(readlink -f "$BASH_SOURCE")")" + +jqt='.jq-template.awk' +if [ -n "${BASHBREW_SCRIPTS:-}" ]; then + jqt="$BASHBREW_SCRIPTS/jq-template.awk" +elif [ "$BASH_SOURCE" -nt "$jqt" ]; then + wget -qO "$jqt" 'https://github.com/docker-library/bashbrew/raw/5f0c26381fb7cc78b2d217d58007800bdcfbcfa1/scripts/jq-template.awk' +fi + +if [ "$#" -eq 0 ]; then + versions="$(jq -r 'keys | map(@sh) | join(" ")' versions.json)" + eval "set -- $versions" +fi + +generated_warning() { + cat <<-EOH + # + # NOTE: THIS DOCKERFILE IS GENERATED VIA "apply-templates.sh" + # + # PLEASE DO NOT EDIT IT DIRECTLY. + # + + EOH +} + +for version; do + export version + + variants="$(jq -r '.[env.version].variants | map(@sh) | join(" ")' versions.json)" + eval "variants=( $variants )" + + for variant in "${variants[@]}"; do + export variant + + echo "processing $version/$variant ..." + + { + generated_warning + gawk -f "$jqt" Dockerfile-builder.template + } > "$version/$variant/Dockerfile.builder" + + cp Dockerfile.template "$version/$variant/Dockerfile" + done +done diff --git a/build.sh b/build.sh index 2e6ef56..8943ff0 100755 --- a/build.sh +++ b/build.sh @@ -1,40 +1,38 @@ -#!/bin/bash -set -e +#!/usr/bin/env bash +set -Eeuo pipefail -cd "$(readlink -f "$(dirname "$BASH_SOURCE")")" +[ -f versions.json ] # run "versions.sh" first -versions=( "$@" ) -if [ ${#versions[@]} -eq 0 ]; then - versions=( */ ) +if [ "$#" -eq 0 ]; then + dirs="$(jq -r 'to_entries | map(.key + "/" + (.value.variants[])) | map(@sh) | join(" ")' versions.json)" + eval "set -- $dirs" fi -versions=( "${versions[@]%/}" ) -base='busybox:' -for version in "${versions[@]}"; do - [ -f "$version/Dockerfile.builder" ] || continue +for dir; do + base="busybox:${dir////-}" ( set -x - docker build -t "$base$version-builder" -f "$version/Dockerfile.builder" "$version" - docker run --rm "$base$version-builder" tar cC rootfs . | xz -T0 -z9 > "$version/busybox.tar.xz" - docker build -t "$base$version-test" "$version" - docker run --rm "$base$version-test" sh -xec 'true' + docker build -t "$base-builder" -f "$dir/Dockerfile.builder" "$dir" + docker run --rm "$base-builder" tar cC rootfs . | xz -T0 -z9 > "$dir/busybox.tar.xz" + docker build -t "$base-test" "$dir" + docker run --rm "$base-test" sh -xec 'true' # detect whether the current host _can_ ping # (QEMU user-mode networking does not route ping traffic) shouldPing= - if docker run --rm "$base$version-builder" ping -c 1 google.com &> /dev/null; then + if docker run --rm "$base-builder" ping -c 1 google.com &> /dev/null; then shouldPing=1 fi if [ -n "$shouldPing" ]; then - if ! docker run --rm "$base$version-test" ping -c 1 google.com; then + if ! docker run --rm "$base-test" ping -c 1 google.com; then sleep 1 - docker run --rm "$base$version-test" ping -c 1 google.com + docker run --rm "$base-test" ping -c 1 google.com fi else - docker run --rm "$base$version-test" nslookup google.com + docker run --rm "$base-test" nslookup google.com fi - docker images "$base$version-test" + docker images "$base-test" ) done diff --git a/generate-stackbrew-library.sh b/generate-stackbrew-library.sh index a66415f..a8c4305 100755 --- a/generate-stackbrew-library.sh +++ b/generate-stackbrew-library.sh @@ -1,19 +1,16 @@ -#!/bin/bash +#!/usr/bin/env bash set -Eeuo pipefail -self="$(basename "$BASH_SOURCE")" -cd "$(dirname "$(readlink -f "$BASH_SOURCE")")" - gitHubUrl='https://github.com/docker-library/busybox' rawGitUrl="$gitHubUrl/raw" -# prefer uclibc, but if it's unavailable use glibc if possible since it's got less "edge case" behavior, especially around DNS -variants=( - uclibc - glibc - musl -) -# (order here determines "preference" for representing "latest") +self="$(basename "$BASH_SOURCE")" +cd "$(dirname "$(readlink -f "$BASH_SOURCE")")" + +if [ "$#" -eq 0 ]; then + versions="$(jq -r 'keys | map(@sh) | join(" ")' versions.json)" + eval "set -- $versions" +fi archMaps=( $( git ls-remote --heads "${gitHubUrl}.git" \ @@ -55,57 +52,89 @@ join() { echo "${out#$sep}" } -# pre-flight sanity checks -fullVersion= -for variant in "${variants[@]}"; do - [ -f "$variant/Dockerfile.builder" ] - oldVersion="$fullVersion" - fullVersion="$(awk '$1 == "ENV" && $2 == "BUSYBOX_VERSION" { print $3; exit }' "$variant/Dockerfile.builder")" - [ -n "$fullVersion" ] - [ "$fullVersion" = "${oldVersion:-$fullVersion}" ] -done -versionAliases=() -while [ "${fullVersion%.*}" != "$fullVersion" ]; do - versionAliases+=( $fullVersion ) - fullVersion="${fullVersion%.*}" -done -versionAliases+=( - $fullVersion - latest -) +# if stable is 1.32.1 and unstable is 1.33.0, we want busybox:1.33 to point to unstable but busybox:1 (and busybox:latest) to point to stable +# since stable always comes first, we'll just let it take all the tags it calculates, and use this to remove any overlap when we process unstable :) +declare -A usedTags=() +_tags() { + local tag first= + for tag; do + [ -z "${usedTags[$tag]:-}" ] || continue + usedTags[$tag]=1 + if [ -z "$first" ]; then + echo + echo -n 'Tags: ' + first=1 + else + echo -n ', ' + fi + echo -n "$tag" + done + if [ -z "$first" ]; then + return 1 + fi + echo + return 0 +} -declare -A archLatest=() -for variant in "${variants[@]}"; do - variantAliases=( "${versionAliases[@]/%/-$variant}" ) - variantAliases=( "${variantAliases[@]//latest-/}" ) +allVersions=() +for version; do + export version - variantArches=() - for arch in "${arches[@]}"; do - archCommit="${archCommits[$arch]}" - if wget --quiet --spider -O /dev/null -o /dev/null "$rawGitUrl/$archCommit/$variant/busybox.tar.xz"; then - variantArches+=( "$arch" ) - if [ -z "${archLatest[$arch]:-}" ]; then - archLatest[$arch]="$variant" + variants="$(jq -r '.[env.version].variants | map(@sh) | join(" ")' versions.json)" + eval "variants=( $variants )" + + fullVersion="$(jq -r '.[env.version].version' versions.json)" + allVersions+=( "$fullVersion" ) + latestVersion="$(xargs -n1 <<<"${allVersions[*]}" | sort -V | tail -1)" + if [ "$latestVersion" != "$fullVersion" ]; then + # if "unstable" is older than "stable" (1.32.0 unstable vs 1.32.1 stable, for example), skip unstable + continue + fi + + versionAliases=() + while [ "${fullVersion%.*}" != "$fullVersion" ]; do + versionAliases+=( $fullVersion ) + fullVersion="${fullVersion%.*}" + done + versionAliases+=( + $fullVersion + $version # "stable", "unstable" + latest + ) + + declare -A archLatestDir=() + for variant in "${variants[@]}"; do + dir="$version/$variant" + + variantAliases=( "${versionAliases[@]/%/-$variant}" ) + variantAliases=( "${variantAliases[@]//latest-/}" ) + + variantArches=() + for arch in "${arches[@]}"; do + archCommit="${archCommits[$arch]}" + if wget --quiet --spider -O /dev/null -o /dev/null "$rawGitUrl/$archCommit/$dir/busybox.tar.xz"; then + variantArches+=( "$arch" ) + : "${archLatestDir[$arch]:=$dir}" # record the first supported directory per architecture for "latest" and friends fi + done + + if _tags "${variantAliases[@]}"; then + cat <<-EOE + Architectures: $(join ', ' "${variantArches[@]}") + Directory: $dir + EOE fi done - echo - cat <<-EOE - Tags: $(join ', ' "${variantAliases[@]}") - Architectures: $(join ', ' "${variantArches[@]}") - Directory: $variant - EOE -done - -echo -cat <<-EOE - Tags: $(join ', ' "${versionAliases[@]}") - Architectures: $(join ', ' "${arches[@]}") -EOE -for arch in "${arches[@]}"; do - archVariant="${archLatest[$arch]}" - cat <<-EOA - ${arch}-Directory: $archVariant - EOA + if _tags "${versionAliases[@]}"; then + cat <<-EOE + Architectures: $(join ', ' "${arches[@]}") + EOE + for arch in "${arches[@]}"; do + archDir="${archLatestDir[$arch]}" + cat <<-EOA + ${arch}-Directory: $archDir + EOA + done + fi done diff --git a/musl/Dockerfile b/stable/glibc/Dockerfile similarity index 100% rename from musl/Dockerfile rename to stable/glibc/Dockerfile diff --git a/stable/glibc/Dockerfile.builder b/stable/glibc/Dockerfile.builder new file mode 100644 index 0000000..4c994eb --- /dev/null +++ b/stable/glibc/Dockerfile.builder @@ -0,0 +1,199 @@ +# +# NOTE: THIS DOCKERFILE IS GENERATED VIA "apply-templates.sh" +# +# PLEASE DO NOT EDIT IT DIRECTLY. +# + +FROM debian:buster-slim + +RUN set -eux; \ + apt-get update; \ + apt-get install -y \ + bzip2 \ + curl \ + gcc \ + gnupg dirmngr \ + make \ + ; \ + rm -rf /var/lib/apt/lists/* + +# pub 1024D/ACC9965B 2006-12-12 +# Key fingerprint = C9E9 416F 76E6 10DB D09D 040F 47B7 0C55 ACC9 965B +# uid Denis Vlasenko +# sub 1024g/2C766641 2006-12-12 +RUN gpg --batch --keyserver ha.pool.sks-keyservers.net --recv-keys C9E9416F76E610DBD09D040F47B70C55ACC9965B + +ENV BUSYBOX_VERSION 1.32.1 +ENV BUSYBOX_SHA256 9d57c4bd33974140fd4111260468af22856f12f5b5ef7c70c8d9b75c712a0dee + +RUN set -eux; \ + tarball="busybox-${BUSYBOX_VERSION}.tar.bz2"; \ + curl -fL -o busybox.tar.bz2.sig "https://busybox.net/downloads/$tarball.sig"; \ + curl -fL -o busybox.tar.bz2 "https://busybox.net/downloads/$tarball"; \ + echo "$BUSYBOX_SHA256 *busybox.tar.bz2" | sha256sum -c -; \ + gpg --batch --verify busybox.tar.bz2.sig busybox.tar.bz2; \ + mkdir -p /usr/src/busybox; \ + tar -xf busybox.tar.bz2 -C /usr/src/busybox --strip-components 1; \ + rm busybox.tar.bz2* + +WORKDIR /usr/src/busybox + +RUN set -eux; \ + \ + setConfs=' \ + CONFIG_AR=y \ + CONFIG_FEATURE_AR_CREATE=y \ + CONFIG_FEATURE_AR_LONG_FILENAMES=y \ +# CONFIG_LAST_SUPPORTED_WCHAR: see https://github.com/docker-library/busybox/issues/13 (UTF-8 input) + CONFIG_LAST_SUPPORTED_WCHAR=0 \ +# As long as we rely on libnss (see below), we have to have libc.so anyhow, so we've removed CONFIG_STATIC here... :cry: + '; \ + \ + unsetConfs=' \ + CONFIG_FEATURE_SYNC_FANCY \ + '; \ + \ + make defconfig; \ + \ + for conf in $unsetConfs; do \ + sed -i \ + -e "s!^$conf=.*\$!# $conf is not set!" \ + .config; \ + done; \ + \ + for confV in $setConfs; do \ + conf="${confV%=*}"; \ + sed -i \ + -e "s!^$conf=.*\$!$confV!" \ + -e "s!^# $conf is not set\$!$confV!" \ + .config; \ + if ! grep -q "^$confV\$" .config; then \ + echo "$confV" >> .config; \ + fi; \ + done; \ + \ + make oldconfig; \ + \ +# trust, but verify + for conf in $unsetConfs; do \ + ! grep -q "^$conf=" .config; \ + done; \ + for confV in $setConfs; do \ + grep -q "^$confV\$" .config; \ + done + +RUN set -eux; \ + nproc="$(nproc)"; \ + make -j "$nproc" busybox; \ + ./busybox --help; \ + mkdir -p rootfs/bin; \ + ln -vL busybox rootfs/bin/; \ + \ +# copy "getconf" from Debian + getconf="$(which getconf)"; \ + ln -vL "$getconf" rootfs/bin/getconf; \ + \ +# hack hack hack hack hack +# with glibc, busybox (static or not) uses libnss for DNS resolution :( + mkdir -p rootfs/etc; \ + cp /etc/nsswitch.conf rootfs/etc/; \ + mkdir -p rootfs/lib; \ + ln -sT lib rootfs/lib64; \ + gccMultiarch="$(gcc -print-multiarch)"; \ + set -- \ + rootfs/bin/busybox \ + rootfs/bin/getconf \ + /lib/"$gccMultiarch"/libnss*.so.* \ +# libpthread is part of glibc: https://stackoverflow.com/a/11210463/433558 + /lib/"$gccMultiarch"/libpthread*.so.* \ + ; \ + while [ "$#" -gt 0 ]; do \ + f="$1"; shift; \ + fn="$(basename "$f")"; \ + if [ -e "rootfs/lib/$fn" ]; then continue; fi; \ + if [ "${f#rootfs/}" = "$f" ]; then \ + if [ "${fn#ld-}" = "$fn" ]; then \ + ln -vL "$f" "rootfs/lib/$fn"; \ + else \ + cp -v "$f" "rootfs/lib/$fn"; \ + fi; \ + fi; \ + ldd="$(ldd "$f" | awk ' \ + $1 ~ /^\// { print $1; next } \ + $2 == "=>" && $3 ~ /^\// { print $3; next } \ + ')"; \ + set -- "$@" $ldd; \ + done; \ + chroot rootfs /bin/getconf _NPROCESSORS_ONLN; \ + \ + chroot rootfs /bin/busybox --install /bin + +# install a few extra files from buildroot (/etc/passwd, etc) +RUN set -eux; \ + buildrootVersion='2020.11.1'; \ + for file in \ + system/device_table.txt \ + system/skeleton/etc/group \ + system/skeleton/etc/passwd \ + system/skeleton/etc/shadow \ + ; do \ + dir="$(dirname "$file")"; \ + mkdir -p "../buildroot/$dir"; \ + curl -fL -o "../buildroot/$file" "https://git.busybox.net/buildroot/plain/$file?id=$buildrootVersion"; \ + [ -s "../buildroot/$file" ]; \ + done; \ + \ + mkdir -p rootfs/etc; \ + ln -vL \ + ../buildroot/system/skeleton/etc/group \ + ../buildroot/system/skeleton/etc/passwd \ + ../buildroot/system/skeleton/etc/shadow \ + rootfs/etc/ \ + ; \ +# CVE-2019-5021, https://github.com/docker-library/official-images/pull/5880#issuecomment-490681907 + grep -E '^root::' rootfs/etc/shadow; \ + sed -ri -e 's/^root::/root:*:/' rootfs/etc/shadow; \ + grep -E '^root:[*]:' rootfs/etc/shadow; \ +# set expected permissions, etc too (https://git.busybox.net/buildroot/tree/system/device_table.txt) + awk ' \ + !/^#/ { \ + if ($2 != "d" && $2 != "f") { \ + printf "error: unknown type \"%s\" encountered in line %d: %s\n", $2, NR, $0 > "/dev/stderr"; \ + exit 1; \ + } \ + sub(/^\/?/, "rootfs/", $1); \ + if ($2 == "d") { \ + printf "mkdir -p %s\n", $1; \ + } \ + printf "chmod %s %s\n", $3, $1; \ + } \ + ' ../buildroot/system/device_table.txt | sh -eux + +# create missing home directories +RUN set -eux; \ + cd rootfs; \ + for userHome in $(awk -F ':' '{ print $3 ":" $4 "=" $6 }' etc/passwd); do \ + user="${userHome%%=*}"; \ + home="${userHome#*=}"; \ + home="./${home#/}"; \ + if [ ! -d "$home" ]; then \ + mkdir -p "$home"; \ + chown "$user" "$home"; \ + chmod 755 "$home"; \ + fi; \ + done + +# test and make sure it works +RUN chroot rootfs /bin/sh -xec 'true' + +# ensure correct timezone (UTC) +RUN set -eux; \ + ln -vL /usr/share/zoneinfo/UTC rootfs/etc/localtime; \ + [ "$(chroot rootfs date +%Z)" = 'UTC' ] + +# test and make sure DNS works too +RUN cp -L /etc/resolv.conf rootfs/etc/; \ + chroot rootfs /bin/sh -xec 'nslookup google.com'; \ + rm rootfs/etc/resolv.conf + +# vim:set ft=dockerfile: diff --git a/uclibc/Dockerfile b/stable/musl/Dockerfile similarity index 100% rename from uclibc/Dockerfile rename to stable/musl/Dockerfile diff --git a/stable/musl/Dockerfile.builder b/stable/musl/Dockerfile.builder new file mode 100644 index 0000000..607e999 --- /dev/null +++ b/stable/musl/Dockerfile.builder @@ -0,0 +1,179 @@ +# +# NOTE: THIS DOCKERFILE IS GENERATED VIA "apply-templates.sh" +# +# PLEASE DO NOT EDIT IT DIRECTLY. +# + +FROM alpine:3.12 + +RUN set -eux; \ + apk add --no-cache \ + bzip2 \ + coreutils \ + curl \ + gcc \ + gnupg \ + linux-headers \ + make \ + musl-dev \ + tzdata \ + ; + +# pub 1024D/ACC9965B 2006-12-12 +# Key fingerprint = C9E9 416F 76E6 10DB D09D 040F 47B7 0C55 ACC9 965B +# uid Denis Vlasenko +# sub 1024g/2C766641 2006-12-12 +RUN gpg --batch --keyserver ha.pool.sks-keyservers.net --recv-keys C9E9416F76E610DBD09D040F47B70C55ACC9965B + +ENV BUSYBOX_VERSION 1.32.1 +ENV BUSYBOX_SHA256 9d57c4bd33974140fd4111260468af22856f12f5b5ef7c70c8d9b75c712a0dee + +RUN set -eux; \ + tarball="busybox-${BUSYBOX_VERSION}.tar.bz2"; \ + curl -fL -o busybox.tar.bz2.sig "https://busybox.net/downloads/$tarball.sig"; \ + curl -fL -o busybox.tar.bz2 "https://busybox.net/downloads/$tarball"; \ + echo "$BUSYBOX_SHA256 *busybox.tar.bz2" | sha256sum -c -; \ + gpg --batch --verify busybox.tar.bz2.sig busybox.tar.bz2; \ + mkdir -p /usr/src/busybox; \ + tar -xf busybox.tar.bz2 -C /usr/src/busybox --strip-components 1; \ + rm busybox.tar.bz2* + +WORKDIR /usr/src/busybox + +RUN set -eux; \ + \ + setConfs=' \ + CONFIG_AR=y \ + CONFIG_FEATURE_AR_CREATE=y \ + CONFIG_FEATURE_AR_LONG_FILENAMES=y \ +# CONFIG_LAST_SUPPORTED_WCHAR: see https://github.com/docker-library/busybox/issues/13 (UTF-8 input) + CONFIG_LAST_SUPPORTED_WCHAR=0 \ + CONFIG_STATIC=y \ + '; \ + \ + unsetConfs=' \ + CONFIG_FEATURE_SYNC_FANCY \ + \ +# see https://wiki.musl-libc.org/wiki/Building_Busybox + CONFIG_FEATURE_HAVE_RPC \ + CONFIG_FEATURE_INETD_RPC \ + CONFIG_FEATURE_UTMP \ + CONFIG_FEATURE_WTMP \ + '; \ + \ + make defconfig; \ + \ + for conf in $unsetConfs; do \ + sed -i \ + -e "s!^$conf=.*\$!# $conf is not set!" \ + .config; \ + done; \ + \ + for confV in $setConfs; do \ + conf="${confV%=*}"; \ + sed -i \ + -e "s!^$conf=.*\$!$confV!" \ + -e "s!^# $conf is not set\$!$confV!" \ + .config; \ + if ! grep -q "^$confV\$" .config; then \ + echo "$confV" >> .config; \ + fi; \ + done; \ + \ + make oldconfig; \ + \ +# trust, but verify + for conf in $unsetConfs; do \ + ! grep -q "^$conf=" .config; \ + done; \ + for confV in $setConfs; do \ + grep -q "^$confV\$" .config; \ + done + +RUN set -eux; \ + nproc="$(nproc)"; \ + make -j "$nproc" busybox; \ + ./busybox --help; \ + mkdir -p rootfs/bin; \ + ln -vL busybox rootfs/bin/; \ + \ +# copy simplified getconf port from Alpine + aportsVersion="v$(cat /etc/alpine-release)"; \ + curl -fsSL \ + "https://git.alpinelinux.org/cgit/aports/plain/main/musl/getconf.c?h=${aportsVersion}" \ + -o /usr/src/getconf.c \ + ; \ + gcc -o rootfs/bin/getconf -static -Os /usr/src/getconf.c; \ + chroot rootfs /bin/getconf _NPROCESSORS_ONLN; \ + \ + chroot rootfs /bin/busybox --install /bin + +# install a few extra files from buildroot (/etc/passwd, etc) +RUN set -eux; \ + buildrootVersion='2020.11.1'; \ + for file in \ + system/device_table.txt \ + system/skeleton/etc/group \ + system/skeleton/etc/passwd \ + system/skeleton/etc/shadow \ + ; do \ + dir="$(dirname "$file")"; \ + mkdir -p "../buildroot/$dir"; \ + curl -fL -o "../buildroot/$file" "https://git.busybox.net/buildroot/plain/$file?id=$buildrootVersion"; \ + [ -s "../buildroot/$file" ]; \ + done; \ + \ + mkdir -p rootfs/etc; \ + ln -vL \ + ../buildroot/system/skeleton/etc/group \ + ../buildroot/system/skeleton/etc/passwd \ + ../buildroot/system/skeleton/etc/shadow \ + rootfs/etc/ \ + ; \ +# CVE-2019-5021, https://github.com/docker-library/official-images/pull/5880#issuecomment-490681907 + grep -E '^root::' rootfs/etc/shadow; \ + sed -ri -e 's/^root::/root:*:/' rootfs/etc/shadow; \ + grep -E '^root:[*]:' rootfs/etc/shadow; \ +# set expected permissions, etc too (https://git.busybox.net/buildroot/tree/system/device_table.txt) + awk ' \ + !/^#/ { \ + if ($2 != "d" && $2 != "f") { \ + printf "error: unknown type \"%s\" encountered in line %d: %s\n", $2, NR, $0 > "/dev/stderr"; \ + exit 1; \ + } \ + sub(/^\/?/, "rootfs/", $1); \ + if ($2 == "d") { \ + printf "mkdir -p %s\n", $1; \ + } \ + printf "chmod %s %s\n", $3, $1; \ + } \ + ' ../buildroot/system/device_table.txt | sh -eux + +# create missing home directories +RUN set -eux; \ + cd rootfs; \ + for userHome in $(awk -F ':' '{ print $3 ":" $4 "=" $6 }' etc/passwd); do \ + user="${userHome%%=*}"; \ + home="${userHome#*=}"; \ + home="./${home#/}"; \ + if [ ! -d "$home" ]; then \ + mkdir -p "$home"; \ + chown "$user" "$home"; \ + chmod 755 "$home"; \ + fi; \ + done + +# test and make sure it works +RUN chroot rootfs /bin/sh -xec 'true' + +# ensure correct timezone (UTC) +RUN set -eux; \ + ln -vL /usr/share/zoneinfo/UTC rootfs/etc/localtime; \ + [ "$(chroot rootfs date +%Z)" = 'UTC' ] + +# test and make sure DNS works too +RUN cp -L /etc/resolv.conf rootfs/etc/; \ + chroot rootfs /bin/sh -xec 'nslookup google.com'; \ + rm rootfs/etc/resolv.conf + +# vim:set ft=dockerfile: diff --git a/stable/uclibc/Dockerfile b/stable/uclibc/Dockerfile new file mode 100644 index 0000000..4c1acc7 --- /dev/null +++ b/stable/uclibc/Dockerfile @@ -0,0 +1,3 @@ +FROM scratch +ADD busybox.tar.xz / +CMD ["sh"] diff --git a/stable/uclibc/Dockerfile.builder b/stable/uclibc/Dockerfile.builder new file mode 100644 index 0000000..bcbc1e7 --- /dev/null +++ b/stable/uclibc/Dockerfile.builder @@ -0,0 +1,327 @@ +# +# NOTE: THIS DOCKERFILE IS GENERATED VIA "apply-templates.sh" +# +# PLEASE DO NOT EDIT IT DIRECTLY. +# + +FROM debian:buster-slim + +RUN set -eux; \ + apt-get update; \ + apt-get install -y \ + bzip2 \ + curl \ + gcc \ + gnupg dirmngr \ + make \ + ; \ + rm -rf /var/lib/apt/lists/* + +# grab/use buildroot for its uClibc toolchain + +RUN set -eux; \ + apt-get update; \ + apt-get install -y \ + bc \ + cpio \ + dpkg-dev \ + g++ \ + patch \ + perl \ + python \ + rsync \ + unzip \ + wget \ + ; \ + rm -rf /var/lib/apt/lists/* + +# pub 1024D/59C36319 2009-01-15 +# Key fingerprint = AB07 D806 D2CE 741F B886 EE50 B025 BA8B 59C3 6319 +# uid Peter Korsgaard +# sub 2048g/45428075 2009-01-15 +RUN gpg --batch --keyserver ha.pool.sks-keyservers.net --recv-keys AB07D806D2CE741FB886EE50B025BA8B59C36319 + +# https://buildroot.org/download.html +# https://buildroot.org/downloads/?C=M;O=D +ENV BUILDROOT_VERSION 2020.11.1 + +RUN set -eux; \ + tarball="buildroot-${BUILDROOT_VERSION}.tar.bz2"; \ + curl -fL -o buildroot.tar.bz2 "https://buildroot.org/downloads/$tarball"; \ + curl -fL -o buildroot.tar.bz2.sign "https://buildroot.org/downloads/$tarball.sign"; \ + gpg --batch --decrypt --output buildroot.tar.bz2.txt buildroot.tar.bz2.sign; \ + awk '$1 == "SHA1:" && $2 ~ /^[0-9a-f]+$/ && $3 == "'"$tarball"'" { print $2, "*buildroot.tar.bz2" }' buildroot.tar.bz2.txt > buildroot.tar.bz2.sha1; \ + test -s buildroot.tar.bz2.sha1; \ + sha1sum -c buildroot.tar.bz2.sha1; \ + mkdir -p /usr/src/buildroot; \ + tar -xf buildroot.tar.bz2 -C /usr/src/buildroot --strip-components 1; \ + rm buildroot.tar.bz2* + +RUN set -eux; \ + \ + cd /usr/src/buildroot; \ + \ + setConfs=' \ + BR2_STATIC_LIBS=y \ + BR2_TOOLCHAIN_BUILDROOT_UCLIBC=y \ + BR2_TOOLCHAIN_BUILDROOT_WCHAR=y \ + '; \ + \ + unsetConfs=' \ + BR2_SHARED_LIBS \ + '; \ + \ +# buildroot arches: https://git.busybox.net/buildroot/tree/arch +# buildroot+uclibc arches: https://git.busybox.net/buildroot/tree/toolchain/toolchain-buildroot/Config.in ("config BR2_TOOLCHAIN_BUILDROOT_UCLIBC") + dpkgArch="$(dpkg --print-architecture)"; \ + case "$dpkgArch" in \ + amd64) \ + setConfs="$setConfs \ + BR2_x86_64=y \ + "; \ + ;; \ + \ + arm64) \ + setConfs="$setConfs \ + BR2_aarch64=y \ + "; \ + ;; \ + \ +# https://wiki.debian.org/ArmEabiPort#Choice_of_minimum_CPU +# https://github.com/free-electrons/toolchains-builder/blob/db259641eaf5bbcf13f4a3c5003e5436e806770c/configs/arch/armv5-eabi.config +# https://git.busybox.net/buildroot/tree/arch/Config.in.arm +# (Debian minimums at ARMv4, we minimum at ARMv5 instead) + armel) \ + setConfs="$setConfs \ + BR2_arm=y \ + BR2_arm926t=y \ + BR2_ARM_EABI=y \ + BR2_ARM_INSTRUCTIONS_THUMB=y \ + BR2_ARM_SOFT_FLOAT=y \ + "; \ + ;; \ + \ +# "Currently the Debian armhf port requires at least an ARMv7 CPU with Thumb-2 and VFP3D16." +# https://wiki.debian.org/ArmHardFloatPort#Supported_devices +# https://github.com/free-electrons/toolchains-builder/blob/db259641eaf5bbcf13f4a3c5003e5436e806770c/configs/arch/armv7-eabihf.config +# https://git.busybox.net/buildroot/tree/arch/Config.in.arm + armhf) \ + setConfs="$setConfs \ + BR2_arm=y \ + BR2_cortex_a9=y \ + BR2_ARM_EABIHF=y \ + BR2_ARM_ENABLE_VFP=y \ + BR2_ARM_FPU_VFPV3D16=y \ + BR2_ARM_INSTRUCTIONS_THUMB2=y \ + "; \ + unsetConfs="$unsetConfs BR2_ARM_SOFT_FLOAT"; \ + ;; \ + \ + i386) \ + setConfs="$setConfs \ + BR2_i386=y \ + "; \ + ;; \ + \ + mips64el) \ + setConfs="$setConfs \ + BR2_mips64el=y \ + BR2_mips_64r2=y \ + BR2_MIPS_NABI64=y \ + "; \ + unsetConfs="$unsetConfs \ + BR2_MIPS_SOFT_FLOAT \ + " \ + ;; \ + \ +# TODO ppc64el ? (needs BR2_TOOLCHAIN_BUILDROOT_UCLIBC support) + \ +# TODO s390x ? (needs BR2_TOOLCHAIN_BUILDROOT_UCLIBC support) + \ + *) \ + echo >&2 "error: unsupported architecture '$dpkgArch'!"; \ + exit 1; \ + ;; \ + esac; \ + if [ "$dpkgArch" != 'i386' ]; then \ + unsetConfs="$unsetConfs BR2_i386"; \ + fi; \ + \ + make defconfig; \ + \ + for conf in $unsetConfs; do \ + sed -i \ + -e "s!^$conf=.*\$!# $conf is not set!" \ + .config; \ + done; \ + \ + for confV in $setConfs; do \ + conf="${confV%=*}"; \ + sed -i \ + -e "s!^$conf=.*\$!$confV!" \ + -e "s!^# $conf is not set\$!$confV!" \ + .config; \ + if ! grep -q "^$confV\$" .config; then \ + echo "$confV" >> .config; \ + fi; \ + done; \ + \ + make oldconfig; \ + \ +# trust, but verify + for conf in $unsetConfs; do \ + ! grep -q "^$conf=" .config; \ + done; \ + for confV in $setConfs; do \ + grep -q "^$confV\$" .config; \ + done; + +# https://www.finnie.org/2014/02/13/compiling-busybox-with-uclibc/ +RUN set -eux; \ +# force a particular GNU arch for "host-gmp" (otherwise it fails on some arches) + gnuArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; \ + make -C /usr/src/buildroot \ + HOST_GMP_CONF_OPTS="--build='"$gnuArch"'" \ +# building host-tar: +# configure: error: you should not run configure as root (set FORCE_UNSAFE_CONFIGURE=1 in environment to bypass this check) + FORCE_UNSAFE_CONFIGURE=1 \ + -j "$(nproc)" \ + toolchain +ENV PATH /usr/src/buildroot/output/host/usr/bin:$PATH + +# pub 1024D/ACC9965B 2006-12-12 +# Key fingerprint = C9E9 416F 76E6 10DB D09D 040F 47B7 0C55 ACC9 965B +# uid Denis Vlasenko +# sub 1024g/2C766641 2006-12-12 +RUN gpg --batch --keyserver ha.pool.sks-keyservers.net --recv-keys C9E9416F76E610DBD09D040F47B70C55ACC9965B + +ENV BUSYBOX_VERSION 1.32.1 +ENV BUSYBOX_SHA256 9d57c4bd33974140fd4111260468af22856f12f5b5ef7c70c8d9b75c712a0dee + +RUN set -eux; \ + tarball="busybox-${BUSYBOX_VERSION}.tar.bz2"; \ + curl -fL -o busybox.tar.bz2.sig "https://busybox.net/downloads/$tarball.sig"; \ + curl -fL -o busybox.tar.bz2 "https://busybox.net/downloads/$tarball"; \ + echo "$BUSYBOX_SHA256 *busybox.tar.bz2" | sha256sum -c -; \ + gpg --batch --verify busybox.tar.bz2.sig busybox.tar.bz2; \ + mkdir -p /usr/src/busybox; \ + tar -xf busybox.tar.bz2 -C /usr/src/busybox --strip-components 1; \ + rm busybox.tar.bz2* + +WORKDIR /usr/src/busybox + +RUN set -eux; \ + \ + setConfs=' \ + CONFIG_AR=y \ + CONFIG_FEATURE_AR_CREATE=y \ + CONFIG_FEATURE_AR_LONG_FILENAMES=y \ +# CONFIG_LAST_SUPPORTED_WCHAR: see https://github.com/docker-library/busybox/issues/13 (UTF-8 input) + CONFIG_LAST_SUPPORTED_WCHAR=0 \ + CONFIG_STATIC=y \ + '; \ + \ + unsetConfs=' \ + CONFIG_FEATURE_SYNC_FANCY \ + '; \ + \ + make defconfig; \ + \ + for conf in $unsetConfs; do \ + sed -i \ + -e "s!^$conf=.*\$!# $conf is not set!" \ + .config; \ + done; \ + \ + for confV in $setConfs; do \ + conf="${confV%=*}"; \ + sed -i \ + -e "s!^$conf=.*\$!$confV!" \ + -e "s!^# $conf is not set\$!$confV!" \ + .config; \ + if ! grep -q "^$confV\$" .config; then \ + echo "$confV" >> .config; \ + fi; \ + done; \ + \ + make oldconfig; \ + \ +# trust, but verify + for conf in $unsetConfs; do \ + ! grep -q "^$conf=" .config; \ + done; \ + for confV in $setConfs; do \ + grep -q "^$confV\$" .config; \ + done + +RUN set -eux; \ + nproc="$(nproc)"; \ + CROSS_COMPILE="$(basename /usr/src/buildroot/output/host/usr/*-buildroot-linux-uclibc*)"; \ + export CROSS_COMPILE="$CROSS_COMPILE-"; \ + make -j "$nproc" busybox; \ + ./busybox --help; \ + mkdir -p rootfs/bin; \ + ln -vL busybox rootfs/bin/; \ + \ +# copy "getconf" from buildroot + ln -vL ../buildroot/output/target/usr/bin/getconf rootfs/bin/; \ + chroot rootfs /bin/getconf _NPROCESSORS_ONLN; \ + \ + chroot rootfs /bin/busybox --install /bin + +# install a few extra files from buildroot (/etc/passwd, etc) +RUN set -eux; \ + mkdir -p rootfs/etc; \ + ln -vL \ + ../buildroot/system/skeleton/etc/group \ + ../buildroot/system/skeleton/etc/passwd \ + ../buildroot/system/skeleton/etc/shadow \ + rootfs/etc/ \ + ; \ +# CVE-2019-5021, https://github.com/docker-library/official-images/pull/5880#issuecomment-490681907 + grep -E '^root::' rootfs/etc/shadow; \ + sed -ri -e 's/^root::/root:*:/' rootfs/etc/shadow; \ + grep -E '^root:[*]:' rootfs/etc/shadow; \ +# set expected permissions, etc too (https://git.busybox.net/buildroot/tree/system/device_table.txt) + awk ' \ + !/^#/ { \ + if ($2 != "d" && $2 != "f") { \ + printf "error: unknown type \"%s\" encountered in line %d: %s\n", $2, NR, $0 > "/dev/stderr"; \ + exit 1; \ + } \ + sub(/^\/?/, "rootfs/", $1); \ + if ($2 == "d") { \ + printf "mkdir -p %s\n", $1; \ + } \ + printf "chmod %s %s\n", $3, $1; \ + } \ + ' ../buildroot/system/device_table.txt | sh -eux + +# create missing home directories +RUN set -eux; \ + cd rootfs; \ + for userHome in $(awk -F ':' '{ print $3 ":" $4 "=" $6 }' etc/passwd); do \ + user="${userHome%%=*}"; \ + home="${userHome#*=}"; \ + home="./${home#/}"; \ + if [ ! -d "$home" ]; then \ + mkdir -p "$home"; \ + chown "$user" "$home"; \ + chmod 755 "$home"; \ + fi; \ + done + +# test and make sure it works +RUN chroot rootfs /bin/sh -xec 'true' + +# ensure correct timezone (UTC) +RUN set -eux; \ + ln -vL /usr/share/zoneinfo/UTC rootfs/etc/localtime; \ + [ "$(chroot rootfs date +%Z)" = 'UTC' ] + +# test and make sure DNS works too +RUN cp -L /etc/resolv.conf rootfs/etc/; \ + chroot rootfs /bin/sh -xec 'nslookup google.com'; \ + rm rootfs/etc/resolv.conf + +# vim:set ft=dockerfile: diff --git a/unstable/glibc/Dockerfile b/unstable/glibc/Dockerfile new file mode 100644 index 0000000..4c1acc7 --- /dev/null +++ b/unstable/glibc/Dockerfile @@ -0,0 +1,3 @@ +FROM scratch +ADD busybox.tar.xz / +CMD ["sh"] diff --git a/glibc/Dockerfile.builder b/unstable/glibc/Dockerfile.builder similarity index 74% rename from glibc/Dockerfile.builder rename to unstable/glibc/Dockerfile.builder index 0d96020..05747b9 100644 --- a/glibc/Dockerfile.builder +++ b/unstable/glibc/Dockerfile.builder @@ -1,3 +1,9 @@ +# +# NOTE: THIS DOCKERFILE IS GENERATED VIA "apply-templates.sh" +# +# PLEASE DO NOT EDIT IT DIRECTLY. +# + FROM debian:buster-slim RUN set -eux; \ @@ -18,11 +24,13 @@ RUN set -eux; \ RUN gpg --batch --keyserver ha.pool.sks-keyservers.net --recv-keys C9E9416F76E610DBD09D040F47B70C55ACC9965B ENV BUSYBOX_VERSION 1.33.0 +ENV BUSYBOX_SHA256 d568681c91a85edc6710770cebc1e80e042ad74d305b5c2e6d57a5f3de3b8fbd RUN set -eux; \ tarball="busybox-${BUSYBOX_VERSION}.tar.bz2"; \ - curl -fL -o busybox.tar.bz2 "https://busybox.net/downloads/$tarball"; \ curl -fL -o busybox.tar.bz2.sig "https://busybox.net/downloads/$tarball.sig"; \ + curl -fL -o busybox.tar.bz2 "https://busybox.net/downloads/$tarball"; \ + echo "$BUSYBOX_SHA256 *busybox.tar.bz2" | sha256sum -c -; \ gpg --batch --verify busybox.tar.bz2.sig busybox.tar.bz2; \ mkdir -p /usr/src/busybox; \ tar -xf busybox.tar.bz2 -C /usr/src/busybox --strip-components 1; \ @@ -30,16 +38,15 @@ RUN set -eux; \ WORKDIR /usr/src/busybox -# CONFIG_LAST_SUPPORTED_WCHAR: see https://github.com/docker-library/busybox/issues/13 (UTF-8 input) RUN set -eux; \ \ setConfs=' \ CONFIG_AR=y \ CONFIG_FEATURE_AR_CREATE=y \ CONFIG_FEATURE_AR_LONG_FILENAMES=y \ +# CONFIG_LAST_SUPPORTED_WCHAR: see https://github.com/docker-library/busybox/issues/13 (UTF-8 input) CONFIG_LAST_SUPPORTED_WCHAR=0 \ -# As long as we rely on libnss, we have to have libc.so anyhow, so -# we've removed CONFIG_STATIC here for now... :cry: +# As long as we rely on libnss (see below), we have to have libc.so anyhow, so we've removed CONFIG_STATIC here... :cry: '; \ \ unsetConfs=' \ @@ -73,30 +80,32 @@ RUN set -eux; \ done; \ for confV in $setConfs; do \ grep -q "^$confV\$" .config; \ - done; + done RUN set -eux; \ - make -j "$(nproc)" \ - busybox \ - ; \ + nproc="$(nproc)"; \ + make -j "$nproc" busybox; \ ./busybox --help; \ mkdir -p rootfs/bin; \ ln -vL busybox rootfs/bin/; \ \ - ln -vL "$(which getconf)" rootfs/bin/getconf; \ +# copy "getconf" from Debian + getconf="$(which getconf)"; \ + ln -vL "$getconf" rootfs/bin/getconf; \ \ # hack hack hack hack hack -# with glibc, static busybox uses libnss for DNS resolution :( +# with glibc, busybox (static or not) uses libnss for DNS resolution :( mkdir -p rootfs/etc; \ cp /etc/nsswitch.conf rootfs/etc/; \ mkdir -p rootfs/lib; \ ln -sT lib rootfs/lib64; \ + gccMultiarch="$(gcc -print-multiarch)"; \ set -- \ rootfs/bin/busybox \ rootfs/bin/getconf \ - /lib/"$(gcc -print-multiarch)"/libnss*.so.* \ + /lib/"$gccMultiarch"/libnss*.so.* \ # libpthread is part of glibc: https://stackoverflow.com/a/11210463/433558 - /lib/"$(gcc -print-multiarch)"/libpthread*.so.* \ + /lib/"$gccMultiarch"/libpthread*.so.* \ ; \ while [ "$#" -gt 0 ]; do \ f="$1"; shift; \ @@ -109,29 +118,43 @@ RUN set -eux; \ cp -v "$f" "rootfs/lib/$fn"; \ fi; \ fi; \ - set -- "$@" $(ldd "$f" | awk ' \ + ldd="$(ldd "$f" | awk ' \ $1 ~ /^\// { print $1; next } \ $2 == "=>" && $3 ~ /^\// { print $3; next } \ - '); \ + ')"; \ + set -- "$@" $ldd; \ done; \ - \ chroot rootfs /bin/getconf _NPROCESSORS_ONLN; \ \ chroot rootfs /bin/busybox --install /bin -# download a few extra files from buildroot (/etc/passwd, etc) +# install a few extra files from buildroot (/etc/passwd, etc) RUN set -eux; \ buildrootVersion='2020.11.1'; \ - mkdir -p rootfs/etc; \ - for f in passwd shadow group; do \ - curl -fL -o "rootfs/etc/$f" "https://git.busybox.net/buildroot/plain/system/skeleton/etc/$f?id=$buildrootVersion"; \ + for file in \ + system/device_table.txt \ + system/skeleton/etc/group \ + system/skeleton/etc/passwd \ + system/skeleton/etc/shadow \ + ; do \ + dir="$(dirname "$file")"; \ + mkdir -p "../buildroot/$dir"; \ + curl -fL -o "../buildroot/$file" "https://git.busybox.net/buildroot/plain/$file?id=$buildrootVersion"; \ + [ -s "../buildroot/$file" ]; \ done; \ + \ + mkdir -p rootfs/etc; \ + ln -vL \ + ../buildroot/system/skeleton/etc/group \ + ../buildroot/system/skeleton/etc/passwd \ + ../buildroot/system/skeleton/etc/shadow \ + rootfs/etc/ \ + ; \ # CVE-2019-5021, https://github.com/docker-library/official-images/pull/5880#issuecomment-490681907 grep -E '^root::' rootfs/etc/shadow; \ sed -ri -e 's/^root::/root:*:/' rootfs/etc/shadow; \ grep -E '^root:[*]:' rootfs/etc/shadow; \ # set expected permissions, etc too (https://git.busybox.net/buildroot/tree/system/device_table.txt) - curl -fL -o buildroot-device-table.txt "https://git.busybox.net/buildroot/plain/system/device_table.txt?id=$buildrootVersion"; \ awk ' \ !/^#/ { \ if ($2 != "d" && $2 != "f") { \ @@ -144,8 +167,7 @@ RUN set -eux; \ } \ printf "chmod %s %s\n", $3, $1; \ } \ - ' buildroot-device-table.txt | bash -Eeuo pipefail -x; \ - rm buildroot-device-table.txt + ' ../buildroot/system/device_table.txt | sh -eux # create missing home directories RUN set -eux; \ diff --git a/unstable/musl/Dockerfile b/unstable/musl/Dockerfile new file mode 100644 index 0000000..4c1acc7 --- /dev/null +++ b/unstable/musl/Dockerfile @@ -0,0 +1,3 @@ +FROM scratch +ADD busybox.tar.xz / +CMD ["sh"] diff --git a/musl/Dockerfile.builder b/unstable/musl/Dockerfile.builder similarity index 78% rename from musl/Dockerfile.builder rename to unstable/musl/Dockerfile.builder index 5307afe..b4b2eb8 100644 --- a/musl/Dockerfile.builder +++ b/unstable/musl/Dockerfile.builder @@ -1,6 +1,13 @@ +# +# NOTE: THIS DOCKERFILE IS GENERATED VIA "apply-templates.sh" +# +# PLEASE DO NOT EDIT IT DIRECTLY. +# + FROM alpine:3.12 -RUN apk add --no-cache \ +RUN set -eux; \ + apk add --no-cache \ bzip2 \ coreutils \ curl \ @@ -9,7 +16,8 @@ RUN apk add --no-cache \ linux-headers \ make \ musl-dev \ - tzdata + tzdata \ + ; # pub 1024D/ACC9965B 2006-12-12 # Key fingerprint = C9E9 416F 76E6 10DB D09D 040F 47B7 0C55 ACC9 965B @@ -18,11 +26,13 @@ RUN apk add --no-cache \ RUN gpg --batch --keyserver ha.pool.sks-keyservers.net --recv-keys C9E9416F76E610DBD09D040F47B70C55ACC9965B ENV BUSYBOX_VERSION 1.33.0 +ENV BUSYBOX_SHA256 d568681c91a85edc6710770cebc1e80e042ad74d305b5c2e6d57a5f3de3b8fbd RUN set -eux; \ tarball="busybox-${BUSYBOX_VERSION}.tar.bz2"; \ - curl -fL -o busybox.tar.bz2 "https://busybox.net/downloads/$tarball"; \ curl -fL -o busybox.tar.bz2.sig "https://busybox.net/downloads/$tarball.sig"; \ + curl -fL -o busybox.tar.bz2 "https://busybox.net/downloads/$tarball"; \ + echo "$BUSYBOX_SHA256 *busybox.tar.bz2" | sha256sum -c -; \ gpg --batch --verify busybox.tar.bz2.sig busybox.tar.bz2; \ mkdir -p /usr/src/busybox; \ tar -xf busybox.tar.bz2 -C /usr/src/busybox --strip-components 1; \ @@ -30,18 +40,13 @@ RUN set -eux; \ WORKDIR /usr/src/busybox -# https://www.mail-archive.com/toybox@lists.landley.net/msg02528.html -# https://www.mail-archive.com/toybox@lists.landley.net/msg02526.html -RUN sed -i 's/^struct kconf_id \*$/static &/g' scripts/kconfig/zconf.hash.c_shipped - -# CONFIG_LAST_SUPPORTED_WCHAR: see https://github.com/docker-library/busybox/issues/13 (UTF-8 input) -# see https://wiki.musl-libc.org/wiki/Building_Busybox RUN set -eux; \ \ setConfs=' \ CONFIG_AR=y \ CONFIG_FEATURE_AR_CREATE=y \ CONFIG_FEATURE_AR_LONG_FILENAMES=y \ +# CONFIG_LAST_SUPPORTED_WCHAR: see https://github.com/docker-library/busybox/issues/13 (UTF-8 input) CONFIG_LAST_SUPPORTED_WCHAR=0 \ CONFIG_STATIC=y \ '; \ @@ -49,6 +54,7 @@ RUN set -eux; \ unsetConfs=' \ CONFIG_FEATURE_SYNC_FANCY \ \ +# see https://wiki.musl-libc.org/wiki/Building_Busybox CONFIG_FEATURE_HAVE_RPC \ CONFIG_FEATURE_INETD_RPC \ CONFIG_FEATURE_UTMP \ @@ -82,40 +88,53 @@ RUN set -eux; \ done; \ for confV in $setConfs; do \ grep -q "^$confV\$" .config; \ - done; + done RUN set -eux; \ - make -j "$(nproc)" \ - busybox \ - ; \ + nproc="$(nproc)"; \ + make -j "$nproc" busybox; \ ./busybox --help; \ mkdir -p rootfs/bin; \ ln -vL busybox rootfs/bin/; \ - chroot rootfs /bin/busybox --install /bin - -# grab a simplified getconf port from Alpine we can statically compile -RUN set -eux; \ + \ +# copy simplified getconf port from Alpine aportsVersion="v$(cat /etc/alpine-release)"; \ curl -fsSL \ "https://git.alpinelinux.org/cgit/aports/plain/main/musl/getconf.c?h=${aportsVersion}" \ -o /usr/src/getconf.c \ ; \ gcc -o rootfs/bin/getconf -static -Os /usr/src/getconf.c; \ - chroot rootfs /bin/getconf _NPROCESSORS_ONLN + chroot rootfs /bin/getconf _NPROCESSORS_ONLN; \ + \ + chroot rootfs /bin/busybox --install /bin -# download a few extra files from buildroot (/etc/passwd, etc) +# install a few extra files from buildroot (/etc/passwd, etc) RUN set -eux; \ buildrootVersion='2020.11.1'; \ - mkdir -p rootfs/etc; \ - for f in passwd shadow group; do \ - curl -fL -o "rootfs/etc/$f" "https://git.busybox.net/buildroot/plain/system/skeleton/etc/$f?id=$buildrootVersion"; \ + for file in \ + system/device_table.txt \ + system/skeleton/etc/group \ + system/skeleton/etc/passwd \ + system/skeleton/etc/shadow \ + ; do \ + dir="$(dirname "$file")"; \ + mkdir -p "../buildroot/$dir"; \ + curl -fL -o "../buildroot/$file" "https://git.busybox.net/buildroot/plain/$file?id=$buildrootVersion"; \ + [ -s "../buildroot/$file" ]; \ done; \ + \ + mkdir -p rootfs/etc; \ + ln -vL \ + ../buildroot/system/skeleton/etc/group \ + ../buildroot/system/skeleton/etc/passwd \ + ../buildroot/system/skeleton/etc/shadow \ + rootfs/etc/ \ + ; \ # CVE-2019-5021, https://github.com/docker-library/official-images/pull/5880#issuecomment-490681907 grep -E '^root::' rootfs/etc/shadow; \ sed -ri -e 's/^root::/root:*:/' rootfs/etc/shadow; \ grep -E '^root:[*]:' rootfs/etc/shadow; \ # set expected permissions, etc too (https://git.busybox.net/buildroot/tree/system/device_table.txt) - curl -fL -o buildroot-device-table.txt "https://git.busybox.net/buildroot/plain/system/device_table.txt?id=$buildrootVersion"; \ awk ' \ !/^#/ { \ if ($2 != "d" && $2 != "f") { \ @@ -128,8 +147,7 @@ RUN set -eux; \ } \ printf "chmod %s %s\n", $3, $1; \ } \ - ' buildroot-device-table.txt | sh -eux; \ - rm buildroot-device-table.txt + ' ../buildroot/system/device_table.txt | sh -eux # create missing home directories RUN set -eux; \ diff --git a/unstable/uclibc/Dockerfile b/unstable/uclibc/Dockerfile new file mode 100644 index 0000000..4c1acc7 --- /dev/null +++ b/unstable/uclibc/Dockerfile @@ -0,0 +1,3 @@ +FROM scratch +ADD busybox.tar.xz / +CMD ["sh"] diff --git a/uclibc/Dockerfile.builder b/unstable/uclibc/Dockerfile.builder similarity index 90% rename from uclibc/Dockerfile.builder rename to unstable/uclibc/Dockerfile.builder index a49785b..9241357 100644 --- a/uclibc/Dockerfile.builder +++ b/unstable/uclibc/Dockerfile.builder @@ -1,3 +1,9 @@ +# +# NOTE: THIS DOCKERFILE IS GENERATED VIA "apply-templates.sh" +# +# PLEASE DO NOT EDIT IT DIRECTLY. +# + FROM debian:buster-slim RUN set -eux; \ @@ -8,8 +14,14 @@ RUN set -eux; \ gcc \ gnupg dirmngr \ make \ - \ -# buildroot + ; \ + rm -rf /var/lib/apt/lists/* + +# grab/use buildroot for its uClibc toolchain + +RUN set -eux; \ + apt-get update; \ + apt-get install -y \ bc \ cpio \ dpkg-dev \ @@ -23,8 +35,6 @@ RUN set -eux; \ ; \ rm -rf /var/lib/apt/lists/* -# we grab buildroot for it's uClibc toolchain - # pub 1024D/59C36319 2009-01-15 # Key fingerprint = AB07 D806 D2CE 741F B886 EE50 B025 BA8B 59C3 6319 # uid Peter Korsgaard @@ -186,11 +196,13 @@ ENV PATH /usr/src/buildroot/output/host/usr/bin:$PATH RUN gpg --batch --keyserver ha.pool.sks-keyservers.net --recv-keys C9E9416F76E610DBD09D040F47B70C55ACC9965B ENV BUSYBOX_VERSION 1.33.0 +ENV BUSYBOX_SHA256 d568681c91a85edc6710770cebc1e80e042ad74d305b5c2e6d57a5f3de3b8fbd RUN set -eux; \ tarball="busybox-${BUSYBOX_VERSION}.tar.bz2"; \ - curl -fL -o busybox.tar.bz2 "https://busybox.net/downloads/$tarball"; \ curl -fL -o busybox.tar.bz2.sig "https://busybox.net/downloads/$tarball.sig"; \ + curl -fL -o busybox.tar.bz2 "https://busybox.net/downloads/$tarball"; \ + echo "$BUSYBOX_SHA256 *busybox.tar.bz2" | sha256sum -c -; \ gpg --batch --verify busybox.tar.bz2.sig busybox.tar.bz2; \ mkdir -p /usr/src/busybox; \ tar -xf busybox.tar.bz2 -C /usr/src/busybox --strip-components 1; \ @@ -198,13 +210,13 @@ RUN set -eux; \ WORKDIR /usr/src/busybox -# CONFIG_LAST_SUPPORTED_WCHAR: see https://github.com/docker-library/busybox/issues/13 (UTF-8 input) RUN set -eux; \ \ setConfs=' \ CONFIG_AR=y \ CONFIG_FEATURE_AR_CREATE=y \ CONFIG_FEATURE_AR_LONG_FILENAMES=y \ +# CONFIG_LAST_SUPPORTED_WCHAR: see https://github.com/docker-library/busybox/issues/13 (UTF-8 input) CONFIG_LAST_SUPPORTED_WCHAR=0 \ CONFIG_STATIC=y \ '; \ @@ -240,19 +252,19 @@ RUN set -eux; \ done; \ for confV in $setConfs; do \ grep -q "^$confV\$" .config; \ - done; + done RUN set -eux; \ - make -j "$(nproc)" \ - CROSS_COMPILE="$(basename /usr/src/buildroot/output/host/usr/*-buildroot-linux-uclibc*)-" \ - busybox \ - ; \ + nproc="$(nproc)"; \ + CROSS_COMPILE="$(basename /usr/src/buildroot/output/host/usr/*-buildroot-linux-uclibc*)"; \ + export CROSS_COMPILE="$CROSS_COMPILE-"; \ + make -j "$nproc" busybox; \ ./busybox --help; \ mkdir -p rootfs/bin; \ ln -vL busybox rootfs/bin/; \ \ +# copy "getconf" from buildroot ln -vL ../buildroot/output/target/usr/bin/getconf rootfs/bin/; \ - \ chroot rootfs /bin/getconf _NPROCESSORS_ONLN; \ \ chroot rootfs /bin/busybox --install /bin @@ -260,11 +272,12 @@ RUN set -eux; \ # install a few extra files from buildroot (/etc/passwd, etc) RUN set -eux; \ mkdir -p rootfs/etc; \ - for f in passwd shadow group; do \ - ln -vL \ - "../buildroot/system/skeleton/etc/$f" \ - "rootfs/etc/$f"; \ - done; \ + ln -vL \ + ../buildroot/system/skeleton/etc/group \ + ../buildroot/system/skeleton/etc/passwd \ + ../buildroot/system/skeleton/etc/shadow \ + rootfs/etc/ \ + ; \ # CVE-2019-5021, https://github.com/docker-library/official-images/pull/5880#issuecomment-490681907 grep -E '^root::' rootfs/etc/shadow; \ sed -ri -e 's/^root::/root:*:/' rootfs/etc/shadow; \ @@ -282,7 +295,7 @@ RUN set -eux; \ } \ printf "chmod %s %s\n", $3, $1; \ } \ - ' ../buildroot/system/device_table.txt | bash -Eeuo pipefail -x + ' ../buildroot/system/device_table.txt | sh -eux # create missing home directories RUN set -eux; \ diff --git a/update.sh b/update.sh index f76d759..bac2d75 100755 --- a/update.sh +++ b/update.sh @@ -1,9 +1,7 @@ -#!/bin/bash -set -eo pipefail +#!/usr/bin/env bash +set -Eeuo pipefail cd "$(dirname "$(readlink -f "$BASH_SOURCE")")" -upstreamVersion="$(curl -fsSL --compressed 'https://busybox.net/downloads/' | grep -E '&2 "error: failed to find latest '$version' release" + exit 1 + fi + fullVersion="${fullVersion%% *}" + export fullVersion + + sha256="$(wget -qO- "https://busybox.net/downloads/busybox-$fullVersion.tar.bz2.sha256" | cut -d' ' -f1)" + export sha256 + + echo "$version: $fullVersion" + + json="$( + jq <<<"$json" -c ' + .[env.version] = { + version: env.fullVersion, + sha256: env.sha256, + buildroot: { + version: env.buildrootVersion, + }, + # prefer uclibc, but if unavailable use glibc since it has less "edge case" behavior + # https://busybox.net/FAQ.html#libc + variants: [ "uclibc", "glibc", "musl" ], + # (order here determines "preference" for representing "latest") + } + ' + )" +done + +jq <<<"$json" -S . > versions.json