Skip to content

Signed built-in sysexts #3162

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/portage-stable-packages-list
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,7 @@ dev-libs/tree-sitter
dev-libs/tree-sitter-bash
dev-libs/userspace-rcu
dev-libs/xmlsec
dev-libs/xxhash
dev-libs/yajl

dev-perl/Parse-Yapp
Expand Down Expand Up @@ -666,6 +667,7 @@ sys-fs/btrfs-progs
sys-fs/cryptsetup
sys-fs/dosfstools
sys-fs/e2fsprogs
sys-fs/erofs-utils
sys-fs/fuse
sys-fs/fuse-common
sys-fs/fuse-overlayfs
Expand Down
4 changes: 4 additions & 0 deletions build_library/prod_image_util.sh
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,10 @@ EOF
# Remove source locale data, only need to ship the compiled archive.
sudo rm -rf ${root_fs_dir}/usr/share/i18n/

# Inject ephemeral sysext signing certificate
sudo mkdir -p "${root_fs_dir}/usr/lib/verity.d"
sudo cp "${SYSEXT_SIGNING_KEY_DIR}/sysexts.crt" "${root_fs_dir}/usr/lib/verity.d"

# Finish image will move files from /etc to /usr/share/flatcar/etc.
# Note that image filesystem contents generated by finish_image will not
# include sysext contents (only the sysext squashfs files themselves).
Expand Down
32 changes: 25 additions & 7 deletions build_library/sysext_prod_builder
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ create_prod_sysext() {
# Pass the build ID extracted from root FS to build_sysext. This prevents common.sh
# in build_sysext to generate a (timestamp based) build ID during a DEV build of a
# release tag (which breaks its version check).
sudo "FLATCAR_BUILD_ID=$FLATCAR_BUILD_ID" "${SCRIPTS_DIR}/build_sysext" \
sudo -E "FLATCAR_BUILD_ID=$FLATCAR_BUILD_ID" "${SCRIPTS_DIR}/build_sysext" \
--board="${BOARD}" \
--image_builddir="${workdir}/sysext-build" \
--squashfs_base="${base_sysext}" \
Expand Down Expand Up @@ -94,6 +94,14 @@ sysext_mountdir="${BUILD_DIR}/prod-sysext-work/mounts"
sysext_base="${sysext_workdir}/base-os.squashfs"

function cleanup() {
IFS=':' read -r -a mounted_sysexts <<< "$sysext_lowerdirs"
# skip the rootfs
mounted_sysexts=("${mounted_sysexts[@]:1}")

for sysext in "${mounted_sysexts[@]}"; do
sudo systemd-dissect --umount --rmdir "$sysext"
done

sudo umount "${sysext_mountdir}"/* || true
rm -rf "${sysext_workdir}" || true
}
Expand All @@ -111,6 +119,7 @@ sudo mksquashfs "${root_fs_dir}" "${sysext_base}" -noappend -xattrs-exclude '^bt
# for combined overlay later.
prev_pkginfo=""
sysext_lowerdirs="${sysext_mountdir}/rootfs-lower"
mkdir -p "${sysext_mountdir}"
for sysext in ${sysexts_list//,/ }; do
# format is "<name>:<group>/<package>"
name="${sysext%|*}"
Expand All @@ -124,12 +133,21 @@ for sysext in ${sysexts_list//,/ }; do
"${grp_pkg}" \
"${prev_pkginfo}"

mkdir -p "${sysext_mountdir}/${name}" \
"${sysext_mountdir}/${name}_pkginfo"
sudo mount -rt squashfs -o loop,nodev "${sysext_output_dir}/${name}.raw" \
"${sysext_mountdir}/${name}"
sudo mount -rt squashfs -o loop,nodev "${sysext_output_dir}/${name}_pkginfo.raw" \
"${sysext_mountdir}/${name}_pkginfo"
sudo systemd-dissect \
--read-only \
--mount \
--mkdir \
--image-policy='root=encrypted+unprotected+absent:usr=encrypted+unprotected+absent' \
"${sysext_output_dir}/${name}.raw" \
"${sysext_mountdir}/${name}"

sudo systemd-dissect \
--read-only \
--mount \
--mkdir \
--image-policy='root=encrypted+unprotected+absent:usr=encrypted+unprotected+absent' \
"${sysext_output_dir}/${name}_pkginfo.raw" \
"${sysext_mountdir}/${name}_pkginfo"

sysext_lowerdirs="${sysext_lowerdirs}:${sysext_mountdir}/${name}"
sysext_lowerdirs="${sysext_lowerdirs}:${sysext_mountdir}/${name}_pkginfo"
Expand Down
2 changes: 1 addition & 1 deletion build_library/vm_image_util.sh
Original file line number Diff line number Diff line change
Expand Up @@ -580,7 +580,7 @@ install_oem_sysext() {
fi

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

local installed_sysext_oem_dir='/oem/sysext'
local installed_sysext_file_prefix="${oem_sysext}-${version}"
Expand Down
19 changes: 15 additions & 4 deletions build_sysext
Original file line number Diff line number Diff line change
Expand Up @@ -301,14 +301,25 @@ if [[ -n "${invalid_files}" ]]; then
die "Invalid file ownership: ${invalid_files}"
fi

mksquashfs "${BUILD_DIR}/install-root" "${BUILD_DIR}/${SYSEXTNAME}.raw" \
-noappend -xattrs-exclude '^btrfs.' -comp "${FLAGS_compression}" ${FLAGS_mksquashfs_opts}
systemd-repart \
--private-key="${SYSEXT_SIGNING_KEY_DIR}/sysexts.key" \
--certificate="${SYSEXT_SIGNING_KEY_DIR}/sysexts.crt" \
--make-ddi=sysext \
--copy-source="${BUILD_DIR}/install-root" \
"${BUILD_DIR}/${SYSEXTNAME}.raw"

rm -rf "${BUILD_DIR}"/{fs-root,install-root,workdir}

# Generate reports
mkdir "${BUILD_DIR}/img-rootfs"
mount -rt squashfs -o loop,nodev "${BUILD_DIR}/${SYSEXTNAME}.raw" "${BUILD_DIR}/img-rootfs"
systemd-dissect --read-only \
--mount \
--mkdir \
--image-policy='root=encrypted+unprotected+absent:usr=encrypted+unprotected+absent' \
"${BUILD_DIR}/${SYSEXTNAME}.raw" \
"${BUILD_DIR}/img-rootfs"

write_contents "${BUILD_DIR}/img-rootfs" "${BUILD_DIR}/${SYSEXTNAME}_contents.txt"
write_contents_with_technical_details "${BUILD_DIR}/img-rootfs" "${BUILD_DIR}/${SYSEXTNAME}_contents_wtd.txt"
write_disk_space_usage_in_paths "${BUILD_DIR}/img-rootfs" "${BUILD_DIR}/${SYSEXTNAME}_disk_usage.txt"
umount "${BUILD_DIR}/img-rootfs"
systemd-dissect --umount --rmdir "${BUILD_DIR}/img-rootfs"
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ DEPEND="
sys-firmware/edk2-bin
sys-fs/btrfs-progs
sys-fs/cryptsetup
sys-fs/erofs-utils
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
sys-fs/erofs-utils
sys-fs/erofs-utils

dev-perl/Parse-Yapp
dev-util/pkgcheck
"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
USE="cros_host expat man -pam"
USE="${USE} cryptsetup"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could have consequences. What needs this, and could it be done against that specific package?


# Used by some old goo in profiles/coreos/base/profile.bashrc
# TODO: clean up that old goo
Expand Down
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
# Temporarily put the SDK version ahead for sd-json support in Dracut.
=sys-apps/systemd-257.5 ~amd64 ~arm64

=sys-fs/erofs-utils-1.8.4 ~amd64 ~arm64
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ src_prepare() {
validate_sig_key

config_update 'CONFIG_INITRAMFS_SOURCE="bootengine.cpio"'
config_update "CONFIG_SYSTEM_TRUSTED_KEYS=\"/usr/share/sb_keys/shim.pem\""
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think you meant to include this, and this certificate should not be used in production builds.

Suggested change
config_update "CONFIG_SYSTEM_TRUSTED_KEYS=\"/usr/share/sb_keys/shim.pem\""


# include all intel and amd microcode files, avoiding the signatures
local fw_dir="${ESYSROOT}/lib/firmware"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ CONFIG_DM_SNAPSHOT=m
CONFIG_DM_THIN_PROVISIONING=m
CONFIG_DM_UEVENT=y
CONFIG_DM_VERITY=m
CONFIG_DM_VERITY_VERIFY_ROOTHASH_SIG=y
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The certificate you're signing with is written to /usr/lib/verity.d, so you don't need this. The verification is done in userspace.

However, I have doubts about this security model. You're verifying sysexts in USR with a certificate in USR. Does that add anything, especially when USR's own integrity is already enforced by verity? Having the certificate in the kernel keyring may be a stronger model, but I'm not the best person to ask. @jepio, your input here would be appreciated.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we use this for the extensions that are downloaded on demand, it makes sense. For the ones itself stored in /usr it might be useful to have them also signed for enforcing a policy.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We were going to have bakery sysexts use certificates in /etc/verity.d because we felt more flexibility was needed here. What if we need to rotate the certificate? Newer sysexts are supposed to work on older Flatcar releases.

CONFIG_DM_ZERO=m
CONFIG_DNS_RESOLVER=y
CONFIG_DRM=m
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
DIST xxhash-0.8.2.tar.gz 1141188 BLAKE2B 735408256240760778fa516e01bed428f04837eb4e059c512e924f13e4a96db6cacbbefb04dea65a37b0f25b52cf13c4927a6e7870dc8c0d45b1b955d4ba3da1 SHA512 3e3eef21432fe88bc4dd9940ccad0308fdea3537b06fa5ac0e74c1bde53413dff29c8b3fc617a8a42b9ce88fcf213311d338a31b1ce73b3729342c9e68f06c78
DIST xxhash-0.8.3.tar.gz 1147630 BLAKE2B 75923c7c5df3490062791fa02ccddfb7281b3646e2b3e4b4a0c0d611c339e07c8d9cb656777fd0fcec9cda484f7b33edf080116bb011f70d6b8299cda63afa4e SHA512 8b5c8b9aad4e869f28310b12cc314037feda81d92f26c23eaecdb35dc65042ca2e65f2e9606033e62a31bcc737a9a950500ffcbdb8677d6ab20e820ea14f2b79
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE pkgmetadata SYSTEM "https://www.gentoo.org/dtd/metadata.dtd">
<pkgmetadata>
<maintainer type="person">
<email>[email protected]</email>
<name>Guilherme Amadio</name>
</maintainer>
<upstream>
<remote-id type="github">Cyan4973/xxHash</remote-id>
<bugs-to>https://github.com/Cyan4973/xxHash/issues</bugs-to>
</upstream>
</pkgmetadata>
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Copyright 1999-2023 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2

EAPI=8

inherit multilib-minimal toolchain-funcs

DESCRIPTION="Extremely fast non-cryptographic hash algorithm"
HOMEPAGE="https://xxhash.com/"
SRC_URI="https://github.com/Cyan4973/xxHash/archive/v${PV}.tar.gz -> ${P}.tar.gz"
S=${WORKDIR}/xxHash-${PV}

LICENSE="BSD-2 GPL-2+"
# https://abi-laboratory.pro/tracker/timeline/xxhash
SLOT="0"
KEYWORDS="~alpha amd64 arm arm64 hppa ~loong ~mips ppc ppc64 ~riscv ~s390 sparc x86 ~x64-macos"

src_prepare() {
default

multilib_copy_sources
}

multilib_src_compile() {
emake AR="$(tc-getAR)" CC="$(tc-getCC)"
}

multilib_src_test() {
emake CC="$(tc-getCC)" check
}

multilib_src_install() {
local emakeargs=(
DESTDIR="${D}"
PREFIX="${EPREFIX}"/usr
LIBDIR="${EPREFIX}"/usr/$(get_libdir)
)

emake "${emakeargs[@]}" install
einstalldocs

rm "${ED}"/usr/$(get_libdir)/libxxhash.a || die
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Copyright 1999-2025 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2

EAPI=8

inherit multilib-minimal toolchain-funcs

DESCRIPTION="Extremely fast non-cryptographic hash algorithm"
HOMEPAGE="https://xxhash.com/"
SRC_URI="https://github.com/Cyan4973/xxHash/archive/v${PV}.tar.gz -> ${P}.tar.gz"
S=${WORKDIR}/xxHash-${PV}

LICENSE="BSD-2 GPL-2+"
SLOT="0"
KEYWORDS="~alpha amd64 arm arm64 hppa ~loong ~mips ppc ppc64 ~riscv ~s390 sparc x86 ~x64-macos"

src_prepare() {
default

multilib_copy_sources
}

multilib_src_compile() {
emake AR="$(tc-getAR)" CC="$(tc-getCC)"
}

multilib_src_test() {
emake CC="$(tc-getCC)" check
}

multilib_src_install() {
local emakeargs=(
DESTDIR="${D}"
PREFIX="${EPREFIX}"/usr
LIBDIR="${EPREFIX}"/usr/$(get_libdir)
)

emake "${emakeargs[@]}" install
einstalldocs

rm "${ED}"/usr/$(get_libdir)/libxxhash.a || die
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
DIST erofs-utils-1.8.4.tar.gz 187276 BLAKE2B da0d80abbfd9b2d547c30bad7647165a3500f20e5de0b5db4c54efb27ec895fd069be983193b06d35728f5a8e1490e6cd255207c76135d8978d86e1512430755 SHA512 c941b0a2ab6c650a9aa4c9cadeb277ebc87007dc51354ff013c7cb763e6e8c9d44ed9e4791730ed05088faaba8c612198b924e70f5e52019382cfdf6d2e6b677
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# Copyright 2021-2025 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2

EAPI=8

inherit autotools

DESCRIPTION="Userspace tools for EROFS"
HOMEPAGE="https://git.kernel.org/pub/scm/linux/kernel/git/xiang/erofs-utils.git"

SRC_URI="https://git.kernel.org/pub/scm/linux/kernel/git/xiang/${PN}.git/snapshot/${P}.tar.gz"

LICENSE="GPL-2+"
SLOT="0"
KEYWORDS="~amd64 ~arm64 ~loong"

IUSE="fuse libdeflate +lz4 +lzma selinux static-libs +threads +uuid +zlib +zstd"

RDEPEND="
dev-libs/xxhash:0=
fuse? ( sys-fs/fuse:0 )
lz4? ( app-arch/lz4:0= )
lzma? ( >=app-arch/xz-utils-5.4.0:0= )
selinux? ( sys-libs/libselinux:0= )
uuid? ( sys-apps/util-linux )
zlib? (
libdeflate? ( app-arch/libdeflate:0= )
!libdeflate? ( sys-libs/zlib:0= )
)
zstd? ( app-arch/zstd:0= )
"
DEPEND="${RDEPEND}"
BDEPEND="virtual/pkgconfig"

PATCHES=(
)

src_prepare() {
default
eautoreconf
}

src_configure() {
local myeconfargs=(
--disable-werror
$(use_enable fuse)
$(use_with libdeflate)
$(use_enable lz4)
$(use_enable lzma)
$(use_with selinux)
$(use_enable static-libs static-fuse)
$(use_enable threads multithreading)
$(use_with uuid)
$(use_with zlib)
$(use_with zstd libzstd)
--without-qpl # not packaged
# do not use bundled xxhash; also upstream says "expected to be
# faster than the internal one"
--with-xxhash
)

econf "${myeconfargs[@]}"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE pkgmetadata SYSTEM "https://www.gentoo.org/dtd/metadata.dtd">
<pkgmetadata>
<maintainer type="person">
<email>[email protected]</email>
<name>WANG Xuerui</name>
</maintainer>
<use>
<flag name="fuse">Builds erofsfuse (requires <pkg>sys-fs/fuse</pkg>).</flag>
<flag name="libdeflate">Use <pkg>app-arch/libdeflate</pkg> rather than <pkg>sys-libs/zlib</pkg> for handling deflate compression.</flag>
<flag name="uuid">Enables UUID support via <pkg>sys-apps/util-linux</pkg>.</flag>
</use>
</pkgmetadata>
21 changes: 21 additions & 0 deletions sdk_lib/sdk_entry.sh
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,27 @@ grep -q 'export MODULE_SIGNING_KEY_DIR' /home/sdk/.bashrc || {
fi
}

grep -q 'export SYSEXT_SIGNING_KEY_DIR' /home/sdk/.bashrc || {
SYSEXT_SIGNING_KEY_DIR=$(su sdk -c "mktemp -d")
if [[ ! "$SYSEXT_SIGNING_KEY_DIR" || ! -d "$SYSEXT_SIGNING_KEY_DIR" ]]; then
echo "Failed to create temporary directory for secure boot keys."
else
echo "export SYSEXT_SIGNING_KEY_DIR='$SYSEXT_SIGNING_KEY_DIR'" >> /home/sdk/.bashrc
fi
pushd "$SYSEXT_SIGNING_KEY_DIR"
build_id=$(source "/mnt/host/source/.repo/manifests/version.txt"; echo "$FLATCAR_BUILD_ID")
openssl req -new -nodes -utf8 \
-x509 -batch -sha256 \
-days 36000 \
-outform PEM \
-out sysexts.crt \
-keyout sysexts.key \
-newkey 4096 \
-subj "/CN=Flatcar $build_id sysext signing key/" \
|| echo "Generating module signing key failed"
popd
}

# This is ugly.
# We need to sudo su - sdk -c so the SDK user gets a fresh login.
# 'sdk' is member of multiple groups, and plain docker USER only
Expand Down