From 64fd94faa0c73c3f64e05674d106893dc209c256 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 3 Mar 2026 21:51:38 +0100 Subject: [PATCH] tpm2-setup: don't fail service on two more types of failures Let's bubble up failures all the way until they reach the services, but then let's carefully gracefully handle some of them, that are about issues not immediately actionable to the admin, even if they are potentially quite problematic. --- src/tpm2-setup/tpm2-setup.c | 24 ++++++++++++++++------- units/systemd-tpm2-setup-early.service.in | 4 ++++ units/systemd-tpm2-setup.service.in | 4 ++++ 3 files changed, 25 insertions(+), 7 deletions(-) diff --git a/src/tpm2-setup/tpm2-setup.c b/src/tpm2-setup/tpm2-setup.c index 3eed095d22..d243f199e9 100644 --- a/src/tpm2-setup/tpm2-setup.c +++ b/src/tpm2-setup/tpm2-setup.c @@ -453,7 +453,7 @@ static int setup_nvpcr_one( static int setup_nvpcr(void) { _cleanup_(setup_nvpcr_context_done) SetupNvPCRContext c = {}; - int r = 0; + int r; _cleanup_strv_free_ char **l = NULL; r = conf_files_list_nulstr( @@ -478,13 +478,11 @@ static int setup_nvpcr(void) { RET_GATHER(ret, setup_nvpcr_one(&c, *i)); } - if (c.n_already > 0 && c.n_anchored == 0 && !arg_early) { + if (c.n_already > 0 && c.n_anchored == 0 && !arg_early) /* If we didn't anchor anything right now, but we anchored something earlier, then it might * have happened in the initrd, and thus the anchor ID was not committed to /var/ or the ESP * yet. Hence, let's explicitly do so now, to catch up. */ - RET_GATHER(ret, tpm2_nvpcr_acquire_anchor_secret(/* ret= */ NULL, /* sync_secondary= */ true)); - } if (c.n_failed > 0) log_warning("%zu NvPCRs failed to initialize, proceeding anyway.", c.n_failed); @@ -499,6 +497,13 @@ static int setup_nvpcr(void) { else if (c.n_failed == 0) log_debug("No NvPCRs defined, nothing initialized."); + /* Turn some errors into recognizable ones, which we can catch with + * SuccessExitStatus= in the service unit file. */ + if (ret == -EOPNOTSUPP) + return EX_UNAVAILABLE; /* e.g. no NvPCR support in TPM */ + if (ret == -ENOSPC) + return EX_CANTCREAT; /* NV index space on TPM exhausted */ + return ret; } @@ -518,10 +523,15 @@ static int run(int argc, char *argv[]) { umask(0022); + /* Execute both jobs, and then return unlisted errors preferably, and listed errors + * (i.e. EX_UNAVAILABLE, EX_CANTCREAT, EX_PROTOCOL) otherwise. */ r = setup_srk(); - RET_GATHER(r, setup_nvpcr()); - - return r; + int k = setup_nvpcr(); + if (r < 0) + return r; + if (k < 0) + return k; + return r != EXIT_SUCCESS ? r : k; } DEFINE_MAIN_FUNCTION_WITH_POSITIVE_FAILURE(run); diff --git a/units/systemd-tpm2-setup-early.service.in b/units/systemd-tpm2-setup-early.service.in index bd69c9de7a..ce1ee94cc4 100644 --- a/units/systemd-tpm2-setup-early.service.in +++ b/units/systemd-tpm2-setup-early.service.in @@ -24,3 +24,7 @@ ExecStart={{LIBEXECDIR}}/systemd-tpm2-setup --early=yes --graceful # The tool returns EX_PROTOCOL if the TPM cannot be accessed due to an authorization failure and we can't generate an SRK. SuccessExitStatus=PROTOCOL +# The tool returns EX_UNAVAILABLE if some key functionality (e.g. NvPCR) support is not available in the TPM device. +SuccessExitStatus=UNAVAILABLE +# The tool returns EX_CANTCREAT if the NV index space is exhausted. +SuccessExitStatus=CANTCREAT diff --git a/units/systemd-tpm2-setup.service.in b/units/systemd-tpm2-setup.service.in index a81b028214..dff516832d 100644 --- a/units/systemd-tpm2-setup.service.in +++ b/units/systemd-tpm2-setup.service.in @@ -25,3 +25,7 @@ ExecStart={{LIBEXECDIR}}/systemd-tpm2-setup --graceful # The tool returns EX_PROTOCOL if the TPM cannot be accessed due to an authorization failure and we can't generate an SRK. SuccessExitStatus=PROTOCOL +# The tool returns EX_UNAVAILABLE if some key functionality (e.g. NvPCR) support is not available in the TPM device. +SuccessExitStatus=UNAVAILABLE +# The tool returns EX_CANTCREAT if the NV index space is exhausted. +SuccessExitStatus=CANTCREAT