]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
pcrextend,tpm2-util,tpm2-setup: gracefully skip NvPCR when TPM NV space is exhausted
authordongshengyuan <545258830@qq.com>
Wed, 24 Jun 2026 11:57:04 +0000 (19:57 +0800)
committerLennart Poettering <lennart@poettering.net>
Thu, 2 Jul 2026 19:49:18 +0000 (21:49 +0200)
Map TPM2_RC_NV_SPACE to -ENOBUFS in tpm2_define_nvpcr_nv_index() rather
than -ENOSPC, giving it a dedicated errno distinct from the -ENOSPC that
write_string_file_at() can return when /run is full — a different failure
that occurs after the NV index is already allocated on the TPM.

In extend_nvpcr_now(), propagate -ENOBUFS as-is so callers can handle it
in a nicer fashion. In vl_method_extend(), map it to the new varlink error
io.systemd.PCRExtend.NvPCRSpaceExhausted. In run(), handle -ENOBUFS
explicitly under --graceful and print an appropriate message. Update
tpm2-setup.c accordingly.

Fixes #42725
Signed-off-by: dongshengyuan <dongshengyuan@uniontech.com>
src/pcrextend/pcrextend.c
src/shared/tpm2-util.c
src/shared/varlink-io.systemd.PCRExtend.c
src/tpm2-setup/tpm2-setup.c

index 067cc92ff39169d20beec88ab9b45f765b51d1b6..782f863272627ac0403bfd5fb6b30fe79a6174b2 100644 (file)
@@ -382,6 +382,8 @@ static int extend_nvpcr_now(
                         return r;
 
                 r = tpm2_nvpcr_initialize(c, /* session= */ NULL, name, &anchor_secret);
+                if (r == -ENOBUFS)
+                        return r; /* NV space exhausted; let caller handle gracefully */
                 if (r < 0)
                         return log_error_errno(r, "Failed to extend NvPCR index '%s' with anchor secret: %m", name);
 
@@ -470,6 +472,8 @@ static int vl_method_extend(sd_varlink *link, sd_json_variant *parameters, sd_va
                 r = extend_nvpcr_now(p.nvpcr, extend_iovec->iov_base, extend_iovec->iov_len, p.event_type);
                 if (IN_SET(r, -ENOENT, -ENODEV))
                         return sd_varlink_error(link, "io.systemd.PCRExtend.NoSuchNvPCR", NULL);
+                if (r == -ENOBUFS)
+                        return sd_varlink_error(link, "io.systemd.PCRExtend.NvPCRSpaceExhausted", NULL);
         } else
                 r = extend_pcr_now(INDEX_TO_MASK(uint32_t, p.pcr), extend_iovec->iov_base, extend_iovec->iov_len, p.event_type);
         if (r < 0)
@@ -609,6 +613,10 @@ static int run(int argc, char *argv[]) {
                 log_notice_errno(r, "TPM2 cannot be used for measurement (no usable PCR bank, missing device, or missing crypto support), skipping gracefully.");
                 return EXIT_SUCCESS;
         }
+        if (arg_graceful && r == -ENOBUFS) {
+                log_notice_errno(r, "TPM NV index space is exhausted, NvPCR '%s' could not be initialized, skipping gracefully.", arg_nvpcr_name);
+                return EXIT_SUCCESS;
+        }
         if (r < 0)
                 return r;
 
index f0e86ad364005bdab86a0df489cf307685023684..3a9fbaa7e47e3eee24b7ea2905d18050589efa59 100644 (file)
@@ -7235,7 +7235,7 @@ static int tpm2_define_nvpcr_nv_index(
                         &public_info,
                         &new_handle->esys_handle);
         if (rc == TPM2_RC_NV_SPACE)
-                return log_debug_errno(SYNTHETIC_ERRNO(ENOSPC),
+                return log_debug_errno(SYNTHETIC_ERRNO(ENOBUFS),
                                        "NV index space on TPM exhausted, cannot allocate NvPCR.");
         if (rc == TPM2_RC_NV_DEFINED) {
                 log_debug("NV index 0x%" PRIu32 " already registered.", nv_index);
index d309330f405a6c53b5bc96249c97e6ab839bcf55..cf42bf9624697134afa0d377c527d0ddd61e4adf 100644 (file)
@@ -29,6 +29,7 @@ static SD_VARLINK_DEFINE_METHOD(
                 SD_VARLINK_DEFINE_INPUT_BY_TYPE(eventType, EventType, SD_VARLINK_NULLABLE));
 
 static SD_VARLINK_DEFINE_ERROR(NoSuchNvPCR);
+static SD_VARLINK_DEFINE_ERROR(NvPCRSpaceExhausted);
 
 SD_VARLINK_DEFINE_INTERFACE(
                 io_systemd_PCRExtend,
@@ -38,4 +39,6 @@ SD_VARLINK_DEFINE_INTERFACE(
                 &vl_method_Extend,
                 SD_VARLINK_SYMBOL_COMMENT("Event type to store in event log"),
                 &vl_type_EventType,
-                &vl_error_NoSuchNvPCR);
+                &vl_error_NoSuchNvPCR,
+                SD_VARLINK_SYMBOL_COMMENT("Space for NV indexes/NvPCRs exhausted, cannot measure."),
+                &vl_error_NvPCRSpaceExhausted);
index bb87cd902f7648478beac0521a8e67175dff3471..86cfdb5d2845b28c957f9d113d516e8693766eb9 100644 (file)
@@ -423,7 +423,7 @@ static int setup_nvpcr_one(
                                         LOG_MESSAGE("The TPM does not correctly support NV indexes in NT_EXTEND mode, unable to allocate NvPCR '%s': %m", name),
                                         LOG_MESSAGE_ID(SD_MESSAGE_TPM_NVPCR_UNSUPPORTED_STR));
         }
-        if (r == -ENOSPC) {
+        if (r == -ENOBUFS) {
                 /* The TPM's NV index space is exhausted. Remember this so we skip the remaining (less
                  * important) NvPCRs, and report it gracefully at the end rather than failing the boot.
                  * Logged at notice level, not error. */
@@ -549,7 +549,7 @@ static int setup_nvpcr(void) {
          * SuccessExitStatus= in the service unit file. */
         if (ret == -EOPNOTSUPP)
                 return EX_UNAVAILABLE;   /* e.g. no NvPCR support in TPM */
-        if (ret == -ENOSPC)
+        if (ret == -ENOBUFS)
                 return EX_CANTCREAT;     /* NV index space on TPM exhausted */
 
         return ret;