From 27b7fb9b2065b4da56f532aca103a04811d70450 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 28 May 2026 11:41:45 +0200 Subject: [PATCH] pcrlock: recompute PCR policy on completed system update Bind the io.systemd.SysUpdate.Notify.OnCompletedUpdate() method in the pcrlock Varlink server and hook a socket into /run/systemd/sysupdate/notify/ via systemd-sysupdate-notify-pcrlock.socket, enabled by default via the preset. When sysupdate signals a completed update, we unconditionally re-run make-policy, since the set of measured components may have changed. --- presets/90-systemd.preset | 1 + src/pcrlock/pcrlock.c | 36 ++++++++++++++++--- units/meson.build | 8 +++++ units/systemd-sysupdate-notify-pcrlock.socket | 29 +++++++++++++++ ...stemd-sysupdate-notify-pcrlock@.service.in | 20 +++++++++++ 5 files changed, 89 insertions(+), 5 deletions(-) create mode 100644 units/systemd-sysupdate-notify-pcrlock.socket create mode 100644 units/systemd-sysupdate-notify-pcrlock@.service.in diff --git a/presets/90-systemd.preset b/presets/90-systemd.preset index 85108dcdd5..ace5d6d980 100644 --- a/presets/90-systemd.preset +++ b/presets/90-systemd.preset @@ -40,6 +40,7 @@ enable systemd-report-sign-tsm.socket enable systemd-report.socket enable systemd-resolved.service enable systemd-sysext.service +enable systemd-sysupdate-notify-pcrlock.socket enable systemd-timesyncd.service enable systemd-tpm2-clear.service enable systemd-userdbd.socket diff --git a/src/pcrlock/pcrlock.c b/src/pcrlock/pcrlock.c index 5aba4e966b..53b9b8a155 100644 --- a/src/pcrlock/pcrlock.c +++ b/src/pcrlock/pcrlock.c @@ -61,6 +61,7 @@ #include "unit-name.h" #include "utf8.h" #include "varlink-io.systemd.PCRLock.h" +#include "varlink-io.systemd.SysUpdate.Notify.h" #include "varlink-util.h" #include "verbs.h" @@ -5467,6 +5468,27 @@ static int vl_method_remove_policy(sd_varlink *link, sd_json_variant *parameters return sd_varlink_reply(link, NULL); } +static int vl_method_on_completed_update(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata) { + int r; + + assert(link); + + /* Triggered by systemd-sysupdate after an update completed. We deliberately ignore all parameters + * (we don't even dispatch them) and simply recompute the PCR policy unconditionally, since the set + * of measured components might have changed. */ + + /* Only honour update notifications if they come from root */ + r = varlink_check_privileged_peer(link); + if (r < 0) + return r; + + r = make_policy(/* force= */ false, /* recovery_pin_mode= */ RECOVERY_PIN_HIDE); + if (r < 0) + return r; + + return sd_varlink_reply(link, NULL); +} + static int run(int argc, char *argv[]) { int r; @@ -5496,15 +5518,19 @@ static int run(int argc, char *argv[]) { if (r < 0) return log_error_errno(r, "Failed to allocate Varlink server: %m"); - r = sd_varlink_server_add_interface(varlink_server, &vl_interface_io_systemd_PCRLock); + r = sd_varlink_server_add_interface_many( + varlink_server, + &vl_interface_io_systemd_PCRLock, + &vl_interface_io_systemd_SysUpdate_Notify); if (r < 0) - return log_error_errno(r, "Failed to add Varlink interface: %m"); + return log_error_errno(r, "Failed to add Varlink interfaces: %m"); r = sd_varlink_server_bind_method_many( varlink_server, - "io.systemd.PCRLock.ReadEventLog", vl_method_read_event_log, - "io.systemd.PCRLock.MakePolicy", vl_method_make_policy, - "io.systemd.PCRLock.RemovePolicy", vl_method_remove_policy); + "io.systemd.PCRLock.ReadEventLog", vl_method_read_event_log, + "io.systemd.PCRLock.MakePolicy", vl_method_make_policy, + "io.systemd.PCRLock.RemovePolicy", vl_method_remove_policy, + "io.systemd.SysUpdate.Notify.OnCompletedUpdate", vl_method_on_completed_update); if (r < 0) return log_error_errno(r, "Failed to bind Varlink methods: %m"); diff --git a/units/meson.build b/units/meson.build index f261fded6f..f2e1006bad 100644 --- a/units/meson.build +++ b/units/meson.build @@ -706,6 +706,14 @@ units = [ 'conditions' : ['ENABLE_BOOTLOADER', 'HAVE_OPENSSL', 'HAVE_TPM2'], 'symlinks' : ['sockets.target.wants/'], }, + { + 'file' : 'systemd-sysupdate-notify-pcrlock@.service.in', + 'conditions' : ['ENABLE_BOOTLOADER', 'HAVE_OPENSSL', 'HAVE_TPM2'], + }, + { + 'file' : 'systemd-sysupdate-notify-pcrlock.socket', + 'conditions' : ['ENABLE_BOOTLOADER', 'HAVE_OPENSSL', 'HAVE_TPM2'], + }, { 'file' : 'systemd-portabled.service.in', 'conditions' : ['ENABLE_PORTABLED'], diff --git a/units/systemd-sysupdate-notify-pcrlock.socket b/units/systemd-sysupdate-notify-pcrlock.socket new file mode 100644 index 0000000000..6b26911bcc --- /dev/null +++ b/units/systemd-sysupdate-notify-pcrlock.socket @@ -0,0 +1,29 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later +# +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. + +[Unit] +Description=Recompute TPM PCR Policy on Completed System Update +Documentation=man:systemd-pcrlock(8) +DefaultDependencies=no +After=tpm2.target +Before=sockets.target +ConditionSecurity=measured-uki + +[Socket] +ListenStream=/run/systemd/sysupdate/notify/io.systemd.PCRLock +FileDescriptorName=varlink +SocketMode=0644 +Accept=yes +MaxConnectionsPerSource=16 +XAttrEntryPoint=user.varlink=entrypoint +XAttrListen=user.varlink=listen +XAttrAccept=user.varlink=server + +[Install] +WantedBy=sockets.target diff --git a/units/systemd-sysupdate-notify-pcrlock@.service.in b/units/systemd-sysupdate-notify-pcrlock@.service.in new file mode 100644 index 0000000000..50108b6f07 --- /dev/null +++ b/units/systemd-sysupdate-notify-pcrlock@.service.in @@ -0,0 +1,20 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later +# +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. + +[Unit] +Description=Recompute TPM PCR Policy on Completed System Update +Documentation=man:systemd-pcrlock(8) +DefaultDependencies=no +Conflicts=shutdown.target +After=systemd-tpm2-setup.service +After=systemd-remount-fs.service var.mount +Before=shutdown.target + +[Service] +ExecStart={{LIBEXECDIR}}/systemd-pcrlock --location=770