From 7fb6b9c2a279ff7b65f0111270094a83ad636ec9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kai=20L=C3=BCke?= Date: Thu, 2 Jul 2026 22:49:46 +0900 Subject: [PATCH] cryptsetup: Skip tokens with JSON parsing errors The plugin already continues on parsing errors but the fallback path not. The plugin swallows ENOMEM as well which is too much, though. Continue on JSON parsing errors by mapping them to EUCLEAN in cryptsetup_get_token_as_json and handle that in any call site, not just the TPM fallback path but also others. --- src/cryptenroll/cryptenroll-tpm2.c | 2 +- src/cryptenroll/cryptenroll.c | 2 +- src/cryptsetup/cryptsetup-pkcs11.c | 2 +- .../cryptsetup-tokens/cryptsetup-token-systemd-tpm2.c | 2 ++ src/shared/cryptsetup-fido2.c | 2 +- src/shared/cryptsetup-tpm2.c | 2 +- src/shared/cryptsetup-util.c | 3 ++- src/shared/cryptsetup-util.h | 3 +++ 8 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/cryptenroll/cryptenroll-tpm2.c b/src/cryptenroll/cryptenroll-tpm2.c index 8c64daa3c8..bc52a18c6a 100644 --- a/src/cryptenroll/cryptenroll-tpm2.c +++ b/src/cryptenroll/cryptenroll-tpm2.c @@ -39,7 +39,7 @@ static int search_policy_hash( sd_json_variant *w; r = cryptsetup_get_token_as_json(cd, token, "systemd-tpm2", &v); - if (IN_SET(r, -ENOENT, -EINVAL, -EMEDIUMTYPE)) + if (ERRNO_IS_NEG_CRYPTSETUP_TOKEN_SKIP(r)) continue; if (r < 0) return log_error_errno(r, "Failed to read JSON token data off disk: %m"); diff --git a/src/cryptenroll/cryptenroll.c b/src/cryptenroll/cryptenroll.c index 9211efef6f..6c3ee9b039 100644 --- a/src/cryptenroll/cryptenroll.c +++ b/src/cryptenroll/cryptenroll.c @@ -802,7 +802,7 @@ static int check_for_homed(struct crypt_device *cd) { for (int token = 0; token < sym_crypt_token_max(CRYPT_LUKS2); token++) { r = cryptsetup_get_token_as_json(cd, token, "systemd-homed", NULL); - if (IN_SET(r, -ENOENT, -EINVAL, -EMEDIUMTYPE)) + if (ERRNO_IS_NEG_CRYPTSETUP_TOKEN_SKIP(r)) continue; if (r < 0) return log_error_errno(r, "Failed to read JSON token data off disk: %m"); diff --git a/src/cryptsetup/cryptsetup-pkcs11.c b/src/cryptsetup/cryptsetup-pkcs11.c index b8534b15ef..df06b0c61d 100644 --- a/src/cryptsetup/cryptsetup-pkcs11.c +++ b/src/cryptsetup/cryptsetup-pkcs11.c @@ -110,7 +110,7 @@ int find_pkcs11_auto_data( int ks; r = cryptsetup_get_token_as_json(cd, token, "systemd-pkcs11", &v); - if (IN_SET(r, -ENOENT, -EINVAL, -EMEDIUMTYPE)) + if (ERRNO_IS_NEG_CRYPTSETUP_TOKEN_SKIP(r)) continue; if (r < 0) return log_error_errno(r, "Failed to read JSON token data off disk: %m"); diff --git a/src/cryptsetup/cryptsetup-tokens/cryptsetup-token-systemd-tpm2.c b/src/cryptsetup/cryptsetup-tokens/cryptsetup-token-systemd-tpm2.c index 20876cc71b..9c73463deb 100644 --- a/src/cryptsetup/cryptsetup-tokens/cryptsetup-token-systemd-tpm2.c +++ b/src/cryptsetup/cryptsetup-tokens/cryptsetup-token-systemd-tpm2.c @@ -87,6 +87,8 @@ _public_ int cryptsetup_token_open_pin( params = *(systemd_tpm2_plugin_params *)usrptr; r = sd_json_parse(json, SD_JSON_PARSE_MUST_BE_OBJECT, &v, /* reterr_line= */ NULL, /* reterr_column= */ NULL); + if (r == -ENOMEM) + return r; if (r < 0) { /* Remap to -EPERM so libcryptsetup keeps iterating past a broken token. */ (void) crypt_log_debug_errno(cd, r, "Token %d: failed to parse JSON data: %m", token); diff --git a/src/shared/cryptsetup-fido2.c b/src/shared/cryptsetup-fido2.c index 8655acba3e..ffc36c697a 100644 --- a/src/shared/cryptsetup-fido2.c +++ b/src/shared/cryptsetup-fido2.c @@ -167,7 +167,7 @@ int acquire_fido2_key_auto( int ks; r = cryptsetup_get_token_as_json(cd, token, "systemd-fido2", &v); - if (IN_SET(r, -ENOENT, -EINVAL, -EMEDIUMTYPE)) + if (ERRNO_IS_NEG_CRYPTSETUP_TOKEN_SKIP(r)) continue; if (r < 0) return log_error_errno(r, "Failed to read JSON token data off disk: %m"); diff --git a/src/shared/cryptsetup-tpm2.c b/src/shared/cryptsetup-tpm2.c index 7a0b9a236d..cd7a1506a1 100644 --- a/src/shared/cryptsetup-tpm2.c +++ b/src/shared/cryptsetup-tpm2.c @@ -313,7 +313,7 @@ int find_tpm2_auto_data( CLEANUP_ARRAY(policy_hash, n_policy_hash, iovec_array_free); r = cryptsetup_get_token_as_json(cd, token, "systemd-tpm2", &v); - if (IN_SET(r, -ENOENT, -EINVAL, -EMEDIUMTYPE)) + if (ERRNO_IS_NEG_CRYPTSETUP_TOKEN_SKIP(r)) continue; if (r < 0) return log_error_errno(r, "Failed to read JSON token data off disk: %m"); diff --git a/src/shared/cryptsetup-util.c b/src/shared/cryptsetup-util.c index 35a59721f8..531d2fcbc0 100644 --- a/src/shared/cryptsetup-util.c +++ b/src/shared/cryptsetup-util.c @@ -164,6 +164,7 @@ int cryptsetup_get_token_as_json( * -EINVAL → token index out of range or "type" field missing * -ENOENT → token doesn't exist * -EMEDIUMTYPE → "verify_type" specified and doesn't match token's type + * -EUCLEAN → token JSON data cannot be parsed */ r = sym_crypt_token_json_get(cd, idx, &text); @@ -172,7 +173,7 @@ int cryptsetup_get_token_as_json( r = sd_json_parse(text, 0, &v, NULL, NULL); if (r < 0) - return r; + return r == -ENOMEM ? r : -EUCLEAN; /* Report unparseable token data in a single way for callers to skip */ if (verify_type) { sd_json_variant *w; diff --git a/src/shared/cryptsetup-util.h b/src/shared/cryptsetup-util.h index 6e9c95aa9e..1c1e122e75 100644 --- a/src/shared/cryptsetup-util.h +++ b/src/shared/cryptsetup-util.h @@ -91,6 +91,9 @@ void cryptsetup_enable_logging(struct crypt_device *cd); int cryptsetup_set_minimal_pbkdf(struct crypt_device *cd); int cryptsetup_get_token_as_json(struct crypt_device *cd, int idx, const char *verify_type, sd_json_variant **ret); +/* Errors cryptsetup_get_token_as_json() returns for a token that is absent, of a different type, or + * unparseable, and callers should keep iterating other tokens. */ +#define ERRNO_IS_NEG_CRYPTSETUP_TOKEN_SKIP(r) IN_SET(r, -ENOENT, -EINVAL, -EMEDIUMTYPE, -EUCLEAN) int cryptsetup_add_token_json(struct crypt_device *cd, sd_json_variant *v); int cryptsetup_get_volume_key_prefix(struct crypt_device *cd, const char *volume_name, char **ret); int cryptsetup_get_volume_key_id(struct crypt_device *cd, const char *volume_name, const void *volume_key,