Skip to content

Commit 7c3a5d8

Browse files
authored
feat: verify kmod signatures for dual-sign (#218)
1 parent 20fce9f commit 7c3a5d8

11 files changed

+281
-5
lines changed

.github/workflows/reusable-build.yml

+29-1
Original file line numberDiff line numberDiff line change
@@ -142,9 +142,10 @@ jobs:
142142
for TAG in "${COMMIT_TAGS[@]}"; do
143143
echo "${TAG}"
144144
done
145-
145+
default_tag=${COMMIT_TAGS[0]}
146146
alias_tags=("${COMMIT_TAGS[@]}")
147147
else
148+
default_tag=${BUILD_TAGS[0]}
148149
alias_tags=("${BUILD_TAGS[@]}")
149150
fi
150151
@@ -154,6 +155,7 @@ jobs:
154155
done
155156
156157
echo "alias_tags=${alias_tags[*]}" >> $GITHUB_OUTPUT
158+
echo "default_tag=$default_tag" >> $GITHUB_ENV
157159
158160
# Build metadata
159161
- name: Image Metadata
@@ -206,6 +208,32 @@ jobs:
206208
labels: ${{ steps.meta.outputs.labels }}
207209
oci: false
208210

211+
- name: Build Test Image
212+
uses: redhat-actions/buildah-build@v2
213+
with:
214+
containerfiles: |
215+
./Containerfile.test
216+
image: akmods-test
217+
tags: latest
218+
build-args: |
219+
BUILDER_IMAGE=${{ env.BUILDER_IMAGE }}
220+
KERNEL_ORG=${{ github.repository_owner }}
221+
KERNEL_FLAVOR=${{ matrix.kernel_flavor }}
222+
FEDORA_MAJOR_VERSION=${{ matrix.fedora_version }}
223+
INPUT_AKMODS=${{ env.IMAGE_NAME }}
224+
INPUT_TAG=${{ env.default_tag }}
225+
DUAL_SIGN=true
226+
oci: false
227+
228+
- name: Test Akmods Signature
229+
id: test_akmods
230+
shell: bash
231+
run: |
232+
if ! podman run akmods-test:latest; then
233+
echo "Signatures Failed"
234+
exit 1
235+
fi
236+
209237
# Workaround bug where capital letters in your GitHub username make it impossible to push to GHCR.
210238
# https://github.com/macbre/push-to-ghcr/issues/12
211239
- name: Lowercase Registry

Containerfile.common

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ ARG KERNEL_FLAVOR="${KERNEL_FLAVOR:-main}"
1717
ARG RPMFUSION_MIRROR=""
1818
ARG DUAL_SIGN="true"
1919

20-
COPY build*.sh dual-sign.sh /tmp/
20+
COPY build*.sh dual-sign*.sh /tmp/
2121
COPY certs /tmp/certs
2222

2323
# cached kernel rpms

Containerfile.extra

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ ARG KERNEL_FLAVOR="${KERNEL_FLAVOR:-main}"
1717
ARG RPMFUSION_MIRROR=""
1818
ARG DUAL_SIGN="true"
1919

20-
COPY build*.sh dual-sign.sh /tmp/
20+
COPY build*.sh dual-sign*.sh /tmp/
2121
COPY certs /tmp/certs
2222

2323
# cached kernel rpms

Containerfile.nvidia

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ ARG KERNEL_FLAVOR="${KERNEL_FLAVOR:-main}"
1717
ARG RPMFUSION_MIRROR=""
1818
ARG DUAL_SIGN="true"
1919

20-
COPY build*.sh dual-sign.sh /tmp/
20+
COPY build*.sh dual-sign*.sh /tmp/
2121
COPY certs /tmp/certs
2222

2323
# cached kernel rpms

Containerfile.test

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
###
2+
### Containerfile.test - used to test akmods
3+
###
4+
5+
ARG FEDORA_MAJOR_VERSION="${FEDORA_MAJOR_VERSION:-40}"
6+
ARG KERNEL_FLAVOR="${KERNEL_FLAVOR:-main}"
7+
ARG KERNEL_IMAGE="${KERNEL_IMAGE:-${KERNEL_FLAVOR}-kernel}"
8+
ARG KERNEL_ORG="${KERNEL_ORG:-ublue-os}"
9+
ARG KERNEL_BASE="ghcr.io/${KERNEL_ORG}/${KERNEL_IMAGE}:${FEDORA_MAJOR_VERSION}"
10+
ARG BUILDER_IMAGE="${BUILDER_IMAGE:-quay.io/fedora/fedora}"
11+
ARG BUILDER_BASE="${BUILDER_IMAGE}:${FEDORA_MAJOR_VERSION}"
12+
ARG INPUT_AKMODS="${INPUT_AKMODS:-akmods}"
13+
ARG INPUT_TAG="${INPUT_TAG:-${KERNEL_FLAVOR}-${FEDORA_MAJOR_VERSION}}"
14+
ARG INPUT_BASE="${INPUT_AKMODS}:${INPUT_TAG}"
15+
FROM ${KERNEL_BASE} AS kernel_cache
16+
FROM ${INPUT_BASE} AS akmods_cache
17+
FROM ${BUILDER_BASE} AS tester
18+
19+
ARG FEDORA_MAJOR_VERSION="${FEDORA_MAJOR_VERSION:-40}"
20+
ARG KERNEL_FLAVOR="${KERNEL_FLAVOR:-main}"
21+
ARG RPMFUSION_MIRROR=""
22+
ARG DUAL_SIGN="true"
23+
24+
COPY test-prep.sh dual-sign-check.sh /tmp/
25+
COPY check-signatures.sh /
26+
COPY certs /tmp/certs
27+
28+
# cached kernel rpms
29+
COPY --from=kernel_cache /tmp/rpms /tmp/kernel_cache
30+
COPY --from=akmods_cache /rpms /tmp/akmods-rpms
31+
32+
RUN --mount=type=cache,dst=/var/cache/dnf \
33+
if grep -qv "surface" <<< "${KERNEL_FLAVOR}"; then \
34+
export KERNEL_NAME="kernel" \
35+
; else \
36+
export KERNEL_NAME="kernel-surface" \
37+
; fi && \
38+
/tmp/test-prep.sh
39+
40+
CMD ["/check-signatures.sh"]

Containerfile.zfs

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ ARG DUAL_SIGN="true"
1818
ARG RPMFUSION_MIRROR=""
1919
ARG ZFS_MINOR_VERSION="${ZFS_MINOR_VERSION:-2.2}"
2020

21-
COPY build*.sh dual-sign-zfs.sh /tmp/
21+
COPY build*.sh dual-sign*.sh /tmp/
2222
COPY certs /tmp/certs
2323

2424
# cached kernel rpms

check-signatures.sh

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#!/usr/bin/bash
2+
3+
source /tmp/info.sh
4+
5+
KERNEL="$(rpm -q "${KERNEL_NAME}" --queryformat '%{VERSION}-%{RELEASE}.%{ARCH}')"
6+
PUBLIC_CHAIN="/tmp/certs/public_key_chain.pem"
7+
8+
for module in /usr/lib/modules/"${KERNEL}"/extra/*/*.ko*;
9+
do
10+
module_basename=${module:0:-3}
11+
module_suffix=${module: -3}
12+
if [[ "$module_suffix" == ".xz" ]]; then
13+
xz --decompress "$module"
14+
/tmp/dual-sign-check.sh "${KERNEL}" "${module_basename}" "${PUBLIC_CHAIN}"
15+
xz -f "${module_basename}"
16+
elif [[ "$module_suffix" == ".gz" ]]; then
17+
gzip -d "$module"
18+
/tmp/dual-sign-check.sh "${KERNEL}" "${module_basename}" "${PUBLIC_CHAIN}"
19+
gzip -9f "${module_basename}"
20+
else
21+
/tmp/dual-sign-check.sh "${KERNEL}" "${module}" "${PUBLIC_CHAIN}"
22+
fi
23+
done

dual-sign-check.sh

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#!/usr/bin/bash
2+
3+
KERNEL="$1"
4+
module="$2"
5+
PUBLIC_CERT="$3"
6+
7+
kmod_sig="/tmp/kmod.sig"
8+
kmod_p7s="/tmp/kmod.p7s"
9+
kmod_data="/tmp/kmod.data"
10+
/usr/src/kernels/"${KERNEL}"/scripts/extract-module-sig.pl -s "${module}" > ${kmod_sig}
11+
openssl pkcs7 -inform der -in ${kmod_sig} -out ${kmod_p7s}
12+
/usr/src/kernels/"${KERNEL}"/scripts/extract-module-sig.pl -0 "${module}" > ${kmod_data}
13+
if openssl cms -verify -binary -inform PEM \
14+
-in ${kmod_p7s} \
15+
-content ${kmod_data} \
16+
-certfile "${PUBLIC_CERT}" \
17+
-out "/dev/null" \
18+
-nointern -noverify
19+
then
20+
echo "Signature Verified for ${module}"
21+
else
22+
echo "Signature Failed for ${module}"
23+
exit 1
24+
fi

dual-sign-zfs.sh

+3
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,18 @@ if [[ "${DUAL_SIGN}" == "true" ]]; then
1818
xz --decompress "$module"
1919
openssl cms -sign -signer "${SIGNING_KEY_1}" -signer "${SIGNING_KEY_2}" -binary -in "$module_basename" -outform DER -out "${module_basename}.cms" -nocerts -noattr -nosmimecap
2020
/usr/src/kernels/"${KERNEL}"/scripts/sign-file -s "${module_basename}.cms" sha256 "${PUBLIC_CHAIN}" "${module_basename}"
21+
/tmp/dual-sign-check.sh "${KERNEL}" "${module_basename}" "${PUBLIC_CHAIN}"
2122
xz -f "${module_basename}"
2223
elif [[ "$module_suffix" == ".gz" ]]; then
2324
gzip -d "$module"
2425
openssl cms -sign -signer "${SIGNING_KEY_1}" -signer "${SIGNING_KEY_2}" -binary -in "$module_basename" -outform DER -out "${module_basename}.cms" -nocerts -noattr -nosmimecap
2526
/usr/src/kernels/"${KERNEL}"/scripts/sign-file -s "${module_basename}.cms" sha256 "${PUBLIC_CHAIN}" "${module_basename}"
27+
/tmp/dual-sign-check.sh "${KERNEL}" "${module_basename}" "${PUBLIC_CHAIN}"
2628
gzip -9f "${module_basename}"
2729
else
2830
openssl cms -sign -signer "${SIGNING_KEY_1}" -signer "${SIGNING_KEY_2}" -binary -in "$module" -outform DER -out "${module}.cms" -nocerts -noattr -nosmimecap
2931
/usr/src/kernels/"${KERNEL}"/scripts/sign-file -s "${module}.cms" sha256 "${PUBLIC_CHAIN}" "${module}"
32+
/tmp/dual-sign-check.sh "${KERNEL}" "${module}" "${PUBLIC_CHAIN}"
3033
fi
3134
done
3235
rpmrebuild --batch /var/cache/rpms/kmods/zfs/kmod-zfs-*.rpm

dual-sign.sh

+3
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,18 @@ if [[ "${DUAL_SIGN}" == "true" ]]; then
1616
xz --decompress "$module"
1717
openssl cms -sign -signer "${SIGNING_KEY_1}" -signer "${SIGNING_KEY_2}" -binary -in "$module_basename" -outform DER -out "${module_basename}.cms" -nocerts -noattr -nosmimecap
1818
/usr/src/kernels/"${KERNEL}"/scripts/sign-file -s "${module_basename}.cms" sha256 "${PUBLIC_CHAIN}" "${module_basename}"
19+
/tmp/dual-sign-check.sh "${KERNEL}" "${module_basename}" "${PUBLIC_CHAIN}"
1920
xz -f "${module_basename}"
2021
elif [[ "$module_suffix" == ".gz" ]]; then
2122
gzip -d "$module"
2223
openssl cms -sign -signer "${SIGNING_KEY_1}" -signer "${SIGNING_KEY_2}" -binary -in "$module_basename" -outform DER -out "${module_basename}.cms" -nocerts -noattr -nosmimecap
2324
/usr/src/kernels/"${KERNEL}"/scripts/sign-file -s "${module_basename}.cms" sha256 "${PUBLIC_CHAIN}" "${module_basename}"
25+
/tmp/dual-sign-check.sh "${KERNEL}" "${module_basename}" "${PUBLIC_CHAIN}"
2426
gzip -9f "${module_basename}"
2527
else
2628
openssl cms -sign -signer "${SIGNING_KEY_1}" -signer "${SIGNING_KEY_2}" -binary -in "$module" -outform DER -out "${module}.cms" -nocerts -noattr -nosmimecap
2729
/usr/src/kernels/"${KERNEL}"/scripts/sign-file -s "${module}.cms" sha256 "${PUBLIC_CHAIN}" "${module}"
30+
/tmp/dual-sign-check.sh "${KERNEL}" "${module}" "${PUBLIC_CHAIN}"
2831
fi
2932
done
3033
find /var/cache/akmods -type f -name \kmod-*.rpm

test-prep.sh

+155
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
#!/usr/bin/bash
2+
3+
set -oeux pipefail
4+
5+
### PREPARE REPOS
6+
# ARCH="$(rpm -E '%_arch')"
7+
RELEASE="$(rpm -E '%fedora')"
8+
9+
sed -i 's@enabled=1@enabled=0@g' /etc/yum.repos.d/fedora-cisco-openh264.repo
10+
11+
# enable RPMs with alternatives to create them in this image build
12+
mkdir -p /var/lib/alternatives
13+
14+
if [[ -f $(find /tmp/akmods-rpms/ublue-os/ublue-os-*.rpm 2> /dev/null) ]]; then
15+
dnf install -y /tmp/akmods-rpms/ublue-os/ublue-os-*.rpm
16+
fi
17+
18+
19+
# install kernel_cache provided kernel
20+
echo "Installing ${KERNEL_FLAVOR} kernel-cache RPMs..."
21+
# fedora image has no kernel so this needs nothing fancy, just install
22+
dnf install -y /tmp/kernel_cache/*.rpm
23+
24+
if [[ "${KERNEL_FLAVOR}" == "surface" ]]; then
25+
KERNEL_VERSION=$(rpm -q kernel-surface|cut -d '-' -f2-)
26+
else
27+
KERNEL_VERSION=$(rpm -q kernel|cut -d '-' -f2-)
28+
fi
29+
30+
# enable more repos
31+
RPMFUSION_MIRROR_RPMS="https://mirrors.rpmfusion.org"
32+
if [ -n "${RPMFUSION_MIRROR}" ]; then
33+
RPMFUSION_MIRROR_RPMS=${RPMFUSION_MIRROR}
34+
fi
35+
36+
if [[ "${RELEASE}" -ge 41 ]]; then
37+
COPR_RELEASE="rawhide"
38+
else
39+
COPR_RELEASE="${RELEASE}"
40+
fi
41+
42+
curl -Lo /etc/yum.repos.d/_copr_ublue-os_staging.repo \
43+
"https://copr.fedorainfracloud.org/coprs/ublue-os/staging/repo/fedora-${COPR_RELEASE}/ublue-os-staging-fedora-${COPR_RELEASE}.repo"
44+
45+
curl -Lo /etc/yum.repos.d/_copr_kylegospo_oversteer.repo \
46+
"https://copr.fedorainfracloud.org/coprs/kylegospo/oversteer/repo/fedora-${COPR_RELEASE}/kylegospo-oversteer-fedora-${COPR_RELEASE}.repo"
47+
48+
curl -Lo /etc/yum.repos.d/_copr_ublue-os-akmods.repo \
49+
"https://copr.fedorainfracloud.org/coprs/ublue-os/akmods/repo/fedora-${COPR_RELEASE}/ublue-os-akmods-fedora-${COPR_RELEASE}.repo"
50+
51+
curl -Lo /etc/yum.repos.d/negativo17-fedora-multimedia.repo \
52+
"https://negativo17.org/repos/fedora-multimedia.repo"
53+
54+
if [[ -f $(find /tmp/akmods-rpms/kmods/kmod-vhba-*.rpm) ]]; then
55+
curl -LsSf -o /etc/yum.repos.d/_copr_rok-cdemu.repo \
56+
"https://copr.fedorainfracloud.org/coprs/rok/cdemu/repo/fedora-${COPR_RELEASE}/rok-cdemu-fedora-${COPR_RELEASE}.repo"
57+
fi
58+
59+
if [[ -f $(find /tmp/akmods-rpms/kmods/kmod-facetimehd-*.rpm) ]]; then
60+
curl -LsSf -o /etc/yum.repos.d/_copr_mulderje-facetimehd-kmod.repo \
61+
"https://copr.fedorainfracloud.org/coprs/mulderje/facetimehd-kmod/repo/fedora-${COPR_RELEASE}/mulderje-facetimehd-kmod-fedora-${COPR_RELEASE}.repo"
62+
fi
63+
64+
if [[ -f $(find /tmp/akmods-rpms/kmods/kmod-kvmfr-*.rpm) ]]; then
65+
curl -LsSf -o /etc/yum.repos.d/_copr_hikariknight-looking-glass-kvmfr.repo \
66+
"https://copr.fedorainfracloud.org/coprs/hikariknight/looking-glass-kvmfr/repo/fedora-${COPR_RELEASE}/hikariknight-looking-glass-kvmfr-fedora-${COPR_RELEASE}.repo"
67+
fi
68+
69+
if [[ -f $(find /tmp/akmods-rpms/kmods/kmod-nvidia-*.rpm) ]]; then
70+
curl -Lo /etc/yum.repos.d/negativo17-fedora-nvidia.repo \
71+
"https://negativo17.org/repos/fedora-nvidia.repo"
72+
curl -Lo /etc/yum.repos.d/nvidia-container-toolkit.repo \
73+
"https://nvidia.github.io/libnvidia-container/stable/rpm/nvidia-container-toolkit.repo"
74+
curl -Lo /etc/yum.repos.d/nvidia-container.pp \
75+
"https://raw.githubusercontent.com/NVIDIA/dgx-selinux/master/bin/RHEL9/nvidia-container.pp"
76+
curl -Lo /etc/yum.repos.d/eyecantcu-supergfxctl.repo \
77+
"https://copr.fedorainfracloud.org/coprs/eyecantcu/supergfxctl/repo/fedora-${COPR_RELEASE}/eyecantcu-supergfxctl-fedora-${COPR_RELEASE}.repo"
78+
curl -Lo /tmp/nvidia-install.sh \
79+
"https://raw.githubusercontent.com/ublue-os/hwe/main/nvidia-install.sh"
80+
chmod +x /tmp/nvidia-install.sh
81+
sed -i "s@gpgcheck=0@gpgcheck=1@" /etc/yum.repos.d/nvidia-container-toolkit.repo
82+
fi
83+
84+
dnf install -y \
85+
"${RPMFUSION_MIRROR_RPMS}"/free/fedora/rpmfusion-free-release-"${RELEASE}".noarch.rpm \
86+
"${RPMFUSION_MIRROR_RPMS}"/nonfree/fedora/rpmfusion-nonfree-release-"${RELEASE}".noarch.rpm \
87+
fedora-repos-archive \
88+
openssl
89+
90+
91+
# after F41 launches, bump to 42
92+
if [[ "${FEDORA_MAJOR_VERSION}" -ge 41 ]]; then
93+
# pre-release rpmfusion is in a different location
94+
sed -i "s%free/fedora/releases%free/fedora/development%" /etc/yum.repos.d/rpmfusion-*.repo
95+
# pre-release rpmfusion needs to enable testing
96+
sed -i '0,/enabled=0/{s/enabled=0/enabled=1/}' /etc/yum.repos.d/rpmfusion-*-updates-testing.repo
97+
fi
98+
99+
if [ -n "${RPMFUSION_MIRROR}" ]; then
100+
# force use of single rpmfusion mirror
101+
echo "Using single rpmfusion mirror: ${RPMFUSION_MIRROR}"
102+
sed -i.bak "s%^metalink=%#metalink=%" /etc/yum.repos.d/rpmfusion-*.repo
103+
sed -i "s%^#baseurl=http://download1.rpmfusion.org%baseurl=${RPMFUSION_MIRROR}%" /etc/yum.repos.d/rpmfusion-*.repo
104+
fi
105+
106+
if [[ ! -s "/tmp/certs/private_key.priv" ]]; then
107+
echo "WARNING: Using test signing key. Run './generate-akmods-key' for production builds."
108+
cp /tmp/certs/public_key.der{.test,}
109+
fi
110+
111+
openssl x509 -in /tmp/certs/public_key.der -out /tmp/certs/public_key.crt
112+
cat /tmp/certs/public_key.crt > /tmp/certs/public_key_chain.pem
113+
rm -f /tmp/certs/private_key.priv
114+
115+
if [[ "${DUAL_SIGN}" == "true" ]]; then
116+
if [[ ! -s "/tmp/certs/private_key_2.priv" ]]; then
117+
echo "WARNING: Using test signing key. Run './generate-akmods-key' for production builds."
118+
cp /tmp/certs/public_key_2.der{.test,}
119+
fi
120+
openssl x509 -in /tmp/certs/public_key_2.der -out /tmp/certs/public_key_2.crt
121+
rm -f /tmp/certs/public_key_chain.pem
122+
cat /tmp/certs/public_key.crt <(echo) /tmp/certs/public_key_2.crt >> /tmp/certs/public_key_chain.pem
123+
fi
124+
125+
rm -f /tmp/certs/private_key_2.priv
126+
127+
if [[ -f $(find /tmp/akmods-rpms/kmods/kmod-nvidia-*.rpm 2> /dev/null) ]]; then
128+
sed -i '0,/enabled=0/{s/enabled=0/enabled=1/}' /etc/yum.repos.d/eyecantcu-supergfxctl.repo
129+
sed -i '0,/enabled=0/{s/enabled=0/enabled=1/}' /etc/yum.repos.d/negativo17-fedora-nvidia.repo
130+
sed -i '0,/enabled=0/{s/enabled=0/enabled=1/}' /etc/yum.repos.d/nvidia-container-toolkit.repo
131+
source /tmp/akmods-rpms/kmods/nvidia-vars
132+
dnf install -y \
133+
libnvidia-fbc \
134+
libnvidia-ml.i686 \
135+
libva-nvidia-driver \
136+
mesa-vulkan-drivers.i686 \
137+
nvidia-driver \
138+
nvidia-driver-cuda \
139+
nvidia-driver-cuda-libs.i686 \
140+
nvidia-driver-libs.i686 \
141+
nvidia-modprobe \
142+
nvidia-persistenced \
143+
nvidia-settings \
144+
nvidia-container-toolkit \
145+
/tmp/akmods-rpms/kmods/kmod-nvidia-"${KERNEL_VERSION}"-"${NVIDIA_AKMOD_VERSION}".fc"${RELEASE}".rpm
146+
elif [[ -f $(find /tmp/akmods-rpms/kmods/zfs/kmod-*.rpm 2> /dev/null) ]]; then
147+
dnf install -y \
148+
pv \
149+
/tmp/akmods-rpms/kmods/zfs/*.rpm
150+
else
151+
dnf install -y \
152+
/tmp/akmods-rpms/kmods/*.rpm
153+
fi
154+
155+
printf "KERNEL_NAME=%s" "$KERNEL_NAME" >> /tmp/info.sh

0 commit comments

Comments
 (0)