diff --git a/.github/workflows/reusable-build.yml b/.github/workflows/reusable-build.yml index 1cfe8b15..82948e7d 100644 --- a/.github/workflows/reusable-build.yml +++ b/.github/workflows/reusable-build.yml @@ -142,9 +142,10 @@ jobs: for TAG in "${COMMIT_TAGS[@]}"; do echo "${TAG}" done - + default_tag=${COMMIT_TAGS[0]} alias_tags=("${COMMIT_TAGS[@]}") else + default_tag=${BUILD_TAGS[0]} alias_tags=("${BUILD_TAGS[@]}") fi @@ -154,6 +155,7 @@ jobs: done echo "alias_tags=${alias_tags[*]}" >> $GITHUB_OUTPUT + echo "default_tag=$default_tag" >> $GITHUB_ENV # Build metadata - name: Image Metadata @@ -206,6 +208,32 @@ jobs: labels: ${{ steps.meta.outputs.labels }} oci: false + - name: Build Test Image + uses: redhat-actions/buildah-build@v2 + with: + containerfiles: | + ./Containerfile.test + image: akmods-test + tags: latest + build-args: | + BUILDER_IMAGE=${{ env.BUILDER_IMAGE }} + KERNEL_ORG=${{ github.repository_owner }} + KERNEL_FLAVOR=${{ matrix.kernel_flavor }} + FEDORA_MAJOR_VERSION=${{ matrix.fedora_version }} + INPUT_AKMODS=${{ env.IMAGE_NAME }} + INPUT_TAG=${{ env.default_tag }} + DUAL_SIGN=true + oci: false + + - name: Test Akmods Signature + id: test_akmods + shell: bash + run: | + if ! podman run akmods-test:latest; then + echo "Signatures Failed" + exit 1 + fi + # Workaround bug where capital letters in your GitHub username make it impossible to push to GHCR. # https://github.com/macbre/push-to-ghcr/issues/12 - name: Lowercase Registry diff --git a/Containerfile.common b/Containerfile.common index a5d7d6b1..3f6e7e5a 100644 --- a/Containerfile.common +++ b/Containerfile.common @@ -17,7 +17,7 @@ ARG KERNEL_FLAVOR="${KERNEL_FLAVOR:-main}" ARG RPMFUSION_MIRROR="" ARG DUAL_SIGN="true" -COPY build*.sh dual-sign.sh /tmp/ +COPY build*.sh dual-sign*.sh /tmp/ COPY certs /tmp/certs # cached kernel rpms diff --git a/Containerfile.extra b/Containerfile.extra index 0d317880..463a0183 100644 --- a/Containerfile.extra +++ b/Containerfile.extra @@ -17,7 +17,7 @@ ARG KERNEL_FLAVOR="${KERNEL_FLAVOR:-main}" ARG RPMFUSION_MIRROR="" ARG DUAL_SIGN="true" -COPY build*.sh dual-sign.sh /tmp/ +COPY build*.sh dual-sign*.sh /tmp/ COPY certs /tmp/certs # cached kernel rpms diff --git a/Containerfile.nvidia b/Containerfile.nvidia index 42b92038..16fbe82b 100644 --- a/Containerfile.nvidia +++ b/Containerfile.nvidia @@ -17,7 +17,7 @@ ARG KERNEL_FLAVOR="${KERNEL_FLAVOR:-main}" ARG RPMFUSION_MIRROR="" ARG DUAL_SIGN="true" -COPY build*.sh dual-sign.sh /tmp/ +COPY build*.sh dual-sign*.sh /tmp/ COPY certs /tmp/certs # cached kernel rpms diff --git a/Containerfile.test b/Containerfile.test new file mode 100644 index 00000000..39bccb23 --- /dev/null +++ b/Containerfile.test @@ -0,0 +1,40 @@ +### +### Containerfile.test - used to test akmods +### + +ARG FEDORA_MAJOR_VERSION="${FEDORA_MAJOR_VERSION:-40}" +ARG KERNEL_FLAVOR="${KERNEL_FLAVOR:-main}" +ARG KERNEL_IMAGE="${KERNEL_IMAGE:-${KERNEL_FLAVOR}-kernel}" +ARG KERNEL_ORG="${KERNEL_ORG:-ublue-os}" +ARG KERNEL_BASE="ghcr.io/${KERNEL_ORG}/${KERNEL_IMAGE}:${FEDORA_MAJOR_VERSION}" +ARG BUILDER_IMAGE="${BUILDER_IMAGE:-quay.io/fedora/fedora}" +ARG BUILDER_BASE="${BUILDER_IMAGE}:${FEDORA_MAJOR_VERSION}" +ARG INPUT_AKMODS="${INPUT_AKMODS:-akmods}" +ARG INPUT_TAG="${INPUT_TAG:-${KERNEL_FLAVOR}-${FEDORA_MAJOR_VERSION}}" +ARG INPUT_BASE="${INPUT_AKMODS}:${INPUT_TAG}" +FROM ${KERNEL_BASE} AS kernel_cache +FROM ${INPUT_BASE} AS akmods_cache +FROM ${BUILDER_BASE} AS tester + +ARG FEDORA_MAJOR_VERSION="${FEDORA_MAJOR_VERSION:-40}" +ARG KERNEL_FLAVOR="${KERNEL_FLAVOR:-main}" +ARG RPMFUSION_MIRROR="" +ARG DUAL_SIGN="true" + +COPY test-prep.sh dual-sign-check.sh /tmp/ +COPY check-signatures.sh / +COPY certs /tmp/certs + +# cached kernel rpms +COPY --from=kernel_cache /tmp/rpms /tmp/kernel_cache +COPY --from=akmods_cache /rpms /tmp/akmods-rpms + +RUN --mount=type=cache,dst=/var/cache/dnf \ + if grep -qv "surface" <<< "${KERNEL_FLAVOR}"; then \ + export KERNEL_NAME="kernel" \ + ; else \ + export KERNEL_NAME="kernel-surface" \ + ; fi && \ + /tmp/test-prep.sh + +CMD ["/check-signatures.sh"] diff --git a/Containerfile.zfs b/Containerfile.zfs index 1784462e..52de7c55 100644 --- a/Containerfile.zfs +++ b/Containerfile.zfs @@ -18,7 +18,7 @@ ARG DUAL_SIGN="true" ARG RPMFUSION_MIRROR="" ARG ZFS_MINOR_VERSION="${ZFS_MINOR_VERSION:-2.2}" -COPY build*.sh dual-sign-zfs.sh /tmp/ +COPY build*.sh dual-sign*.sh /tmp/ COPY certs /tmp/certs # cached kernel rpms diff --git a/check-signatures.sh b/check-signatures.sh new file mode 100755 index 00000000..d873e928 --- /dev/null +++ b/check-signatures.sh @@ -0,0 +1,23 @@ +#!/usr/bin/bash + +source /tmp/info.sh + +KERNEL="$(rpm -q "${KERNEL_NAME}" --queryformat '%{VERSION}-%{RELEASE}.%{ARCH}')" +PUBLIC_CHAIN="/tmp/certs/public_key_chain.pem" + +for module in /usr/lib/modules/"${KERNEL}"/extra/*/*.ko*; +do + module_basename=${module:0:-3} + module_suffix=${module: -3} + if [[ "$module_suffix" == ".xz" ]]; then + xz --decompress "$module" + /tmp/dual-sign-check.sh "${KERNEL}" "${module_basename}" "${PUBLIC_CHAIN}" + xz -f "${module_basename}" + elif [[ "$module_suffix" == ".gz" ]]; then + gzip -d "$module" + /tmp/dual-sign-check.sh "${KERNEL}" "${module_basename}" "${PUBLIC_CHAIN}" + gzip -9f "${module_basename}" + else + /tmp/dual-sign-check.sh "${KERNEL}" "${module}" "${PUBLIC_CHAIN}" + fi +done diff --git a/dual-sign-check.sh b/dual-sign-check.sh new file mode 100755 index 00000000..109aeb16 --- /dev/null +++ b/dual-sign-check.sh @@ -0,0 +1,24 @@ +#!/usr/bin/bash + +KERNEL="$1" +module="$2" +PUBLIC_CERT="$3" + +kmod_sig="/tmp/kmod.sig" +kmod_p7s="/tmp/kmod.p7s" +kmod_data="/tmp/kmod.data" +/usr/src/kernels/"${KERNEL}"/scripts/extract-module-sig.pl -s "${module}" > ${kmod_sig} +openssl pkcs7 -inform der -in ${kmod_sig} -out ${kmod_p7s} +/usr/src/kernels/"${KERNEL}"/scripts/extract-module-sig.pl -0 "${module}" > ${kmod_data} +if openssl cms -verify -binary -inform PEM \ + -in ${kmod_p7s} \ + -content ${kmod_data} \ + -certfile "${PUBLIC_CERT}" \ + -out "/dev/null" \ + -nointern -noverify + then + echo "Signature Verified for ${module}" +else + echo "Signature Failed for ${module}" + exit 1 +fi diff --git a/dual-sign-zfs.sh b/dual-sign-zfs.sh index c7a93a44..83990905 100755 --- a/dual-sign-zfs.sh +++ b/dual-sign-zfs.sh @@ -18,15 +18,18 @@ if [[ "${DUAL_SIGN}" == "true" ]]; then xz --decompress "$module" openssl cms -sign -signer "${SIGNING_KEY_1}" -signer "${SIGNING_KEY_2}" -binary -in "$module_basename" -outform DER -out "${module_basename}.cms" -nocerts -noattr -nosmimecap /usr/src/kernels/"${KERNEL}"/scripts/sign-file -s "${module_basename}.cms" sha256 "${PUBLIC_CHAIN}" "${module_basename}" + /tmp/dual-sign-check.sh "${KERNEL}" "${module_basename}" "${PUBLIC_CHAIN}" xz -f "${module_basename}" elif [[ "$module_suffix" == ".gz" ]]; then gzip -d "$module" openssl cms -sign -signer "${SIGNING_KEY_1}" -signer "${SIGNING_KEY_2}" -binary -in "$module_basename" -outform DER -out "${module_basename}.cms" -nocerts -noattr -nosmimecap /usr/src/kernels/"${KERNEL}"/scripts/sign-file -s "${module_basename}.cms" sha256 "${PUBLIC_CHAIN}" "${module_basename}" + /tmp/dual-sign-check.sh "${KERNEL}" "${module_basename}" "${PUBLIC_CHAIN}" gzip -9f "${module_basename}" else openssl cms -sign -signer "${SIGNING_KEY_1}" -signer "${SIGNING_KEY_2}" -binary -in "$module" -outform DER -out "${module}.cms" -nocerts -noattr -nosmimecap /usr/src/kernels/"${KERNEL}"/scripts/sign-file -s "${module}.cms" sha256 "${PUBLIC_CHAIN}" "${module}" + /tmp/dual-sign-check.sh "${KERNEL}" "${module}" "${PUBLIC_CHAIN}" fi done rpmrebuild --batch /var/cache/rpms/kmods/zfs/kmod-zfs-*.rpm diff --git a/dual-sign.sh b/dual-sign.sh index d113efc9..6b978167 100755 --- a/dual-sign.sh +++ b/dual-sign.sh @@ -16,15 +16,18 @@ if [[ "${DUAL_SIGN}" == "true" ]]; then xz --decompress "$module" openssl cms -sign -signer "${SIGNING_KEY_1}" -signer "${SIGNING_KEY_2}" -binary -in "$module_basename" -outform DER -out "${module_basename}.cms" -nocerts -noattr -nosmimecap /usr/src/kernels/"${KERNEL}"/scripts/sign-file -s "${module_basename}.cms" sha256 "${PUBLIC_CHAIN}" "${module_basename}" + /tmp/dual-sign-check.sh "${KERNEL}" "${module_basename}" "${PUBLIC_CHAIN}" xz -f "${module_basename}" elif [[ "$module_suffix" == ".gz" ]]; then gzip -d "$module" openssl cms -sign -signer "${SIGNING_KEY_1}" -signer "${SIGNING_KEY_2}" -binary -in "$module_basename" -outform DER -out "${module_basename}.cms" -nocerts -noattr -nosmimecap /usr/src/kernels/"${KERNEL}"/scripts/sign-file -s "${module_basename}.cms" sha256 "${PUBLIC_CHAIN}" "${module_basename}" + /tmp/dual-sign-check.sh "${KERNEL}" "${module_basename}" "${PUBLIC_CHAIN}" gzip -9f "${module_basename}" else openssl cms -sign -signer "${SIGNING_KEY_1}" -signer "${SIGNING_KEY_2}" -binary -in "$module" -outform DER -out "${module}.cms" -nocerts -noattr -nosmimecap /usr/src/kernels/"${KERNEL}"/scripts/sign-file -s "${module}.cms" sha256 "${PUBLIC_CHAIN}" "${module}" + /tmp/dual-sign-check.sh "${KERNEL}" "${module}" "${PUBLIC_CHAIN}" fi done find /var/cache/akmods -type f -name \kmod-*.rpm diff --git a/test-prep.sh b/test-prep.sh new file mode 100755 index 00000000..5ba8c09a --- /dev/null +++ b/test-prep.sh @@ -0,0 +1,155 @@ +#!/usr/bin/bash + +set -oeux pipefail + +### PREPARE REPOS +# ARCH="$(rpm -E '%_arch')" +RELEASE="$(rpm -E '%fedora')" + +sed -i 's@enabled=1@enabled=0@g' /etc/yum.repos.d/fedora-cisco-openh264.repo + +# enable RPMs with alternatives to create them in this image build +mkdir -p /var/lib/alternatives + +if [[ -f $(find /tmp/akmods-rpms/ublue-os/ublue-os-*.rpm 2> /dev/null) ]]; then + dnf install -y /tmp/akmods-rpms/ublue-os/ublue-os-*.rpm +fi + + +# install kernel_cache provided kernel +echo "Installing ${KERNEL_FLAVOR} kernel-cache RPMs..." +# fedora image has no kernel so this needs nothing fancy, just install +dnf install -y /tmp/kernel_cache/*.rpm + +if [[ "${KERNEL_FLAVOR}" == "surface" ]]; then + KERNEL_VERSION=$(rpm -q kernel-surface|cut -d '-' -f2-) +else + KERNEL_VERSION=$(rpm -q kernel|cut -d '-' -f2-) +fi + +# enable more repos +RPMFUSION_MIRROR_RPMS="https://mirrors.rpmfusion.org" +if [ -n "${RPMFUSION_MIRROR}" ]; then + RPMFUSION_MIRROR_RPMS=${RPMFUSION_MIRROR} +fi + +if [[ "${RELEASE}" -ge 41 ]]; then + COPR_RELEASE="rawhide" +else + COPR_RELEASE="${RELEASE}" +fi + +curl -Lo /etc/yum.repos.d/_copr_ublue-os_staging.repo \ + "https://copr.fedorainfracloud.org/coprs/ublue-os/staging/repo/fedora-${COPR_RELEASE}/ublue-os-staging-fedora-${COPR_RELEASE}.repo" + +curl -Lo /etc/yum.repos.d/_copr_kylegospo_oversteer.repo \ + "https://copr.fedorainfracloud.org/coprs/kylegospo/oversteer/repo/fedora-${COPR_RELEASE}/kylegospo-oversteer-fedora-${COPR_RELEASE}.repo" + +curl -Lo /etc/yum.repos.d/_copr_ublue-os-akmods.repo \ + "https://copr.fedorainfracloud.org/coprs/ublue-os/akmods/repo/fedora-${COPR_RELEASE}/ublue-os-akmods-fedora-${COPR_RELEASE}.repo" + +curl -Lo /etc/yum.repos.d/negativo17-fedora-multimedia.repo \ + "https://negativo17.org/repos/fedora-multimedia.repo" + +if [[ -f $(find /tmp/akmods-rpms/kmods/kmod-vhba-*.rpm) ]]; then +curl -LsSf -o /etc/yum.repos.d/_copr_rok-cdemu.repo \ + "https://copr.fedorainfracloud.org/coprs/rok/cdemu/repo/fedora-${COPR_RELEASE}/rok-cdemu-fedora-${COPR_RELEASE}.repo" +fi + +if [[ -f $(find /tmp/akmods-rpms/kmods/kmod-facetimehd-*.rpm) ]]; then +curl -LsSf -o /etc/yum.repos.d/_copr_mulderje-facetimehd-kmod.repo \ + "https://copr.fedorainfracloud.org/coprs/mulderje/facetimehd-kmod/repo/fedora-${COPR_RELEASE}/mulderje-facetimehd-kmod-fedora-${COPR_RELEASE}.repo" +fi + +if [[ -f $(find /tmp/akmods-rpms/kmods/kmod-kvmfr-*.rpm) ]]; then +curl -LsSf -o /etc/yum.repos.d/_copr_hikariknight-looking-glass-kvmfr.repo \ + "https://copr.fedorainfracloud.org/coprs/hikariknight/looking-glass-kvmfr/repo/fedora-${COPR_RELEASE}/hikariknight-looking-glass-kvmfr-fedora-${COPR_RELEASE}.repo" +fi + +if [[ -f $(find /tmp/akmods-rpms/kmods/kmod-nvidia-*.rpm) ]]; then + curl -Lo /etc/yum.repos.d/negativo17-fedora-nvidia.repo \ + "https://negativo17.org/repos/fedora-nvidia.repo" + curl -Lo /etc/yum.repos.d/nvidia-container-toolkit.repo \ + "https://nvidia.github.io/libnvidia-container/stable/rpm/nvidia-container-toolkit.repo" + curl -Lo /etc/yum.repos.d/nvidia-container.pp \ + "https://raw.githubusercontent.com/NVIDIA/dgx-selinux/master/bin/RHEL9/nvidia-container.pp" + curl -Lo /etc/yum.repos.d/eyecantcu-supergfxctl.repo \ + "https://copr.fedorainfracloud.org/coprs/eyecantcu/supergfxctl/repo/fedora-${COPR_RELEASE}/eyecantcu-supergfxctl-fedora-${COPR_RELEASE}.repo" + curl -Lo /tmp/nvidia-install.sh \ + "https://raw.githubusercontent.com/ublue-os/hwe/main/nvidia-install.sh" + chmod +x /tmp/nvidia-install.sh + sed -i "s@gpgcheck=0@gpgcheck=1@" /etc/yum.repos.d/nvidia-container-toolkit.repo +fi + +dnf install -y \ + "${RPMFUSION_MIRROR_RPMS}"/free/fedora/rpmfusion-free-release-"${RELEASE}".noarch.rpm \ + "${RPMFUSION_MIRROR_RPMS}"/nonfree/fedora/rpmfusion-nonfree-release-"${RELEASE}".noarch.rpm \ + fedora-repos-archive \ + openssl + + +# after F41 launches, bump to 42 +if [[ "${FEDORA_MAJOR_VERSION}" -ge 41 ]]; then + # pre-release rpmfusion is in a different location + sed -i "s%free/fedora/releases%free/fedora/development%" /etc/yum.repos.d/rpmfusion-*.repo + # pre-release rpmfusion needs to enable testing + sed -i '0,/enabled=0/{s/enabled=0/enabled=1/}' /etc/yum.repos.d/rpmfusion-*-updates-testing.repo +fi + +if [ -n "${RPMFUSION_MIRROR}" ]; then + # force use of single rpmfusion mirror + echo "Using single rpmfusion mirror: ${RPMFUSION_MIRROR}" + sed -i.bak "s%^metalink=%#metalink=%" /etc/yum.repos.d/rpmfusion-*.repo + sed -i "s%^#baseurl=http://download1.rpmfusion.org%baseurl=${RPMFUSION_MIRROR}%" /etc/yum.repos.d/rpmfusion-*.repo +fi + +if [[ ! -s "/tmp/certs/private_key.priv" ]]; then + echo "WARNING: Using test signing key. Run './generate-akmods-key' for production builds." + cp /tmp/certs/public_key.der{.test,} +fi + +openssl x509 -in /tmp/certs/public_key.der -out /tmp/certs/public_key.crt +cat /tmp/certs/public_key.crt > /tmp/certs/public_key_chain.pem +rm -f /tmp/certs/private_key.priv + +if [[ "${DUAL_SIGN}" == "true" ]]; then + if [[ ! -s "/tmp/certs/private_key_2.priv" ]]; then + echo "WARNING: Using test signing key. Run './generate-akmods-key' for production builds." + cp /tmp/certs/public_key_2.der{.test,} + fi + openssl x509 -in /tmp/certs/public_key_2.der -out /tmp/certs/public_key_2.crt + rm -f /tmp/certs/public_key_chain.pem + cat /tmp/certs/public_key.crt <(echo) /tmp/certs/public_key_2.crt >> /tmp/certs/public_key_chain.pem +fi + +rm -f /tmp/certs/private_key_2.priv + +if [[ -f $(find /tmp/akmods-rpms/kmods/kmod-nvidia-*.rpm 2> /dev/null) ]]; then + sed -i '0,/enabled=0/{s/enabled=0/enabled=1/}' /etc/yum.repos.d/eyecantcu-supergfxctl.repo + sed -i '0,/enabled=0/{s/enabled=0/enabled=1/}' /etc/yum.repos.d/negativo17-fedora-nvidia.repo + sed -i '0,/enabled=0/{s/enabled=0/enabled=1/}' /etc/yum.repos.d/nvidia-container-toolkit.repo + source /tmp/akmods-rpms/kmods/nvidia-vars + dnf install -y \ + libnvidia-fbc \ + libnvidia-ml.i686 \ + libva-nvidia-driver \ + mesa-vulkan-drivers.i686 \ + nvidia-driver \ + nvidia-driver-cuda \ + nvidia-driver-cuda-libs.i686 \ + nvidia-driver-libs.i686 \ + nvidia-modprobe \ + nvidia-persistenced \ + nvidia-settings \ + nvidia-container-toolkit \ + /tmp/akmods-rpms/kmods/kmod-nvidia-"${KERNEL_VERSION}"-"${NVIDIA_AKMOD_VERSION}".fc"${RELEASE}".rpm +elif [[ -f $(find /tmp/akmods-rpms/kmods/zfs/kmod-*.rpm 2> /dev/null) ]]; then + dnf install -y \ + pv \ + /tmp/akmods-rpms/kmods/zfs/*.rpm +else + dnf install -y \ + /tmp/akmods-rpms/kmods/*.rpm +fi + +printf "KERNEL_NAME=%s" "$KERNEL_NAME" >> /tmp/info.sh