From: Kai Lüke Date: Thu, 2 Jul 2026 13:49:46 +0000 (+0900) Subject: cryptsetup: Skip tokens with JSON parsing errors X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=7fb6b9c2a279ff7b65f0111270094a83ad636ec9;p=thirdparty%2Fsystemd.git 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. --- diff --git a/src/cryptenroll/cryptenroll-tpm2.c b/src/cryptenroll/cryptenroll-tpm2.c index 8c64daa3c88..bc52a18c6ab 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 9211efef6fe..6c3ee9b039a 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 b8534b15ef3..df06b0c61d2 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 20876cc71b6..9c73463debe 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 8655acba3e7..ffc36c697a2 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 7a0b9a236da..cd7a1506a1d 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 35a59721f88..531d2fcbc01 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 6e9c95aa9e8..1c1e122e753 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,