From a66bded4ce244f87efbaf7ff3168be31c2e7377c Mon Sep 17 00:00:00 2001 From: Jeremi Piotrowski Date: Wed, 13 Jul 2022 15:43:15 +0200 Subject: [PATCH 1/6] install_cross_libs: fix toolchain dependency installation `./setup_board --nousepkg --nogetbinpkg` currently fails with a circular dependency due to pulling in the whole systemd-cryptsetup-udev dependency chain. This is due to several issue: * `emerge --root=$ROOT --emptytree` considers ROOT=/ to also be empty, so it pulls in all host packages. This must've not always been the case. So we need to pipe the dependency package list through `egrep $ROOT` to filter only those that would get installed into the desired ROOT * if SYSROOT=/ and not SYSROOT=ROOT, then virtual/os-headers is missing from $ROOT package list * the final filter expression tries to previously looked like this: (=sys-devel/gcc|sys-devel/binutils-0.9) which also matches sys-devel/gcc-config and sys-devel/binutils-config, which are necessary dependencies. Rework the match expression to not filter those out. --- build_library/toolchain_util.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/build_library/toolchain_util.sh b/build_library/toolchain_util.sh index 7315ef6780..f9328b4345 100644 --- a/build_library/toolchain_util.sh +++ b/build_library/toolchain_util.sh @@ -262,8 +262,9 @@ _get_dependency_list() { PORTAGE_CONFIGROOT="$ROOT" emerge "$@" --pretend \ --emptytree --root-deps=rdeps --onlydeps --quiet | \ + egrep "$ROOT" | sed -e 's/[^]]*\] \([^ :]*\).*/=\1/' | - egrep -v "(=$(echo "${pkgs[*]}")-[0-9])" + egrep -v "=($(echo "${pkgs[*]}"))-[0-9]" } # Configure a new ROOT @@ -392,7 +393,7 @@ install_cross_libs() { # In order to get a dependency list we must calculate it before # updating package.provided. Otherwise portage will no-op. $sudo rm -f "${package_provided}/cross-${cross_chost}" - local cross_deps=$(ROOT="$ROOT" _get_dependency_list \ + local cross_deps=$(ROOT="$ROOT" SYSROOT="$ROOT" _get_dependency_list \ "$@" "${TOOLCHAIN_PKGS[@]}" | $sudo tee \ "$ROOT/etc/portage/cross-${cross_chost}-depends") From 95c5d9483792717afb8bfd4bc3ad6856749c3e71 Mon Sep 17 00:00:00 2001 From: Jeremi Piotrowski Date: Wed, 13 Jul 2022 15:43:15 +0200 Subject: [PATCH 2/6] setup_board: fix building binpkgs for toolchain dependencies install_cross_libs installs TOOLCHAIN_PKGS deps into /usr/$BOARD_CHOST, so that TOOLCHAIN_PKGS binpkgs can be built. We also need binpkgs for the TOOLCHAIN_PKGS deps so that we can install them into /build/$BOARD later together with TOOLCHAIN_PKGS. This is where the flow is currently broken. Due to a change in semantics, --emptyroot tries to rebuild host packages as well, and dropping it leaves --onlydeps which results in no binpkgs being built because they are already installed. We can solve resolve this by reusing the dependency list generated by install_cross_libs, and explicitly building those binpkgs. It is worth remarking that this flow of building the toolchain binpkgs through setup_board is not in use in Flatcar, because we normally build toolchains with catalyst. We are interested in reviving it because we want to build everything with SLSA provenance information. --- setup_board | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setup_board b/setup_board index bddb4dfcc6..0854c44902 100755 --- a/setup_board +++ b/setup_board @@ -319,9 +319,9 @@ if [[ ${FLAGS_regen_configs} -eq ${FLAGS_FALSE} ]]; then install_cross_libs "${BOARD_CHOST}" ${EMERGE_FLAGS} --buildpkg=n info "Building toolchain dependencies" - "${EMERGE_WRAPPER}" --buildpkg --buildpkgonly --onlydeps -e \ + "${EMERGE_WRAPPER}" --buildpkg --buildpkgonly \ --root="/usr/${BOARD_CHOST}" --sysroot="/usr/${BOARD_CHOST}" \ - ${EMERGE_TOOLCHAIN_FLAGS} "${TOOLCHAIN_PKGS[@]}" + ${EMERGE_TOOLCHAIN_FLAGS} $(< "/usr/${BOARD_CHOST}/etc/portage/cross-${BOARD_CHOST}-depends") info "Building toolchain" "${EMERGE_WRAPPER}" --buildpkg --buildpkgonly \ --root="/usr/${BOARD_CHOST}" --sysroot="/usr/${BOARD_CHOST}" \ From 0eb44ea2809fb027a95d0e6321c32693d5a72920 Mon Sep 17 00:00:00 2001 From: Jeremi Piotrowski Date: Wed, 13 Jul 2022 15:43:15 +0200 Subject: [PATCH 3/6] build_toolchains: add provenance metadata files to root overlay Catalyst runs builds with copies of the portage/coreos overlays in a chroot, which prevents us from accessing the git metadata necessary to create provenance information. Copy some files over into the root_overlay used by the toolchains catalyst build so that provenance can be correctly captured. --- build_toolchains | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/build_toolchains b/build_toolchains index 4168c01a10..ebef08c8cf 100755 --- a/build_toolchains +++ b/build_toolchains @@ -26,6 +26,24 @@ stage4/root_overlay: ${ROOT_OVERLAY} EOF catalyst_stage_default } +create_provenance_overlay() { + local root_overlay="$1" + while read f; do + d="${f%/*}" + mkdir -p "${root_overlay}${d}/" + cp "${f}" "${root_overlay}${d}/" + done < <(find /mnt/host/source/src/scripts -name HEAD) + local scripts_git=/mnt/host/source/src/scripts/.git + # `git rev-parse` fails due to the safe.directory setting in SDK container. + # Open-code the ref lookup + read scripts_hash <"${scripts_git}/HEAD" + if [[ "${scripts_hash}" == "ref:"* ]]; then + read scripts_hash<"${scripts_git}/${scripts_hash#ref: }" + echo "${scripts_hash}" >"${root_overlay}${scripts_git}/HEAD" + fi + mkdir -p "${root_overlay}/mnt/host/source/.repo/manifests" + cp "${REPO_MANIFESTS_DIR}/version.txt" "${root_overlay}/mnt/host/source/.repo/manifests" +} catalyst_init "$@" check_gsutil_opts @@ -35,6 +53,7 @@ ROOT_OVERLAY="${TEMPDIR}/stage4-${ARCH}-$FLAGS_version-overlay" # toolchain_util.sh is required by catalyst_toolchains.sh mkdir -p "${ROOT_OVERLAY}/tmp" cp "${BUILD_LIBRARY_DIR}/toolchain_util.sh" "${ROOT_OVERLAY}/tmp" +create_provenance_overlay "${ROOT_OVERLAY}" catalyst_build From 7c87bb611f458a86a4240e584063016b1342cec5 Mon Sep 17 00:00:00 2001 From: Jeremi Piotrowski Date: Wed, 13 Jul 2022 15:43:15 +0200 Subject: [PATCH 4/6] enable GENERATE_SLSA_PROVENANCE for board ROOT This needs to be done in setup_board for ROOT=/build/$BOARD, but also in toolchain_util because basic toolchains packages are built through catalyst. --- build_library/toolchain_util.sh | 2 ++ setup_board | 3 +++ 2 files changed, 5 insertions(+) diff --git a/build_library/toolchain_util.sh b/build_library/toolchain_util.sh index f9328b4345..749b63267c 100644 --- a/build_library/toolchain_util.sh +++ b/build_library/toolchain_util.sh @@ -289,6 +289,8 @@ $(portageq envvar -v CHOST CBUILD ROOT \ PORTDIR PORTDIR_OVERLAY DISTDIR PKGDIR) HOSTCC=\${CBUILD}-gcc PKG_CONFIG_PATH="\${SYSROOT}/usr/lib/pkgconfig/" +# Enable provenance reporting by default. Produced files are in /usr/share/SLSA +GENERATE_SLSA_PROVENANCE="true" EOF } diff --git a/setup_board b/setup_board index 0854c44902..c6fc42a652 100755 --- a/setup_board +++ b/setup_board @@ -269,6 +269,9 @@ PORTAGE_BINHOST="${BOARD_BINHOST}" # You can use --select to override this. EMERGE_DEFAULT_OPTS="--oneshot" +# Enable provenance reporting by default. Produced files are in /usr/share/SLSA +GENERATE_SLSA_PROVENANCE="true" + # Allow the user to override or define additional settings. source "${BOARD_ETC}/portage/make.conf.user" EOF From e20cf95bcb1efbff7910c8c0f744322ce1e02589 Mon Sep 17 00:00:00 2001 From: Jeremi Piotrowski Date: Wed, 13 Jul 2022 15:43:15 +0200 Subject: [PATCH 5/6] prod_image_util: unpack SLSA report along with gcc when building image Prod images need libstdc++.so and other libraries produced by sys-devel/gcc build, but because we don't want all of gcc in the image, the binpkg is manually unpacked instead of installed with emerge. Make sure to preserve SLSA metadata when unpacking as well. --- build_library/prod_image_util.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/build_library/prod_image_util.sh b/build_library/prod_image_util.sh index cf928cbb7a..9cd88f5f4d 100755 --- a/build_library/prod_image_util.sh +++ b/build_library/prod_image_util.sh @@ -46,7 +46,8 @@ extract_prod_gcc() { qtbz2 -O -t "${pkg}" | \ sudo tar -C "${root_fs_dir}" -xj \ --transform 's#/usr/lib/.*/#/usr/lib64/#' \ - --wildcards './usr/lib/gcc/*.so*' + --wildcards './usr/lib/gcc/*.so*' \ + --wildcards './usr/share/SLSA' package_provided "${gcc}" } From 3f39f483898a974fac815e1ce6dddddae3dd5492 Mon Sep 17 00:00:00 2001 From: Jeremi Piotrowski Date: Tue, 19 Jul 2022 16:22:44 +0000 Subject: [PATCH 6/6] build_library: install initramfs/torcx SLSA reports into rootfs Some packages are currently missing from the /usr/share/SLSA directory compared to flatcar_production_image_packages.txt. For torcx packages, extract the reports from the torcx bundle when adding it to the rootfs. For initramfs packages, as a substitute we enumerate build dependencies of coreos-kernel (image_packages_implicit()). At this time these are bootengine and intel-microcode. --- build_library/build_image_util.sh | 49 +++++++++++++++++++++++++++---- build_library/prod_image_util.sh | 1 + 2 files changed, 45 insertions(+), 5 deletions(-) diff --git a/build_library/build_image_util.sh b/build_library/build_image_util.sh index 6cecf63ea9..6d2ec7d200 100755 --- a/build_library/build_image_util.sh +++ b/build_library/build_image_util.sh @@ -265,12 +265,15 @@ query_available_package() { tail -n 1 } -# Generate a list of packages installed in an image. -# Usage: image_packages /image/root -image_packages() { - local profile="${BUILD_DIR}/configroot/etc/portage/profile" +# List packages installed directly in portages package database +image_packages_portage() { ROOT="$1" PORTAGE_CONFIGROOT="${BUILD_DIR}"/configroot \ equery --no-color list --format '$cpv::$repo' '*' +} +# List packages implicitly contained in rootfs, such as in torcx packages or +# initramfs. +image_packages_implicit() { + local profile="${BUILD_DIR}/configroot/etc/portage/profile" # We also want to list packages that only exist in the initramfs. # Approximate this by listing build dependencies of coreos-kernel that @@ -304,6 +307,13 @@ image_packages() { while read pkg ; do query_available_package "${pkg}" ; done } +# Generate a list of packages installed in an image. +# Usage: image_packages /image/root +image_packages() { + image_packages_portage "$1" + image_packages_implicit "$1" +} + # Generate a list of installed packages in the format: # sys-apps/systemd-212-r8::coreos write_packages() { @@ -511,6 +521,35 @@ EOF sudo gzip -9 "${root_fs_dir}"/usr/share/licenses/common/* } +# Add /usr/share/SLSA reports for packages indirectly contained within the rootfs +# If the package is available in BOARD_ROOT accesses it from there, otherwise +# needs to download binpkg. +# Reports for torcx packages are also included when adding the torcx package to +# rootfs. +insert_extra_slsa() { + info "Inserting additional SLSA file" + local rootfs="$1" + for atom in $(image_packages_implicit "$rootfs"); do + pkg="${atom%::*}" + pkg="${pkg/\//_}.json.xz" + if [ -f "${BOARD_ROOT}/usr/share/SLSA/${pkg}" ]; then + info "Found ${atom} in BOARD_ROOT" + sudo cp "${BOARD_ROOT}/usr/share/SLSA/${pkg}" "${rootfs}/usr/share/SLSA/" + continue + fi + # let's not die if SLSA information is missing + pkgversion=$( (get_binary_pkg "=${atom}" 2>/dev/null ) || true) + binpkg="$(portageq-${BOARD} pkgdir)/${pkgversion}.tbz2" + if [ -f "${binpkg}" ]; then + info "Found ${atom} at ${binpkg}" + qtbz2 -O -t "${binpkg}" | \ + sudo tar -C "${rootfs}" -xj --wildcards './usr/share/SLSA' + continue + fi + warn "Missing SLSA information for ${atom}" + done +} + # Add an entry to the image's package.provided package_provided() { local p profile="${BUILD_DIR}/configroot/etc/portage/profile" @@ -600,7 +639,7 @@ finish_image() { local casDigest="$(torcx_manifest::get_digest "${FLAGS_torcx_manifest}" "${pkg}" "${version}")" sudo cp "${FLAGS_torcx_root}/pkgs/${BOARD}/${pkg}/${casDigest}/${pkg}:${version}.torcx.tgz" \ "${root_fs_dir}${on_disk_path}" - + sudo tar xf "${root_fs_dir}${on_disk_path}" -C "${root_fs_dir}" --wildcards "./usr/share/SLSA" if [[ "${version}" == "${default_version}" ]]; then # Create the default symlink for this package sudo ln -fns "${on_disk_path##*/}" \ diff --git a/build_library/prod_image_util.sh b/build_library/prod_image_util.sh index 9cd88f5f4d..7923a96636 100755 --- a/build_library/prod_image_util.sh +++ b/build_library/prod_image_util.sh @@ -84,6 +84,7 @@ create_prod_image() { write_packages "${root_fs_dir}" "${BUILD_DIR}/${image_packages}" write_licenses "${root_fs_dir}" "${BUILD_DIR}/${image_licenses}" insert_licenses "${BUILD_DIR}/${image_licenses}" "${root_fs_dir}" + insert_extra_slsa "${root_fs_dir}" # Assert that if this is supposed to be an official build that the # official update keys have been used.