From b3dbe5459ca2c62ea87b3cf250f5aa191852176b Mon Sep 17 00:00:00 2001 From: Kevin Wang Date: Thu, 24 Sep 2026 21:59:49 -0700 Subject: [PATCH] fix(os/mkosi): mask systemd's TPM SRK setup units On a measured-UKI boot (GCP), systemd-tpm2-setup.service tries to write the SRK public key to /var/lib/systemd/tpm2-srk-public-key.pem. It runs before sysinit.target, but the writable /var overlays come from dstack-volatile-binds.service, which the unit does not order after, so it hits the read-only root, fails, and leaves the system degraded. Nothing in dstack uses systemd's SRK: the TPM key provider creates its own primary key at 0x81000100 through tpm2-tss, and no image component uses systemd-creds or systemd-cryptenroll with a TPM. The Yocto image builds systemd without TPM support, so these units never existed there. Mask both SRK units instead of giving them a writable path, which would only keep an unused object persisted in the vTPM. Signed-off-by: Kevin Wang --- .../etc/systemd/system/systemd-tpm2-setup-early.service | 1 + .../etc/systemd/system/systemd-tpm2-setup.service | 1 + os/mkosi/tests/acceptance.sh | 9 +++++++++ 3 files changed, 11 insertions(+) create mode 120000 os/mkosi/mkosi.skeleton/etc/systemd/system/systemd-tpm2-setup-early.service create mode 120000 os/mkosi/mkosi.skeleton/etc/systemd/system/systemd-tpm2-setup.service diff --git a/os/mkosi/mkosi.skeleton/etc/systemd/system/systemd-tpm2-setup-early.service b/os/mkosi/mkosi.skeleton/etc/systemd/system/systemd-tpm2-setup-early.service new file mode 120000 index 000000000..dc1dc0cde --- /dev/null +++ b/os/mkosi/mkosi.skeleton/etc/systemd/system/systemd-tpm2-setup-early.service @@ -0,0 +1 @@ +/dev/null \ No newline at end of file diff --git a/os/mkosi/mkosi.skeleton/etc/systemd/system/systemd-tpm2-setup.service b/os/mkosi/mkosi.skeleton/etc/systemd/system/systemd-tpm2-setup.service new file mode 120000 index 000000000..dc1dc0cde --- /dev/null +++ b/os/mkosi/mkosi.skeleton/etc/systemd/system/systemd-tpm2-setup.service @@ -0,0 +1 @@ +/dev/null \ No newline at end of file diff --git a/os/mkosi/tests/acceptance.sh b/os/mkosi/tests/acceptance.sh index 44fb408ef..046115165 100755 --- a/os/mkosi/tests/acceptance.sh +++ b/os/mkosi/tests/acceptance.sh @@ -120,6 +120,15 @@ grep -q '^WatchdogSec=' "$gw_unit" || { echo 'dstack-gateway-checker.service must set WatchdogSec'; exit 1; } test ! -e "$D/../common/rootfs/wg-checker.sh" test ! -e "$D/../common/rootfs/wg-checker.service" +# systemd-tpm2-setup writes the SRK public key to /var/lib/systemd before the +# /var overlays exist, so on a measured-UKI boot it fails on the read-only root +# and leaves the system degraded. Nothing in dstack uses systemd's SRK (the TPM +# key provider has its own primary key), and the Yocto systemd has no TPM +# support, so both SRK units are masked instead of given a writable path. +for unit in systemd-tpm2-setup.service systemd-tpm2-setup-early.service; do + [[ $(readlink "$D/mkosi.skeleton/etc/systemd/system/$unit") == /dev/null ]] || { + echo "$unit must be masked in the image skeleton"; exit 1; } +done # systemd enables any unit that matches no preset rule, so the enable list is # only meaningful with a terminal disable. Without it, every package pulled in # by Packages= would start at boot with no diff to 80-dstack.preset.