diff --git a/build_library/build_image_util.sh b/build_library/build_image_util.sh index 242e8b9432..da266d42f6 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() { @@ -517,6 +527,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" @@ -606,7 +645,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 9ffa81108b..77502402bb 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}" } @@ -85,6 +86,7 @@ create_prod_image() { write_sbom "${root_fs_dir}" "${BUILD_DIR}/${image_sbom}" 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. diff --git a/build_library/toolchain_util.sh b/build_library/toolchain_util.sh index 7315ef6780..749b63267c 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 @@ -288,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 } @@ -392,7 +395,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") 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 diff --git a/setup_board b/setup_board index bddb4dfcc6..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 @@ -319,9 +322,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}" \