units: harden systemd-tpm2-swtpm.service

Lock down the software TPM service: restrict the runtime directory (which
holds the AES key sealing swtpm's state) to 0700, and apply the usual
sandboxing (NoNewPrivileges, MemoryDenyWriteExecute, ProtectSystem-adjacent
Protect*/Restrict* knobs, PrivateNetwork, PrivateTmp, a @system-service
syscall filter, etc.).

A few common knobs can't be used here: the service must keep CAP_SYS_ADMIN
(needed for the ioctl that creates the vtpm proxy device on /dev/vtpmx),
and it needs runtime access to the ESP and its backing block device at a
path only known at runtime, which rules out PrivateDevices=, DevicePolicy=,
ProtectSystem= and User=/DynamicUser=.

Signed-off-by: Paul Meyer <katexochen0@gmail.com>
This commit is contained in:
Paul Meyer
2026-06-25 09:39:55 +02:00
parent df2baac2b9
commit 2f1c3b8afb
+24 -2
View File
@@ -18,10 +18,32 @@ After=modprobe@tpm_vtpm_proxy.service
Before=tpm2.target sysinit.target shutdown.target
[Service]
Type=notify
RuntimeDirectory=systemd/swtpm
CapabilityBoundingSet=CAP_SYS_ADMIN
ExecStart={{LIBEXECDIR}}/systemd-tpm2-swtpm
# Write out volatile state (so that we can read it back after the initrd transition
ExecStop=swtpm_ioctl --unix %t/systemd/swtpm/socket -v
# Initiate graceful shutdown
ExecStop=swtpm_ioctl --unix %t/systemd/swtpm/socket -s
LockPersonality=yes
MemoryDenyWriteExecute=yes
NoNewPrivileges=yes
PrivateNetwork=yes
PrivateTmp=disconnected
ProtectControlGroups=yes
ProtectHome=yes
ProtectHostname=yes
ProtectKernelLogs=yes
ProtectKernelModules=yes
ProtectKernelTunables=yes
ProtectProc=invisible
RestrictAddressFamilies=AF_UNIX AF_NETLINK
RestrictNamespaces=yes
RestrictRealtime=yes
RestrictSUIDSGID=yes
RuntimeDirectory=systemd/swtpm
RuntimeDirectoryMode=0700
SystemCallArchitectures=native
SystemCallErrorNumber=EPERM
SystemCallFilter=@system-service
Type=notify
UMask=0077