]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
cryptsetup: Skip tokens with JSON parsing errors
authorKai Lüke <kai@amutable.com>
Thu, 2 Jul 2026 13:49:46 +0000 (22:49 +0900)
committerKai Lüke <pothos@users.noreply.github.com>
Fri, 10 Jul 2026 06:07:47 +0000 (08:07 +0200)
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
src/cryptenroll/cryptenroll.c
src/cryptsetup/cryptsetup-pkcs11.c
src/cryptsetup/cryptsetup-tokens/cryptsetup-token-systemd-tpm2.c
src/shared/cryptsetup-fido2.c
src/shared/cryptsetup-tpm2.c
src/shared/cryptsetup-util.c
src/shared/cryptsetup-util.h

index 8c64daa3c882e0c3c11dfc82b2886c08ae06a5c2..bc52a18c6ab7f9d032e29558f9abcaf4ba7bb7a3 100644 (file)
@@ -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");
index 9211efef6feb792bdd75e2a100030a1c4ef73f58..6c3ee9b039aac60ed1e1b9ea74e2d891ba60fe06 100644 (file)
@@ -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");
index b8534b15ef3dea7c4c1427f294b9de3394ead508..df06b0c61d22b151ee44e605235592f91cb17366 100644 (file)
@@ -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");
index 20876cc71b6eef3ff2957e0f137e3a28fd8ffc37..9c73463debe026c401528fbae65bddb08c576346 100644 (file)
@@ -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);
index 8655acba3e726d8760b4ac88a5f227ebceaf31ed..ffc36c697a267d46f0337a388e98b405bfc60ce5 100644 (file)
@@ -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");
index 7a0b9a236da2bb05d4253fdd78bf088c7b76b31a..cd7a1506a1d12af03b82c1e98cd77a8b227c2a61 100644 (file)
@@ -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");
index 35a59721f88427e967e8d5ff056e1ecca6708ab7..531d2fcbc017915193331c08a988003e8135c4d1 100644 (file)
@@ -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;
index 6e9c95aa9e8f6b26245f3f2c64212895ad94b7d8..1c1e122e753e662cbbdad10dfcefa975281256aa 100644 (file)
@@ -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,