]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
core: if we cannot decode a TPM credential skip over it for ImportCredential=
authorLennart Poettering <lennart@poettering.net>
Wed, 17 Sep 2025 08:37:31 +0000 (10:37 +0200)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Fri, 10 Oct 2025 08:36:47 +0000 (10:36 +0200)
let's skip over credentials we cannot decode when they are found with
ImportCredential=. When installing an OS on some disk and using that
disk on a different machine than assumed we'll otherwise end up with a
broken boot, because the credentials cannot be decoded when starting
systemd-firstboot. Let's handle this somewhat gracefully.

This leaves handling for LoadCredential=/SetCredential= as it is (i.e.
failure to decrypt results in service failure), because it is a lot more
explicit and focussed as opposed to ImportCredentials= which looks
everywhere, uses globs and so on and is hence very vague and unfocussed.

Fixes: #34740
(cherry picked from commit 4be269563db777bb30f2609b3d4f5180fe9e2d2a)

man/systemd.exec.xml
src/core/exec-credential.c

index 0afde99ee6fe24ce8163f37780b65d412390f337..c0c147045e2ca06a2a68d80e376794596111eeec 100644 (file)
@@ -3915,6 +3915,13 @@ StandardInputData=V2XigLJyZSBubyBzdHJhbmdlcnMgdG8gbG92ZQpZb3Uga25vdyB0aGUgcnVsZX
         <varname>LoadCredential=</varname> and <varname>LoadCredentialEncrypted=</varname> take priority over
         credentials found by <varname>ImportCredential=</varname>.</para>
 
+        <para>Note that if decryption or authentication of a credential picked up as result of
+        <varname>ImportCredential=</varname> fails it will be skipped gracefully (a warning is generated, but
+        the credential will not be made available to the invoked service). This is different for those
+        configured via
+        <varname>SetCredentialEncrypted=</varname>/<varname>LoadCredentialEncrypted=</varname>, where failed
+        decryption/authentication will result in service failure.</para>
+
         <xi:include href="version-info.xml" xpointer="v254"/></listitem>
       </varlistentry>
 
index 5e2bc8edd975241d8db04631c4c1575cb1f106b1..ae5a32fb2c9ad39e97a66014e0a9d3cc1f200044 100644 (file)
@@ -468,7 +468,8 @@ static int maybe_decrypt_and_write_credential(
                 struct load_cred_args *args,
                 const char *id,
                 const char *data,
-                size_t size) {
+                size_t size,
+                bool graceful) {
 
         _cleanup_(iovec_done_erase) struct iovec plaintext = {};
         size_t add;
@@ -522,8 +523,14 @@ static int maybe_decrypt_and_write_credential(
                 default:
                         assert_not_reached();
                 }
-                if (r < 0)
+                if (r < 0) {
+                        if (graceful) {
+                                log_warning_errno(r, "Unable to decrypt credential '%s', skipping.", id);
+                                return 0;
+                        }
+
                         return r;
+                }
 
                 data = plaintext.iov_base;
                 size = plaintext.iov_len;
@@ -612,7 +619,7 @@ static int load_credential_glob(
                         if (r < 0)
                                 return log_debug_errno(r, "Failed to read credential '%s': %m", *p);
 
-                        r = maybe_decrypt_and_write_credential(args, fn, data, size);
+                        r = maybe_decrypt_and_write_credential(args, fn, data, size, /* graceful= */ true);
                         if (r < 0)
                                 return r;
                 }
@@ -737,7 +744,7 @@ static int load_credential(
         if (r < 0)
                 return log_debug_errno(r, "Failed to read credential '%s': %m", path);
 
-        return maybe_decrypt_and_write_credential(args, id, data, size);
+        return maybe_decrypt_and_write_credential(args, id, data, size, /* graceful= */ true);
 }
 
 static int load_cred_recurse_dir_cb(
@@ -874,10 +881,11 @@ static int acquire_credentials(
 
                 args.encrypted = false;
 
-                r = load_credential_glob(&args,
-                                         ic,
-                                         search_path,
-                                         READ_FULL_FILE_SECURE|READ_FULL_FILE_FAIL_WHEN_LARGER);
+                r = load_credential_glob(
+                                &args,
+                                ic,
+                                search_path,
+                                READ_FULL_FILE_SECURE|READ_FULL_FILE_FAIL_WHEN_LARGER);
                 if (r < 0)
                         return r;
 
@@ -889,10 +897,11 @@ static int acquire_credentials(
 
                 args.encrypted = true;
 
-                r = load_credential_glob(&args,
-                                         ic,
-                                         search_path,
-                                         READ_FULL_FILE_SECURE|READ_FULL_FILE_FAIL_WHEN_LARGER|READ_FULL_FILE_UNBASE64);
+                r = load_credential_glob(
+                                &args,
+                                ic,
+                                search_path,
+                                READ_FULL_FILE_SECURE|READ_FULL_FILE_FAIL_WHEN_LARGER|READ_FULL_FILE_UNBASE64);
                 if (r < 0)
                         return r;
         }
@@ -910,7 +919,7 @@ static int acquire_credentials(
                 if (errno != ENOENT)
                         return log_debug_errno(errno, "Failed to test if credential %s exists: %m", sc->id);
 
-                r = maybe_decrypt_and_write_credential(&args, sc->id, sc->data, sc->size);
+                r = maybe_decrypt_and_write_credential(&args, sc->id, sc->data, sc->size, /* graceful= */ false);
                 if (r < 0)
                         return r;
         }