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 <aplanas@suse.com>
(cherry picked from commit 2994ca5226)
This commit is contained in:
Alberto Planas
2026-10-16 11:36:32 +01:00
committed by Luca Boccassi
parent a30858ebc3
commit 9c420c2f03
3 changed files with 16 additions and 3 deletions
+3 -1
View File
@@ -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");
}
+10 -2
View File
@@ -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;
}
+3
View File
@@ -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);