Skip to content

Commit 4a2154f

Browse files
committed
sysext: Sign OS-dependent 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. Signed-off-by: Daniel Zatovic <[email protected]>
1 parent 89da3cc commit 4a2154f

File tree

5 files changed

+82
-12
lines changed

5 files changed

+82
-12
lines changed

build_library/prod_image_util.sh

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

173+
# Inject ephemeral sysext signing certificate
174+
sudo mkdir -p "${root_fs_dir}/usr/lib/verity.d"
175+
sudo cp "${SYSEXT_SIGNING_KEY_DIR}/sysexts.crt" "${root_fs_dir}/usr/lib/verity.d"
176+
173177
# Finish image will move files from /etc to /usr/share/flatcar/etc.
174178
# Note that image filesystem contents generated by finish_image will not
175179
# 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
@@ -63,7 +63,7 @@ create_prod_sysext() {
6363
# The --install_root_basename="${name}-base-sysext-rootfs" flag is
6464
# important - it sets the name of a rootfs directory, which is used
6565
# to determine the package target in coreos/base/profile.bashrc
66-
sudo "FLATCAR_BUILD_ID=$FLATCAR_BUILD_ID" "${SCRIPTS_DIR}/build_sysext" \
66+
sudo -E "FLATCAR_BUILD_ID=$FLATCAR_BUILD_ID" "${SCRIPTS_DIR}/build_sysext" \
6767
--board="${BOARD}" \
6868
--image_builddir="${workdir}/sysext-build" \
6969
--squashfs_base="${base_sysext}" \
@@ -99,6 +99,14 @@ sysext_mountdir="${BUILD_DIR}/prod-sysext-work/mounts"
9999
sysext_base="${sysext_workdir}/base-os.squashfs"
100100

101101
function cleanup() {
102+
IFS=':' read -r -a mounted_sysexts <<< "$sysext_lowerdirs"
103+
# skip the rootfs
104+
mounted_sysexts=("${mounted_sysexts[@]:1}")
105+
106+
for sysext in "${mounted_sysexts[@]}"; do
107+
sudo systemd-dissect --umount --rmdir "$sysext"
108+
done
109+
102110
sudo umount "${sysext_mountdir}"/* || true
103111
rm -rf "${sysext_workdir}" || true
104112
}
@@ -116,6 +124,7 @@ sudo mksquashfs "${root_fs_dir}" "${sysext_base}" -noappend -xattrs-exclude '^bt
116124
# for combined overlay later.
117125
prev_pkginfo=""
118126
sysext_lowerdirs="${sysext_mountdir}/rootfs-lower"
127+
mkdir -p "${sysext_mountdir}"
119128
for sysext in ${sysexts_list//,/ }; do
120129
# format is "<name>:<group>/<package>"
121130
name="${sysext%|*}"
@@ -129,12 +138,21 @@ for sysext in ${sysexts_list//,/ }; do
129138
"${grp_pkg}" \
130139
"${prev_pkginfo}"
131140

132-
mkdir -p "${sysext_mountdir}/${name}" \
133-
"${sysext_mountdir}/${name}_pkginfo"
134-
sudo mount -rt squashfs -o loop,nodev "${sysext_output_dir}/${name}.raw" \
135-
"${sysext_mountdir}/${name}"
136-
sudo mount -rt squashfs -o loop,nodev "${sysext_output_dir}/${name}_pkginfo.raw" \
137-
"${sysext_mountdir}/${name}_pkginfo"
141+
sudo systemd-dissect \
142+
--read-only \
143+
--mount \
144+
--mkdir \
145+
--image-policy='root=encrypted+unprotected+absent:usr=encrypted+unprotected+absent' \
146+
"${sysext_output_dir}/${name}.raw" \
147+
"${sysext_mountdir}/${name}"
148+
149+
sudo systemd-dissect \
150+
--read-only \
151+
--mount \
152+
--mkdir \
153+
--image-policy='root=encrypted+unprotected+absent:usr=encrypted+unprotected+absent' \
154+
"${sysext_output_dir}/${name}_pkginfo.raw" \
155+
"${sysext_mountdir}/${name}_pkginfo"
138156

139157
sysext_lowerdirs="${sysext_lowerdirs}:${sysext_mountdir}/${name}"
140158
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
@@ -602,7 +602,7 @@ install_oem_sysext() {
602602
fi
603603

604604
mkdir -p "${built_sysext_dir}"
605-
sudo "${build_sysext_env[@]}" "${SCRIPT_ROOT}/build_sysext" "${build_sysext_flags[@]}" "${oem_sysext}"
605+
sudo -E "${build_sysext_env[@]}" "${SCRIPT_ROOT}/build_sysext" "${build_sysext_flags[@]}" "${oem_sysext}"
606606

607607
local installed_sysext_oem_dir='/oem/sysext'
608608
local installed_sysext_file_prefix="${oem_sysext}-${version}"

build_sysext

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

307-
mksquashfs "${BUILD_DIR}/${FLAGS_install_root_basename}" "${BUILD_DIR}/${SYSEXTNAME}.raw" \
308-
-noappend -xattrs-exclude '^btrfs.' -comp "${FLAGS_compression}" ${FLAGS_mksquashfs_opts}
307+
systemd-repart \
308+
--private-key="${SYSEXT_SIGNING_KEY_DIR}/sysexts.key" \
309+
--certificate="${SYSEXT_SIGNING_KEY_DIR}/sysexts.crt" \
310+
--make-ddi=sysext \
311+
--copy-source="${BUILD_DIR}/${FLAGS_install_root_basename}" \
312+
"${BUILD_DIR}/${SYSEXTNAME}.raw"
313+
309314
rm -rf "${BUILD_DIR}"/{fs-root,"${FLAGS_install_root_basename}",workdir}
310315

311316
# Generate reports
312317
mkdir "${BUILD_DIR}/img-rootfs"
313-
mount -rt squashfs -o loop,nodev "${BUILD_DIR}/${SYSEXTNAME}.raw" "${BUILD_DIR}/img-rootfs"
318+
systemd-dissect --read-only \
319+
--mount \
320+
--mkdir \
321+
--image-policy='root=encrypted+unprotected+absent:usr=encrypted+unprotected+absent' \
322+
"${BUILD_DIR}/${SYSEXTNAME}.raw" \
323+
"${BUILD_DIR}/img-rootfs"
324+
314325
write_contents "${BUILD_DIR}/img-rootfs" "${BUILD_DIR}/${SYSEXTNAME}_contents.txt"
315326
write_contents_with_technical_details "${BUILD_DIR}/img-rootfs" "${BUILD_DIR}/${SYSEXTNAME}_contents_wtd.txt"
316327
write_disk_space_usage_in_paths "${BUILD_DIR}/img-rootfs" "${BUILD_DIR}/${SYSEXTNAME}_disk_usage.txt"
317-
umount "${BUILD_DIR}/img-rootfs"
328+
systemd-dissect --umount --rmdir "${BUILD_DIR}/img-rootfs"

sdk_lib/sdk_entry.sh

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,43 @@ if ! grep -q 'export MODULE_SIGNING_KEY_DIR=' /home/sdk/.bashrc; then
8888
fi
8989
fi
9090

91+
# Ensure sysext signing keys exist; regenerate if directory or files missing
92+
if grep -q 'export SYSEXT_SIGNING_KEY_DIR' /home/sdk/.bashrc; then
93+
_existing_sysext_dir=$(source /home/sdk/.bashrc 2>/dev/null; echo "$SYSEXT_SIGNING_KEY_DIR")
94+
if [[ -z "$_existing_sysext_dir" || ! -d "$_existing_sysext_dir" || ! -s "$_existing_sysext_dir/sysexts.key" || ! -s "$_existing_sysext_dir/sysexts.crt" ]]; then
95+
# Drop stale export so block below regenerates
96+
sed -i -e '/export SYSEXT_SIGNING_KEY_DIR=/d' /home/sdk/.bashrc
97+
fi
98+
fi
99+
grep -q 'export SYSEXT_SIGNING_KEY_DIR' /home/sdk/.bashrc || {
100+
if [[ ${COREOS_OFFICIAL:-0} -eq 1 ]]; then
101+
SYSEXT_SIGNING_KEY_DIR=$(su sdk -c "mktemp -d")
102+
else
103+
SYSEXT_SIGNING_KEY_DIR="/home/sdk/.sysext-signing-keys"
104+
su sdk -c "mkdir -p ${SYSEXT_SIGNING_KEY_DIR@Q}"
105+
fi
106+
if [[ ! "$SYSEXT_SIGNING_KEY_DIR" || ! -d "$SYSEXT_SIGNING_KEY_DIR" ]]; then
107+
echo "Failed to create directory for sysext signing keys."
108+
else
109+
echo "export SYSEXT_SIGNING_KEY_DIR='$SYSEXT_SIGNING_KEY_DIR'" >> /home/sdk/.bashrc
110+
fi
111+
pushd "$SYSEXT_SIGNING_KEY_DIR" > /dev/null
112+
build_id=$(source "/mnt/host/source/.repo/manifests/version.txt"; echo "$FLATCAR_BUILD_ID")
113+
# Generate sysext signing key only if missing or empty
114+
if [[ ! -s sysexts.key || ! -s sysexts.crt ]]; then
115+
su sdk -c "openssl req -new -nodes -utf8 \
116+
-x509 -batch -sha256 \
117+
-days 36000 \
118+
-outform PEM \
119+
-out sysexts.crt \
120+
-keyout sysexts.key \
121+
-newkey 4096 \
122+
-subj '/CN=Flatcar sysext key/OU=$build_id'" \
123+
|| echo "Generating sysext signing key failed"
124+
fi
125+
popd > /dev/null
126+
}
127+
91128
# This is ugly.
92129
# We need to sudo su - sdk -c so the SDK user gets a fresh login.
93130
# 'sdk' is member of multiple groups, and plain docker USER only

0 commit comments

Comments
 (0)