From 9c420c2f031e7849b0420641e93abde5d1bb4ece Mon Sep 17 00:00:00 2001 From: Alberto Planas Date: Mon, 14 Sep 2026 10:41:05 +0200 Subject: [PATCH] creds: don't report a malformed PCR signature file as changing PCRs tpm2_load_pcr_signature() propagates the JSON parser's errno, and the parser reports a string that is not valid UTF-8 as -EUCLEAN. With EUCLEAN now mapping to io.systemd.Credentials.PCRsKeptChanging, such a file would be reported as if a PCR were being extended continuously. Translate it where it originates, so that the errno stays single valued for every caller of tpm2_load_pcr_signature() and not only for the creds one: a signature file that cannot be parsed is -EBADMSG, whichever way it is malformed. A syntax error used to come out as -EINVAL, which matched nothing on the way out either. Signed-off-by: Alberto Planas (cherry picked from commit 2994ca5226458678650734f99590fdff564fa7e9) --- src/shared/creds-util.c | 4 +++- src/shared/tpm2-util.c | 12 ++++++++++-- src/shared/tpm2-util.h | 3 +++ 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/shared/creds-util.c b/src/shared/creds-util.c index 766da2c9d5..2eefb7f575 100644 --- a/src/shared/creds-util.c +++ b/src/shared/creds-util.c @@ -1362,7 +1362,7 @@ int decrypt_credential_and_warn( /* Relevant error codes: * - * -EBADMSG → Corrupted file + * -EBADMSG → Corrupted file, or unparsable PCR signature file * -EOPNOTSUPP → Unsupported file type (could be: requires TPM but we have no TPM) * -EHOSTDOWN → Need PCR signature file, but couldn't find it * -EHWPOISON → Attempt to unlock with NULL key and either CREDENTIAL_ALLOW_REFUSE is on, or CREDENTIAL_ALLOW_NULL is off, but the system has a TPM and SecureBoot is on @@ -1386,6 +1386,8 @@ int decrypt_credential_and_warn( r = tpm2_load_pcr_signature(tpm2_signature_path, &signature_json); if (r == -ENOENT) return log_error_errno(SYNTHETIC_ERRNO(EHOSTDOWN), "Couldn't find PCR signature file: %m"); + if (r == -EBADMSG) + return log_error_errno(r, "PCR signature file is malformed."); if (r < 0) return log_error_errno(r, "Failed to load PCR signature: %m"); } diff --git a/src/shared/tpm2-util.c b/src/shared/tpm2-util.c index 8d6a0c415b..2499976dc2 100644 --- a/src/shared/tpm2-util.c +++ b/src/shared/tpm2-util.c @@ -12035,8 +12035,16 @@ int tpm2_load_pcr_signature(const char *path, sd_json_variant **ret) { return log_debug_errno(r, "Failed to find TPM PCR signature file '%s': %m", path); r = sd_json_parse_file(f, discovered_path, 0, ret, NULL, NULL); - if (r < 0) - return log_debug_errno(r, "Failed to parse TPM PCR signature JSON object '%s': %m", discovered_path); + if (r == -ENOMEM) + return log_oom_debug(); + if (r < 0) { + log_debug_errno(r, "Failed to parse TPM PCR signature JSON object '%s': %m", discovered_path); + + /* Don't propagate the parser's errno: it reports a string that is not valid UTF-8 as + * -EUCLEAN, and to our callers that errno means "a PCR kept being extended". Report a + * malformed file as such instead, whichever way it is malformed. */ + return -EBADMSG; + } return 0; } diff --git a/src/shared/tpm2-util.h b/src/shared/tpm2-util.h index 8c0b136b08..475ac54014 100644 --- a/src/shared/tpm2-util.h +++ b/src/shared/tpm2-util.h @@ -624,6 +624,9 @@ int tpm2_parse_pcr_argument(const char *arg, Tpm2PCRValue **ret_pcr_values, size int tpm2_parse_pcr_argument_append(const char *arg, Tpm2PCRValue **pcr_values, size_t *n_pcr_values); int tpm2_parse_pcr_argument_to_mask(const char *arg, uint32_t *mask); +/* Note: tpm2_load_pcr_signature() returns -ENOENT if there is no such file, and -EBADMSG if there is one but + * it cannot be parsed. In particular it does not propagate the JSON parser's -EUCLEAN, which means something + * else to the TPM2 callers of this. */ int tpm2_load_pcr_signature(const char *path, sd_json_variant **ret); int tpm2_load_pcr_public_key(const char *path, void **ret_pubkey, size_t *ret_pubkey_size);