Skip to content

Commit 67c35f0

Browse files
committed
sysext: Sign built-in sysexts
Generate an ephemeral sysext signing key, that is injected into the image's sysext root of trust. All OS-dependent sysexts will be signed by this key and the private key (stored in /tmp) will be discarded on SDK container exit.
1 parent 68dac14 commit 67c35f0

File tree

5 files changed

+66
-12
lines changed

5 files changed

+66
-12
lines changed

build_library/prod_image_util.sh

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,10 @@ EOF
162162
# Remove source locale data, only need to ship the compiled archive.
163163
sudo rm -rf ${root_fs_dir}/usr/share/i18n/
164164

165+
# Inject ephemeral sysext signing certificate
166+
sudo mkdir -p "${root_fs_dir}/usr/lib/verity.d"
167+
sudo cp "${SYSEXT_SIGNING_KEY_DIR}/sysexts.crt" "${root_fs_dir}/usr/lib/verity.d"
168+
165169
# Finish image will move files from /etc to /usr/share/flatcar/etc.
166170
# Note that image filesystem contents generated by finish_image will not
167171
# include sysext contents (only the sysext squashfs files themselves).

build_library/sysext_prod_builder

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ create_prod_sysext() {
5959
# Pass the build ID extracted from root FS to build_sysext. This prevents common.sh
6060
# in build_sysext to generate a (timestamp based) build ID during a DEV build of a
6161
# release tag (which breaks its version check).
62-
sudo "FLATCAR_BUILD_ID=$FLATCAR_BUILD_ID" "${SCRIPTS_DIR}/build_sysext" \
62+
sudo -E "FLATCAR_BUILD_ID=$FLATCAR_BUILD_ID" "${SCRIPTS_DIR}/build_sysext" \
6363
--board="${BOARD}" \
6464
--image_builddir="${workdir}/sysext-build" \
6565
--squashfs_base="${base_sysext}" \
@@ -94,6 +94,14 @@ sysext_mountdir="${BUILD_DIR}/prod-sysext-work/mounts"
9494
sysext_base="${sysext_workdir}/base-os.squashfs"
9595

9696
function cleanup() {
97+
IFS=':' read -r -a mounted_sysexts <<< "$sysext_lowerdirs"
98+
# skip the rootfs
99+
mounted_sysexts=("${mounted_sysexts[@]:1}")
100+
101+
for sysext in "${mounted_sysexts[@]}"; do
102+
sudo systemd-dissect --umount --rmdir "$sysext"
103+
done
104+
97105
sudo umount "${sysext_mountdir}"/* || true
98106
rm -rf "${sysext_workdir}" || true
99107
}
@@ -111,6 +119,7 @@ sudo mksquashfs "${root_fs_dir}" "${sysext_base}" -noappend -xattrs-exclude '^bt
111119
# for combined overlay later.
112120
prev_pkginfo=""
113121
sysext_lowerdirs="${sysext_mountdir}/rootfs-lower"
122+
mkdir -p "${sysext_mountdir}"
114123
for sysext in ${sysexts_list//,/ }; do
115124
# format is "<name>:<group>/<package>"
116125
name="${sysext%|*}"
@@ -124,12 +133,21 @@ for sysext in ${sysexts_list//,/ }; do
124133
"${grp_pkg}" \
125134
"${prev_pkginfo}"
126135

127-
mkdir -p "${sysext_mountdir}/${name}" \
128-
"${sysext_mountdir}/${name}_pkginfo"
129-
sudo mount -rt squashfs -o loop,nodev "${sysext_output_dir}/${name}.raw" \
130-
"${sysext_mountdir}/${name}"
131-
sudo mount -rt squashfs -o loop,nodev "${sysext_output_dir}/${name}_pkginfo.raw" \
132-
"${sysext_mountdir}/${name}_pkginfo"
136+
sudo systemd-dissect \
137+
--read-only \
138+
--mount \
139+
--mkdir \
140+
--image-policy='root=encrypted+unprotected+absent:usr=encrypted+unprotected+absent' \
141+
"${sysext_output_dir}/${name}.raw" \
142+
"${sysext_mountdir}/${name}"
143+
144+
sudo systemd-dissect \
145+
--read-only \
146+
--mount \
147+
--mkdir \
148+
--image-policy='root=encrypted+unprotected+absent:usr=encrypted+unprotected+absent' \
149+
"${sysext_output_dir}/${name}_pkginfo.raw" \
150+
"${sysext_mountdir}/${name}_pkginfo"
133151

134152
sysext_lowerdirs="${sysext_lowerdirs}:${sysext_mountdir}/${name}"
135153
sysext_lowerdirs="${sysext_lowerdirs}:${sysext_mountdir}/${name}_pkginfo"

build_library/vm_image_util.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -580,7 +580,7 @@ install_oem_sysext() {
580580
fi
581581

582582
mkdir -p "${built_sysext_dir}"
583-
sudo "${build_sysext_env[@]}" "${SCRIPT_ROOT}/build_sysext" "${build_sysext_flags[@]}" "${oem_sysext}"
583+
sudo -E "${build_sysext_env[@]}" "${SCRIPT_ROOT}/build_sysext" "${build_sysext_flags[@]}" "${oem_sysext}"
584584

585585
local installed_sysext_oem_dir='/oem/sysext'
586586
local installed_sysext_file_prefix="${oem_sysext}-${version}"

build_sysext

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -301,14 +301,25 @@ if [[ -n "${invalid_files}" ]]; then
301301
die "Invalid file ownership: ${invalid_files}"
302302
fi
303303

304-
mksquashfs "${BUILD_DIR}/install-root" "${BUILD_DIR}/${SYSEXTNAME}.raw" \
305-
-noappend -xattrs-exclude '^btrfs.' -comp "${FLAGS_compression}" ${FLAGS_mksquashfs_opts}
304+
systemd-repart \
305+
--private-key="${SYSEXT_SIGNING_KEY_DIR}/sysexts.key" \
306+
--certificate="${SYSEXT_SIGNING_KEY_DIR}/sysexts.crt" \
307+
--make-ddi=sysext \
308+
--copy-source="${BUILD_DIR}/install-root" \
309+
"${BUILD_DIR}/${SYSEXTNAME}.raw"
310+
306311
rm -rf "${BUILD_DIR}"/{fs-root,install-root,workdir}
307312

308313
# Generate reports
309314
mkdir "${BUILD_DIR}/img-rootfs"
310-
mount -rt squashfs -o loop,nodev "${BUILD_DIR}/${SYSEXTNAME}.raw" "${BUILD_DIR}/img-rootfs"
315+
systemd-dissect --read-only \
316+
--mount \
317+
--mkdir \
318+
--image-policy='root=encrypted+unprotected+absent:usr=encrypted+unprotected+absent' \
319+
"${BUILD_DIR}/${SYSEXTNAME}.raw" \
320+
"${BUILD_DIR}/img-rootfs"
321+
311322
write_contents "${BUILD_DIR}/img-rootfs" "${BUILD_DIR}/${SYSEXTNAME}_contents.txt"
312323
write_contents_with_technical_details "${BUILD_DIR}/img-rootfs" "${BUILD_DIR}/${SYSEXTNAME}_contents_wtd.txt"
313324
write_disk_space_usage_in_paths "${BUILD_DIR}/img-rootfs" "${BUILD_DIR}/${SYSEXTNAME}_disk_usage.txt"
314-
umount "${BUILD_DIR}/img-rootfs"
325+
systemd-dissect --umount --rmdir "${BUILD_DIR}/img-rootfs"

sdk_lib/sdk_entry.sh

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,27 @@ grep -q 'export MODULE_SIGNING_KEY_DIR' /home/sdk/.bashrc || {
6363
fi
6464
}
6565

66+
grep -q 'export SYSEXT_SIGNING_KEY_DIR' /home/sdk/.bashrc || {
67+
SYSEXT_SIGNING_KEY_DIR=$(su sdk -c "mktemp -d")
68+
if [[ ! "$SYSEXT_SIGNING_KEY_DIR" || ! -d "$SYSEXT_SIGNING_KEY_DIR" ]]; then
69+
echo "Failed to create temporary directory for secure boot keys."
70+
else
71+
echo "export SYSEXT_SIGNING_KEY_DIR='$SYSEXT_SIGNING_KEY_DIR'" >> /home/sdk/.bashrc
72+
fi
73+
pushd "$SYSEXT_SIGNING_KEY_DIR"
74+
build_id=$(source "/mnt/host/source/.repo/manifests/version.txt"; echo "$FLATCAR_BUILD_ID")
75+
openssl req -new -nodes -utf8 \
76+
-x509 -batch -sha256 \
77+
-days 36000 \
78+
-outform PEM \
79+
-out sysexts.crt \
80+
-keyout sysexts.key \
81+
-newkey 4096 \
82+
-subj "/CN=Flatcar $build_id sysext signing key/" \
83+
|| echo "Generating module signing key failed"
84+
popd
85+
}
86+
6687
# This is ugly.
6788
# We need to sudo su - sdk -c so the SDK user gets a fresh login.
6889
# 'sdk' is member of multiple groups, and plain docker USER only

0 commit comments

Comments
 (0)